data handler improves, written test for nfproxy, new option on parsing fail
This commit is contained in:
@@ -75,12 +75,9 @@ def handle_packet(glob: dict) -> None:
|
||||
|
||||
cache_call = {} # Cache of the data handler calls
|
||||
cache_call[RawPacket] = internal_data.current_pkt
|
||||
|
||||
final_result = Action.ACCEPT
|
||||
|
||||
result = PacketHandlerResult(glob)
|
||||
|
||||
func_name = None
|
||||
mangled_packet = None
|
||||
for filter in internal_data.filter_call_info:
|
||||
final_params = []
|
||||
skip_call = False
|
||||
@@ -116,24 +113,37 @@ def handle_packet(glob: dict) -> None:
|
||||
if skip_call:
|
||||
continue
|
||||
|
||||
res = context_call(glob, filter.func, *final_params)
|
||||
|
||||
if res is None:
|
||||
continue #ACCEPTED
|
||||
if not isinstance(res, Action):
|
||||
raise Exception(f"Invalid return type {type(res)} for function {filter.name}")
|
||||
if res == Action.MANGLE:
|
||||
mangled_packet = internal_data.current_pkt.raw_packet
|
||||
if res != Action.ACCEPT:
|
||||
func_name = filter.name
|
||||
final_result = res
|
||||
break
|
||||
# Create an iterator with all the calls to be done
|
||||
def try_to_call(params:list):
|
||||
is_base_call = True
|
||||
for i in range(len(params)):
|
||||
if isinstance(params[i], list):
|
||||
new_params = params.copy()
|
||||
for ele in params[i]:
|
||||
new_params[i] = ele
|
||||
for ele in try_to_call(new_params):
|
||||
yield ele
|
||||
is_base_call = False
|
||||
break
|
||||
if is_base_call:
|
||||
yield context_call(glob, filter.func, *params)
|
||||
|
||||
for res in try_to_call(final_params):
|
||||
if res is None:
|
||||
continue #ACCEPTED
|
||||
if not isinstance(res, Action):
|
||||
raise Exception(f"Invalid return type {type(res)} for function {filter.name}")
|
||||
if res == Action.MANGLE:
|
||||
result.matched_by = filter.name
|
||||
result.mangled_packet = internal_data.current_pkt.raw_packet
|
||||
result.action = Action.MANGLE
|
||||
elif res != Action.ACCEPT:
|
||||
result.matched_by = filter.name
|
||||
result.action = res
|
||||
result.mangled_packet = None
|
||||
return result.set_result()
|
||||
|
||||
result.action = final_result
|
||||
result.matched_by = func_name
|
||||
result.mangled_packet = mangled_packet
|
||||
|
||||
return result.set_result()
|
||||
return result.set_result() # Will be MANGLE or ACCEPT
|
||||
|
||||
|
||||
def compile(glob:dict) -> None:
|
||||
@@ -148,13 +158,12 @@ def compile(glob:dict) -> None:
|
||||
|
||||
if "FGEX_STREAM_MAX_SIZE" in glob and int(glob["FGEX_STREAM_MAX_SIZE"]) > 0:
|
||||
internal_data.stream_max_size = int(glob["FGEX_STREAM_MAX_SIZE"])
|
||||
else:
|
||||
internal_data.stream_max_size = 1*8e20 # 1MB default value
|
||||
|
||||
if "FGEX_FULL_STREAM_ACTION" in glob and isinstance(glob["FGEX_FULL_STREAM_ACTION"], FullStreamAction):
|
||||
internal_data.full_stream_action = glob["FGEX_FULL_STREAM_ACTION"]
|
||||
else:
|
||||
internal_data.full_stream_action = FullStreamAction.FLUSH
|
||||
|
||||
if "FGEX_INVALID_ENCODING_ACTION" in glob and isinstance(glob["FGEX_INVALID_ENCODING_ACTION"], Action):
|
||||
internal_data.invalid_encoding_action = glob["FGEX_INVALID_ENCODING_ACTION"]
|
||||
|
||||
PacketHandlerResult(glob).reset_result()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from firegex.nfproxy.internals.models import FilterHandler
|
||||
from firegex.nfproxy.internals.models import FullStreamAction
|
||||
from firegex.nfproxy.internals.models import FullStreamAction, ExceptionAction
|
||||
|
||||
class RawPacket:
|
||||
"class rapresentation of the nfqueue packet sent in python context by the c++ core"
|
||||
@@ -120,23 +120,39 @@ class DataStreamCtx:
|
||||
@property
|
||||
def stream_max_size(self) -> int:
|
||||
if "stream_max_size" not in self.__data.keys():
|
||||
self.__data["stream_max_size"] = 1*8e20
|
||||
self.__data["stream_max_size"] = 1*8e20 # 1MB default value
|
||||
return self.__data.get("stream_max_size")
|
||||
|
||||
@stream_max_size.setter
|
||||
def stream_max_size(self, v: int):
|
||||
if not isinstance(v, int):
|
||||
raise Exception("Invalid data type, data MUST be of type int")
|
||||
self.__data["stream_max_size"] = v
|
||||
|
||||
@property
|
||||
def full_stream_action(self) -> FullStreamAction:
|
||||
if "full_stream_action" not in self.__data.keys():
|
||||
self.__data["full_stream_action"] = "flush"
|
||||
self.__data["full_stream_action"] = FullStreamAction.FLUSH
|
||||
return self.__data.get("full_stream_action")
|
||||
|
||||
@full_stream_action.setter
|
||||
def full_stream_action(self, v: FullStreamAction):
|
||||
if not isinstance(v, FullStreamAction):
|
||||
raise Exception("Invalid data type, data MUST be of type FullStreamAction")
|
||||
self.__data["full_stream_action"] = v
|
||||
|
||||
@property
|
||||
def invalid_encoding_action(self) -> ExceptionAction:
|
||||
if "invalid_encoding_action" not in self.__data.keys():
|
||||
self.__data["invalid_encoding_action"] = ExceptionAction.REJECT
|
||||
return self.__data.get("invalid_encoding_action")
|
||||
|
||||
@invalid_encoding_action.setter
|
||||
def invalid_encoding_action(self, v: ExceptionAction):
|
||||
if not isinstance(v, ExceptionAction):
|
||||
raise Exception("Invalid data type, data MUST be of type ExceptionAction")
|
||||
self.__data["invalid_encoding_action"] = v
|
||||
|
||||
@property
|
||||
def data_handler_context(self) -> dict:
|
||||
if "data_handler_context" not in self.__data.keys():
|
||||
|
||||
@@ -13,3 +13,4 @@ class RejectConnection(Exception):
|
||||
|
||||
class StreamFullReject(Exception):
|
||||
"raise this exception if you want to reject the connection due to full stream"
|
||||
|
||||
|
||||
@@ -8,6 +8,13 @@ class Action(Enum):
|
||||
REJECT = 2
|
||||
MANGLE = 3
|
||||
|
||||
class ExceptionAction(Enum):
|
||||
"""Action to be taken by the filter when an exception occurs (used in some cases)"""
|
||||
ACCEPT = 0
|
||||
DROP = 1
|
||||
REJECT = 2
|
||||
NOACTION = 3
|
||||
|
||||
class FullStreamAction(Enum):
|
||||
"""Action to be taken by the filter when the stream is full"""
|
||||
FLUSH = 0
|
||||
@@ -40,5 +47,3 @@ class PacketHandlerResult:
|
||||
|
||||
def reset_result(self) -> None:
|
||||
self.glob["__firegex_pyfilter_result"] = None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user