The RuleOption structure defines a single rule option as an option type and a reference to the data specific to that option. Each option has a flags field that contains specific flags for that option as well as a "Not" flag. The "Not" flag is used to negate the results of evaluating that option.
typedef enum DynamicOptionType { OPTION_TYPE_PREPROCESSOR, OPTION_TYPE_CONTENT, OPTION_TYPE_PCRE, OPTION_TYPE_FLOWBIT, OPTION_TYPE_FLOWFLAGS, OPTION_TYPE_ASN1, OPTION_TYPE_CURSOR, OPTION_TYPE_HDR_CHECK, OPTION_TYPE_BYTE_TEST, OPTION_TYPE_BYTE_JUMP, OPTION_TYPE_BYTE_EXTRACT, OPTION_TYPE_SET_CURSOR, OPTION_TYPE_LOOP, OPTION_TYPE_MAX }; typedef struct _RuleOption { int optionType; union { void *ptr; ContentInfo *content; CursorInfo *cursor; PCREInfo *pcre; FlowBitsInfo *flowBit; ByteData *byte; ByteExtract *byteExtract; FlowFlags *flowFlags; Asn1Context *asn1; HdrOptCheck *hdrData; LoopInfo *loop; PreprocessorOption *preprocOpt; } option_u; } RuleOption; #define NOT_FLAG 0x10000000
Some options also contain information that is initialized at run time, such as the compiled PCRE information, Boyer-Moore content information, the integer ID for a flowbit, etc.
The option types and related structures are listed below.
The ContentInfo structure defines an option for a content search. It includes the pattern, depth and offset, and flags (one of which must specify the buffer - raw, URI or normalized - to search). Additional flags include nocase, relative, unicode, and a designation that this content is to be used for snorts fast pattern evaluation. The most unique content, that which distinguishes this rule as a possible match to a packet, should be marked for fast pattern evaluation. In the dynamic detection engine provided with Snort, if no ContentInfo structure in a given rules uses that flag, the one with the longest content length will be used.
typedef struct _ContentInfo { u_int8_t *pattern; u_int32_t depth; int32_t offset; u_int32_t flags; /* must include a CONTENT_BUF_X */ void *boyer_ptr; u_int8_t *patternByteForm; u_int32_t patternByteFormLength; u_int32_t incrementLength; } ContentInfo; #define CONTENT_NOCASE 0x01 #define CONTENT_RELATIVE 0x02 #define CONTENT_UNICODE2BYTE 0x04 #define CONTENT_UNICODE4BYTE 0x08 #define CONTENT_FAST_PATTERN 0x10 #define CONTENT_END_BUFFER 0x20 #define CONTENT_BUF_NORMALIZED 0x100 #define CONTENT_BUF_RAW 0x200 #define CONTENT_BUF_URI 0x400
The PCREInfo structure defines an option for a PCRE search. It includes the PCRE expression, pcre_flags such as caseless, as defined in PCRE.h, and flags to specify the buffer.
/* pcre.h provides flags: PCRE_CASELESS PCRE_MULTILINE PCRE_DOTALL PCRE_EXTENDED PCRE_ANCHORED PCRE_DOLLAR_ENDONLY PCRE_UNGREEDY */ typedef struct _PCREInfo { char *expr; void *compiled_expr; void *compiled_extra; u_int32_t compile_flags; u_int32_t flags; /* must include a CONTENT_BUF_X */ } PCREInfo;
The FlowBitsInfo structure defines a flowbits option. It includes the name of the flowbit and the operation (set, setx, unset, toggle, isset, isnotset).
#define FLOWBIT_SET 0x01 #define FLOWBIT_UNSET 0x02 #define FLOWBIT_TOGGLE 0x04 #define FLOWBIT_ISSET 0x08 #define FLOWBIT_ISNOTSET 0x10 #define FLOWBIT_RESET 0x20 #define FLOWBIT_NOALERT 0x40 #define FLOWBIT_SETX 0x80 typedef struct _FlowBitsInfo { char *flowBitsName; uint8_t operation; uint16_t id; uint32_t flags; char *groupName; uint8_t eval; uint16_t *ids; uint8_t num_ids; } FlowBitsInfo;
The FlowFlags structure defines a flow option. It includes the flags, which specify the direction (from_server, to_server), established session, etc.
#define FLOW_ESTABLISHED 0x10 #define FLOW_IGNORE_REASSEMBLED 0x1000 #define FLOW_ONLY_REASSMBLED 0x2000 #define FLOW_FR_SERVER 0x40 #define FLOW_TO_CLIENT 0x40 /* Just for redundancy */ #define FLOW_TO_SERVER 0x80 #define FLOW_FR_CLIENT 0x80 /* Just for redundancy */ typedef struct _FlowFlags { u_int32_t flags; } FlowFlags;
The Asn1Context structure defines the information for an ASN1 option. It mirrors the ASN1 rule option and also includes a flags field.
#define ASN1_ABS_OFFSET 1 #define ASN1_REL_OFFSET 2 typedef struct _Asn1Context { int bs_overflow; int double_overflow; int print; int length; unsigned int max_length; int offset; int offset_type; u_int32_t flags; } Asn1Context;
The CursorInfo structure defines an option for a cursor evaluation. The cursor is the current position within the evaluation buffer, as related to content and PCRE searches, as well as byte tests and byte jumps. It includes an offset and flags that specify the buffer. This can be used to verify there is sufficient data to continue evaluation, similar to the isdataat rule option.
typedef struct _CursorInfo { int32_t offset; u_int32_t flags; /* specify one of CONTENT_BUF_X */ } CursorInfo;
The HdrOptCheck structure defines an option to check a protocol header for a specific value. It includes the header field, the operation (,,=,etc), a value, a mask to ignore that part of the header field, and flags.
#define IP_HDR_ID 0x0001 /* IP Header ID */ #define IP_HDR_PROTO 0x0002 /* IP Protocol */ #define IP_HDR_FRAGBITS 0x0003 /* Frag Flags set in IP Header */ #define IP_HDR_FRAGOFFSET 0x0004 /* Frag Offset set in IP Header */ #define IP_HDR_OPTIONS 0x0005 /* IP Options -- is option xx included */ #define IP_HDR_TTL 0x0006 /* IP Time to live */ #define IP_HDR_TOS 0x0007 /* IP Type of Service */ #define IP_HDR_OPTCHECK_MASK 0x000f #define TCP_HDR_ACK 0x0010 /* TCP Ack Value */ #define TCP_HDR_SEQ 0x0020 /* TCP Seq Value */ #define TCP_HDR_FLAGS 0x0030 /* Flags set in TCP Header */ #define TCP_HDR_OPTIONS 0x0040 /* TCP Options -- is option xx included */ #define TCP_HDR_WIN 0x0050 /* TCP Window */ #define TCP_HDR_OPTCHECK_MASK 0x00f0 #define ICMP_HDR_CODE 0x1000 /* ICMP Header Code */ #define ICMP_HDR_TYPE 0x2000 /* ICMP Header Type */ #define ICMP_HDR_ID 0x3000 /* ICMP ID for ICMP_ECHO/ICMP_ECHO_REPLY */ #define ICMP_HDR_SEQ 0x4000 /* ICMP ID for ICMP_ECHO/ICMP_ECHO_REPLY */ #define ICMP_HDR_OPTCHECK_MASK 0xf000 typedef struct _HdrOptCheck { u_int16_t hdrField; /* Field to check */ u_int32_t op; /* Type of comparison */ u_int32_t value; /* Value to compare value against */ u_int32_t mask_value; /* bits of value to ignore */ u_int32_t flags; } HdrOptCheck;
The ByteData structure defines the information for both ByteTest and ByteJump operations. It includes the number of bytes, an operation (for ByteTest, ,,=,etc), a value, an offset, multiplier, and flags. The flags must specify the buffer.
#define CHECK_EQ 0 #define CHECK_NEQ 1 #define CHECK_LT 2 #define CHECK_GT 3 #define CHECK_LTE 4 #define CHECK_GTE 5 #define CHECK_AND 6 #define CHECK_XOR 7 #define CHECK_ALL 8 #define CHECK_ATLEASTONE 9 #define CHECK_NONE 10 typedef struct _ByteData { u_int32_t bytes; /* Number of bytes to extract */ u_int32_t op; /* Type of byte comparison, for checkValue */ u_int32_t value; /* Value to compare value against, for checkValue, or extracted value */ int32_t offset; /* Offset from cursor */ u_int32_t multiplier; /* Used for byte jump -- 32bits is MORE than enough */ u_int32_t flags; /* must include a CONTENT_BUF_X */ } ByteData;
See Byte Test above.
See Cursor Check above.
The LoopInfo structure defines the information for a set of options that are to be evaluated repeatedly. The loop option acts like a FOR loop and includes start, end, and increment values as well as the comparison operation for termination. It includes a cursor adjust that happens through each iteration of the loop, a reference to a RuleInfo structure that defines the RuleOptions are to be evaluated through each iteration. One of those options may be a ByteExtract.
typedef struct _LoopInfo { DynamicElement *start; /* Starting value of FOR loop (i=start) */ DynamicElement *end; /* Ending value of FOR loop (i OP end) */ DynamicElement *increment; /* Increment value of FOR loop (i+= increment) */ u_int32_t op; /* Type of comparison for loop termination */ CursorInfo *cursorAdjust; /* How to move cursor each iteration of loop */ struct _Rule *subRule; /* Pointer to SubRule & options to evaluate within * the loop */ u_int8_t initialized; /* Loop initialized properly (safeguard) */ u_int32_t flags; /* can be used to negate loop results, specifies * relative. */ } LoopInfo;
The ByteExtract structure defines the information to use when extracting bytes for a DynamicElement used a in Loop evaltion. It includes the number of bytes, an offset, multiplier, flags specifying the buffer, and a reference to the DynamicElement.
typedef struct _ByteExtract { u_int32_t bytes; /* Number of bytes to extract */ int32_t offset; /* Offset from cursor */ u_int32_t multiplier; /* Multiply value by this (similar to byte jump) */ u_int32_t flags; /* must include a CONTENT_BUF_X */ char *refId; /* To match up with a DynamicElement refId */ void *memoryLocation; /* Location to store the data extracted */ } ByteExtract;
The DynamicElement structure is used to define the values for a looping evaluation. It includes whether the element is static (an integer) or dynamic (extracted from a buffer in the packet) and the value. For a dynamic element, the value is filled by a related ByteExtract option that is part of the loop.
#define DYNAMIC_TYPE_INT_STATIC 1 #define DYNAMIC_TYPE_INT_REF 2 typedef struct _DynamicElement { char dynamicType; /* type of this field - static or reference */ char *refId; /* reference ID (NULL if static) */ union { void *voidPtr; /* Holder */ int32_t staticInt; /* Value of static */ int32_t *dynamicInt; /* Pointer to value of dynamic */ } data; } DynamicElement;