diff --git a/src/Makefile.am b/src/Makefile.am index 7851ead44a..bef10a7623 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,7 @@ detect-flow.c detect-flow.h \ detect-dsize.c detect-dsize.h \ detect-decode-event.c detect-decode-event.h \ detect-noalert.c detect-noalert.h \ +detect-csum.c detect-csum.h \ util-print.c util-print.h \ util-mpm.c util-mpm.h \ util-binsearch.c util-binsearch.h \ diff --git a/src/decode-icmpv4.c b/src/decode-icmpv4.c index 1217cdeb79..258f0428e0 100644 --- a/src/decode-icmpv4.c +++ b/src/decode-icmpv4.c @@ -13,7 +13,7 @@ * * \retval csum Checksum for the ICMP packet */ -static inline uint16_t ICMPV4CalculateChecksum(uint16_t *pkt, uint16_t tlen) +inline uint16_t ICMPV4CalculateChecksum(uint16_t *pkt, uint16_t tlen) { uint16_t pad = 0; uint32_t csum = pkt[0]; @@ -76,6 +76,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt #endif p->proto = IPPROTO_ICMP; + return; } diff --git a/src/decode-icmpv4.h b/src/decode-icmpv4.h index d4e1ef350d..2844694227 100644 --- a/src/decode-icmpv4.h +++ b/src/decode-icmpv4.h @@ -133,6 +133,12 @@ typedef struct ICMPV4Hdr_ /* XXX incomplete */ } ICMPV4Hdr; +typedef struct ICMPV4Cache_ { + /* checksum computed over the icmpv4 packet */ + int32_t comp_csum; +} ICMPV4Cache; + +inline uint16_t ICMPV4CalculateChecksum(uint16_t *, uint16_t); void DecodeICMPV4RegisterTests(void); #endif /* __DECODE_ICMPV4_H__ */ diff --git a/src/decode-icmpv6.c b/src/decode-icmpv6.c index 429bf69101..8d7314e3aa 100644 --- a/src/decode-icmpv6.c +++ b/src/decode-icmpv6.c @@ -15,8 +15,8 @@ * * \retval csum Checksum for the ICMPV6 packet */ -static inline uint16_t ICMPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) +inline uint16_t ICMPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; diff --git a/src/decode-icmpv6.h b/src/decode-icmpv6.h index 582a30bfce..07427654e0 100644 --- a/src/decode-icmpv6.h +++ b/src/decode-icmpv6.h @@ -73,6 +73,12 @@ typedef struct ICMPV6Hdr_ /* XXX incomplete */ } ICMPV6Hdr; +typedef struct ICMPV6Cache_ { + /* checksum computed over the icmpv6 packet */ + int32_t comp_csum; +} ICMPV6Cache; + +inline uint16_t ICMPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t); void DecodeICMPV6RegisterTests(void); #endif /* __DECODE_ICMPV6_H__ */ diff --git a/src/decode-ipv4.c b/src/decode-ipv4.c index 87fff43c20..0aeaa81c28 100644 --- a/src/decode-ipv4.c +++ b/src/decode-ipv4.c @@ -19,7 +19,7 @@ * * \retval csum Checksum for the IP packet */ -static inline uint16_t IPV4CalculateChecksum(uint16_t *pkt, uint16_t hlen) +inline uint16_t IPV4CalculateChecksum(uint16_t *pkt, uint16_t hlen) { uint32_t csum = pkt[0]; diff --git a/src/decode-ipv4.h b/src/decode-ipv4.h index 5aa91e2630..48845e899f 100644 --- a/src/decode-ipv4.h +++ b/src/decode-ipv4.h @@ -165,6 +165,7 @@ typedef struct IPV4Cache_ uint8_t ip_ttl; /* time to live field */ uint8_t ip_proto; /* datagram protocol */ uint16_t ip_csum; /* checksum */ + int32_t comp_csum; /* checksum computed over the ipv4 packet */ uint32_t ip_src_u32; /* source IP */ uint32_t ip_dst_u32; /* dest IP */ @@ -189,6 +190,7 @@ typedef struct IPV4Vars_ IPV4Opt *o_rtralt; } IPV4Vars; +inline uint16_t IPV4CalculateChecksum(uint16_t *, uint16_t); void DecodeIPV4RegisterTests(void); #endif /* __DECODE_IPV4_H__ */ diff --git a/src/decode-tcp.c b/src/decode-tcp.c index 84bd4716cf..a1b1c11e13 100644 --- a/src/decode-tcp.c +++ b/src/decode-tcp.c @@ -18,8 +18,8 @@ * * \retval csum Checksum for the TCP packet */ -static inline uint16_t TCPCalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) +inline uint16_t TCPCalculateChecksum(uint16_t *shdr, uint16_t *pkt, + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; @@ -78,8 +78,8 @@ static inline uint16_t TCPCalculateChecksum(uint16_t *shdr, uint16_t *pkt, * * \retval csum Checksum for the TCP packet */ -static inline uint16_t TCPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) +inline uint16_t TCPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; diff --git a/src/decode-tcp.h b/src/decode-tcp.h index a247dfbf6d..5dba9ec482 100644 --- a/src/decode-tcp.h +++ b/src/decode-tcp.h @@ -105,6 +105,11 @@ typedef struct TCPVars_ TCPOpt *mss; } TCPVars; +typedef struct TCPCache_ { + /* checksum computed over the tcp(for both ipv4 and ipv6) packet */ + int32_t comp_csum; +} TCPCache; + #define CLEAR_TCP_PACKET(p) { \ (p)->tcph = NULL; \ (p)->tcpvars.tcp_opt_cnt = 0; \ @@ -114,6 +119,8 @@ typedef struct TCPVars_ (p)->tcpvars.mss = NULL; \ } +inline uint16_t TCPCalculateChecksum(uint16_t *, uint16_t *, uint16_t); +inline uint16_t TCPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t); void DecodeTCPRegisterTests(void); #endif /* __DECODE_TCP_H__ */ diff --git a/src/decode-udp.c b/src/decode-udp.c index c111ff987b..8ee0ede125 100644 --- a/src/decode-udp.c +++ b/src/decode-udp.c @@ -18,8 +18,8 @@ * * \retval csum Checksum for the UDP packet */ -static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) +inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; @@ -77,8 +77,8 @@ static inline uint16_t UDPV4CalculateChecksum(uint16_t *shdr, uint16_t *pkt, * * \retval csum Checksum for the UDP packet */ -static inline uint16_t UDPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, - uint16_t tlen) +inline uint16_t UDPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt, + uint16_t tlen) { uint16_t pad = 0; uint32_t csum = shdr[0]; @@ -150,6 +150,7 @@ static int DecodeUDPPacket(ThreadVars *t, Packet *p, uint8_t *pkt, uint16_t len) SET_UDP_SRC_PORT(p,&p->sp); SET_UDP_DST_PORT(p,&p->dp); + p->udpvars.hlen = UDP_HEADER_LEN; p->payload = pkt + UDP_HEADER_LEN; p->payload_len = len - UDP_HEADER_LEN; diff --git a/src/decode-udp.h b/src/decode-udp.h index 3e052cb719..691f2f8064 100644 --- a/src/decode-udp.h +++ b/src/decode-udp.h @@ -28,6 +28,13 @@ typedef struct UDPVars_ uint8_t hlen; } UDPVars; +typedef struct UDPCache_ { + /* checksum computed over the udp(for both ipv4 and ipv6) packet */ + int32_t comp_csum; +} UDPCache; + +inline uint16_t UDPV4CalculateChecksum(uint16_t *, uint16_t *, uint16_t); +inline uint16_t UDPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t); void DecodeUDPV4RegisterTests(void); #endif /* __DECODE_UDP_H__ */ diff --git a/src/decode.h b/src/decode.h index 02e50c1253..f1aaf8ce17 100644 --- a/src/decode.h +++ b/src/decode.h @@ -254,13 +254,17 @@ typedef struct Packet_ IPV6ExtHdrs ip6eh; ICMPV4Hdr *icmpv4h; + ICMPV4Cache icmpv4c; ICMPV6Hdr *icmpv6h; + ICMPV6Cache icmpv6c; TCPHdr *tcph; TCPVars tcpvars; + TCPCache tcpc; UDPHdr *udph; UDPVars udpvars; + UDPCache udpc; /* ptr to the payload of the packet * with it's length. */ @@ -356,6 +360,15 @@ typedef struct DecodeThreadVars_ (p)->recursion_level = 0; \ } +/* reset these to -1(indicates that the packet is fresh from the queue) */ +#define RESET_PACKET_CSUMS(p) { \ + (p)->ip4c.comp_csum = -1; \ + (p)->tcpc.comp_csum = -1; \ + (p)->udpc.comp_csum = -1; \ + (p)->icmpv4c.comp_csum = -1; \ + (p)->icmpv6c.comp_csum = -1; \ +} + /* macro's for setting the action * handle the case of a root packet diff --git a/src/detect-csum.c b/src/detect-csum.c new file mode 100644 index 0000000000..ad3125e383 --- /dev/null +++ b/src/detect-csum.c @@ -0,0 +1,1517 @@ +/** + * \file + * \author Anoop Saldanha + * + * Checksum keyword for the the detection engine. + */ + +#include + +#include "eidps-common.h" +#include "debug.h" +#include "decode.h" +#include "detect.h" +#include "detect-csum.h" + +#include "util-unittest.h" + +/* prototypes for the "ipv4-csum" rule keyword */ +int DetectIPV4CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectIPV4CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectIPV4CsumFree(void *); + +/* prototypes for the "tcpv4-csum" rule keyword */ +int DetectTCPV4CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectTCPV4CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectTCPV4CsumFree(void *); + +/* prototypes for the "tcpv6-csum" rule keyword */ +int DetectTCPV6CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectTCPV6CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectTCPV6CsumFree(void *); + +/* prototypes for the "udpv4-csum" rule keyword */ +int DetectUDPV4CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectUDPV4CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectUDPV4CsumFree(void *); + +/* prototypes for the "udpv6-csum" rule keyword */ +int DetectUDPV6CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectUDPV6CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectUDPV6CsumFree(void *); + +/* prototypes for the "icmpv4-csum" rule keyword */ +int DetectICMPV4CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectICMPV4CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectICMPV4CsumFree(void *); + +/* prototypes for the "icmpv6-csum" rule keyword */ +int DetectICMPV6CsumMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, + Signature *, SigMatch *); +int DetectICMPV6CsumSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectICMPV6CsumFree(void *); + +void DetectCsumRegisterTests(void); + +/** + * \brief Registers handlers for all the checksum keywords. The checksum + * keywords that are registered are ipv4-sum, tcpv4-csum, tcpv6-csum, + * udpv4-csum, udpv6-csum, icmpv4-csum and icmpv6-csum. + * + * Each of the checksum keywords implemented here takes 2 arguments - + * "valid" or "invalid". If the rule keyword in the signature is + * specified as "valid", the Match function would return TRUE if the + * checksum for that particular packet and protocol is valid. Similarly + * for "invalid". + * + * The Setup functions takes 4 arguments - + * + * DetectEngineCtx * (de_ctx) - A pointer to the detection engine context + * Signature *(s) - Pointer to signature for the current Signature being + * parsed from the rules + * SigMatch * (m) - Pointer to the head of the SigMatchs added to the + * current Signature being parsed + * char * (csum_str) - Pointer to a string holding the keyword value + * + * The Setup function returns 0 if it successfully parses the keyword + * value, and -1 otherwise. + * + * The Match function takes 5 arguments - + * + * ThreadVars * (t) - Pointer to the tv for the detection module instance + * DetectEngineThreadCtx * (det_ctx) - Pointer to the detection engine + * thread context + * Packet * (p) - Pointer to the Packet currently being handled + * Signature * (s) - Pointer to the Signature, the packet is being + * currently matched with + * SigMatch * (m) - Pointer to the keyword structure from the above + * Signature, the Packet is being currently matched + * with + * + * The Match function returns 1 if the Packet contents match the keyword, + * and 0 otherwise + * + * The Free function takes a single argument - + * + * void * (ptr) - Pointer to the DetectCsumData for a keyword + */ +void DetectCsumRegister (void) +{ + sigmatch_table[DETECT_IPV4_CSUM].name = "ipv4-csum"; + sigmatch_table[DETECT_IPV4_CSUM].Match = DetectIPV4CsumMatch; + sigmatch_table[DETECT_IPV4_CSUM].Setup = DetectIPV4CsumSetup; + sigmatch_table[DETECT_IPV4_CSUM].Free = DetectIPV4CsumFree; + sigmatch_table[DETECT_IPV4_CSUM].RegisterTests = DetectCsumRegisterTests; + + sigmatch_table[DETECT_TCPV4_CSUM].name = "tcpv4-csum"; + sigmatch_table[DETECT_TCPV4_CSUM].Match = DetectTCPV4CsumMatch; + sigmatch_table[DETECT_TCPV4_CSUM].Setup = DetectTCPV4CsumSetup; + sigmatch_table[DETECT_TCPV4_CSUM].Free = DetectTCPV4CsumFree; + sigmatch_table[DETECT_TCPV4_CSUM].RegisterTests = NULL; + + sigmatch_table[DETECT_TCPV6_CSUM].name = "tcpv6-csum"; + sigmatch_table[DETECT_TCPV6_CSUM].Match = DetectTCPV6CsumMatch; + sigmatch_table[DETECT_TCPV6_CSUM].Setup = DetectTCPV6CsumSetup; + sigmatch_table[DETECT_TCPV6_CSUM].Free = DetectTCPV6CsumFree; + sigmatch_table[DETECT_TCPV6_CSUM].RegisterTests = NULL; + + sigmatch_table[DETECT_UDPV4_CSUM].name = "udpv4-csum"; + sigmatch_table[DETECT_UDPV4_CSUM].Match = DetectUDPV4CsumMatch; + sigmatch_table[DETECT_UDPV4_CSUM].Setup = DetectUDPV4CsumSetup; + sigmatch_table[DETECT_UDPV4_CSUM].Free = DetectUDPV4CsumFree; + sigmatch_table[DETECT_UDPV4_CSUM].RegisterTests = NULL; + + sigmatch_table[DETECT_UDPV6_CSUM].name = "udpv6-csum"; + sigmatch_table[DETECT_UDPV6_CSUM].Match = DetectUDPV6CsumMatch; + sigmatch_table[DETECT_UDPV6_CSUM].Setup = DetectUDPV6CsumSetup; + sigmatch_table[DETECT_UDPV6_CSUM].Free = DetectUDPV6CsumFree; + sigmatch_table[DETECT_UDPV6_CSUM].RegisterTests = NULL; + + sigmatch_table[DETECT_ICMPV4_CSUM].name = "icmpv4-csum"; + sigmatch_table[DETECT_ICMPV4_CSUM].Match = DetectICMPV4CsumMatch; + sigmatch_table[DETECT_ICMPV4_CSUM].Setup = DetectICMPV4CsumSetup; + sigmatch_table[DETECT_ICMPV4_CSUM].Free = DetectICMPV4CsumFree; + sigmatch_table[DETECT_ICMPV4_CSUM].RegisterTests = NULL; + + sigmatch_table[DETECT_ICMPV6_CSUM].name = "icmpv6-csum"; + sigmatch_table[DETECT_ICMPV6_CSUM].Match = DetectICMPV6CsumMatch; + sigmatch_table[DETECT_ICMPV6_CSUM].Setup = DetectICMPV6CsumSetup; + sigmatch_table[DETECT_ICMPV6_CSUM].Free = DetectICMPV6CsumFree; + sigmatch_table[DETECT_ICMPV6_CSUM].RegisterTests = NULL; + + return; +} + +/** + * \brief Validates and parses the argument supplied with the checksum keyword. + * Accepts strings both with and without quotes, i.e. valid, \"valid\", + * invalid and \"invalid\" + * + * \param key Pointer to a const character string holding the csum keyword value + * \param cd Pointer to the DetectCsumData structure that holds the keyword + * value sent as argument + * + * \retval 1 if the keyvalue has been parsed successfully, and 0 otherwise + */ +static int DetectCsumParseArg(const char *key, DetectCsumData *cd) +{ + char *str; + + if (key[0] == '\"' && key[strlen(key) - 1] == '\"') { + str = strdup(key + 1); + str[strlen(key) - 2] = '\0'; + } else + str = strdup(key); + + if (strcasecmp(str, DETECT_CSUM_VALID) == 0 || + strcasecmp(str, DETECT_CSUM_INVALID) == 0) { + cd->valid = (strcasecmp(key, DETECT_CSUM_VALID) == 0); + free(str); + return 1; + } + + free(str); + return 0; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * ipv4 checksum, based on whether ipv4-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectIPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip4h == NULL) + return 1; + + if (p->ip4c.comp_csum == -1) + p->ip4c.comp_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h, + IPV4_GET_RAW_HLEN(p->ip4h)); + + if (p->ip4c.comp_csum == p->ip4h->ip_csum && cd->valid == 1) + return 1; + else if (p->ip4c.comp_csum != p->ip4h->ip_csum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the ipv4-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectIPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_IPV4_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectIPV4CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectIPV4CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * tcpv4 checksum, based on whether tcpv4-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectTCPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip4h == NULL || p->proto != IPPROTO_TCP) + return 1; + + if (p->tcpc.comp_csum == -1) + p->tcpc.comp_csum = TCPCalculateChecksum((uint16_t *)&(p->ip4h->ip_src), + (uint16_t *)p->tcph, + (p->payload_len + + p->tcpvars.hlen) ); + + if (p->tcpc.comp_csum == p->tcph->th_sum && cd->valid == 1) + return 1; + else if (p->tcpc.comp_csum != p->tcph->th_sum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the tcpv4-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectTCPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_TCPV4_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectTCPV4CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectTCPV4CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd != NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * tcpv6 checksum, based on whether tcpv6-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectTCPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip6h == NULL || p->proto != IPPROTO_TCP) + return 1; + + if (p->tcpc.comp_csum == -1) + p->tcpc.comp_csum = TCPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), + (uint16_t *)p->tcph, + (p->payload_len + + p->tcpvars.hlen) ); + + if (p->tcpc.comp_csum == p->tcph->th_sum && cd->valid == 1) + return 1; + else if (p->tcpc.comp_csum != p->tcph->th_sum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the tcpv6-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectTCPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_TCPV6_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectTCPV6CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectTCPV6CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * udpv4 checksum, based on whether udpv4-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectUDPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip4h == NULL || p->proto != IPPROTO_UDP) + return 1; + + if (p->udpc.comp_csum == -1) + p->udpc.comp_csum = UDPV4CalculateChecksum((uint16_t *)&(p->ip4h->ip_src), + (uint16_t *)p->udph, + (p->payload_len + + p->udpvars.hlen) ); + + if (p->udpc.comp_csum == p->udph->uh_sum && cd->valid == 1) + return 1; + else if (p->udpc.comp_csum != p->udph->uh_sum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the udpv4-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectUDPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_UDPV4_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectUDPV4CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectUDPV4CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * udpv6 checksum, based on whether udpv6-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectUDPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip6h == NULL || p->proto != IPPROTO_UDP) + return 1; + + if (p->udpc.comp_csum == -1) + p->udpc.comp_csum = UDPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), + (uint16_t *)p->udph, + (p->payload_len + + p->udpvars.hlen) ); + + if (p->udpc.comp_csum == p->udph->uh_sum && cd->valid == 1) + return 1; + else if (p->udpc.comp_csum != p->udph->uh_sum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the udpv6-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectUDPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_UDPV6_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectUDPV6CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectUDPV6CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * icmpv4 checksum, based on whether icmpv4-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectICMPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip4h == NULL || p->proto != IPPROTO_ICMP) + return 1; + + if (p->icmpv4c.comp_csum == -1) + p->icmpv4c.comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h, + ntohs(IPV4_GET_RAW_IPLEN(p->ip4h)) - + IPV4_GET_RAW_HLEN(p->ip4h) * 4); + + if (p->icmpv4c.comp_csum == p->icmpv4h->checksum && cd->valid == 1) + return 1; + else if (p->icmpv4c.comp_csum != p->icmpv4h->checksum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the icmpv4-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectICMPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_ICMPV4_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectICMPV4CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectICMPV4CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/** + * \brief Checks if the packet sent as the argument, has a valid or invalid + * icmpv6 checksum, based on whether icmpv6-csum option for this rule + * has been supplied with "valid" or "invalid" argument + * + * \param t Pointer to the tv for this detection module instance + * \param det_ctx Pointer to the detection engine thread context + * \param p Pointer to the Packet currently being matched + * \param s Pointer to the Signature, the packet is being currently + * matched with + * \param m Pointer to the keyword_structure(SigMatch) from the above + * Signature, the Packet is being currently matched with + * + * \retval 1 if the Packet contents match the keyword option; 0 otherwise + */ +int DetectICMPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectCsumData *cd = (DetectCsumData *)m->ctx; + + if (p->ip6h == NULL || p->proto != IPPROTO_ICMPV6) + return 1; + + if (p->icmpv6c.comp_csum == -1) + p->icmpv6c.comp_csum = ICMPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src), + (uint16_t *)p->icmpv6h, + IPV6_GET_PLEN(p)); + + if (p->icmpv6c.comp_csum == p->icmpv6h->csum && cd->valid == 1) + return 1; + else if (p->icmpv6c.comp_csum != p->icmpv6h->csum && cd->valid == 0) + return 1; + else + return 0; +} + +/** + * \brief Creates a SigMatch for the icmpv6-csum keyword being sent as argument, + * and appends it to the Signature(s). Accepts 2 values for the + * keyword - "valid" and "invalid", both with and without quotes + * + * \param de_ctx Pointer to the detection engine context + * \param s Pointer to signature for the current Signature being parsed + * from the rules + * \param m Pointer to the head of the SigMatchs for the current rule + * being parsed + * \param csum_str Pointer to the string holding the keyword value + * + * \retval 0 on success, -1 on failure + */ +int DetectICMPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, + char *csum_str) +{ + DetectCsumData *cd = NULL; + SigMatch *sm = NULL; + + //printf("DetectCsumSetup: \'%s\'\n", csum_str); + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_ICMPV6_CSUM; + + if ( (cd = malloc(sizeof(DetectCsumData))) == NULL) { + printf("Error allocating memory\n"); + exit(0); + } + memset(cd, 0, sizeof(DetectCsumData)); + + if (DetectCsumParseArg(csum_str, cd) == 0) + goto error; + + sm->ctx = (void *)cd; + + SigMatchAppend(s, m, sm); + + return 0; + +error: + if (cd != NULL) DetectICMPV6CsumFree(cd); + if (sm != NULL) free(sm); + + return -1; +} + +void DetectICMPV6CsumFree(void *ptr) +{ + DetectCsumData *cd = (DetectCsumData *)ptr; + + if (cd == NULL) + free(cd); + + return; +} + +/* ---------------------------------- Unit Tests --------------------------- */ + +#ifdef UNITTESTS + +int DetectCsumIPV4ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectIPV4CsumSetup(NULL, &s, NULL, "\"valid\"") == 0); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "\"invalid\"") == 0); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "\"vaLid\"") == 0); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "\"VALID\"") == 0); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "\"iNvaLid\"") == 0); + + while (s.match != NULL) { + DetectIPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumIPV4InValidArgsTestParse02(void) +{ + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectIPV4CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectIPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumIPV4ValidArgsTestParse03(void) +{ + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectIPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectIPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectIPV4CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectIPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV4ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectICMPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV4InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV4CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectICMPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV4ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectICMPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectICMPV4CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectICMPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV4ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectTCPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV4InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV4CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectTCPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV4ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectTCPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectTCPV4CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectTCPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV4ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectUDPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV4InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV4CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectUDPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV4ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV4CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectUDPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectUDPV4CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectUDPV4CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV6ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectTCPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV6InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV6CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectTCPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumTCPV6ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectTCPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectTCPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectTCPV6CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectTCPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV6ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectUDPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV6InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV6CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectUDPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumUDPV6ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectUDPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectUDPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectUDPV6CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectUDPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV6ValidArgsTestParse01(void) +{ + Signature s; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "invalid") == 0); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "vaLid") == 0); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "VALID") == 0); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "iNvaLid") == 0); + + while (s.match != NULL) { + DetectICMPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV6InValidArgsTestParse02(void) { + Signature s; + int result = -1; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV6CsumSetup(NULL, &s, NULL, "vaid") == -1); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "invaalid") == -1); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "vaLiid") == -1); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "VALieD") == -1); + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "iNvamid") == -1); + + while (s.match != NULL) { + DetectICMPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +int DetectCsumICMPV6ValidArgsTestParse03(void) { + Signature s; + DetectCsumData *cd = NULL; + int result = 0; + SigMatch *temp = NULL; + + memset(&s, 0, sizeof(Signature)); + + result = (DetectICMPV6CsumSetup(NULL, &s, NULL, "valid") == 0); + + while (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 1); + } + DetectICMPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + s.match = NULL; + + result &= (DetectICMPV6CsumSetup(NULL, &s, NULL, "INVALID") == 0); + + if (s.match != NULL) { + if (s.match->ctx != NULL) { + cd = (DetectCsumData *)s.match->ctx; + result &= (cd->valid == 0); + } + DetectICMPV6CsumFree(s.match->ctx); + temp = s.match; + s.match = s.match->next; + free(temp); + } + + return result; +} + +#endif /* UNITTESTS */ + +void DetectCsumRegisterTests(void) +{ + +#ifdef UNITTESTS + + UtRegisterTest("DetectCsumIPV4ValidArgsTestParse01", + DetectCsumIPV4ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumIPV4InValidArgsTestParse02", + DetectCsumIPV4InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumIPV4ValidArgsTestParse03", + DetectCsumIPV4ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumICMPV4ValidArgsTestParse01", + DetectCsumICMPV4ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumICMPV4InValidArgsTestParse02", + DetectCsumICMPV4InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumICMPV4ValidArgsTestParse03", + DetectCsumICMPV4ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumTCPV4ValidArgsTestParse01", + DetectCsumTCPV4ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumTCPV4InValidArgsTestParse02", + DetectCsumTCPV4InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumTCPV4ValidArgsTestParse03", + DetectCsumTCPV4ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumUDPV4ValidArgsTestParse01", + DetectCsumUDPV4ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumUDPV4InValidArgsTestParse02", + DetectCsumUDPV4InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumUDPV4ValidArgsTestParse03", + DetectCsumUDPV4ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumUDPV6ValidArgsTestParse01", + DetectCsumUDPV6ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumUDPV6InValidArgsTestParse02", + DetectCsumUDPV6InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumUDPV6ValidArgsTestParse03", + DetectCsumUDPV6ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumTCPV6ValidArgsTestParse01", + DetectCsumTCPV6ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumTCPV6InValidArgsTestParse02", + DetectCsumTCPV6InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumTCPV6ValidArgsTestParse03", + DetectCsumTCPV6ValidArgsTestParse03, 1); + + UtRegisterTest("DetectCsumICMPV6ValidArgsTestParse01", + DetectCsumICMPV6ValidArgsTestParse01, 1); + UtRegisterTest("DetectCsumICMPV6InValidArgsTestParse02", + DetectCsumICMPV6InValidArgsTestParse02, 1); + UtRegisterTest("DetectCsumICMPV6ValidArgsTestParse03", + DetectCsumICMPV6ValidArgsTestParse03, 1); + +#endif /* UNITTESTS */ + +} diff --git a/src/detect-csum.h b/src/detect-csum.h new file mode 100644 index 0000000000..b9bc506fe7 --- /dev/null +++ b/src/detect-csum.h @@ -0,0 +1,16 @@ +#ifndef __DETECT_CSUM_H__ +#define __DETECT_CSUM_H__ + +#define DETECT_CSUM_VALID "valid" +#define DETECT_CSUM_INVALID "invalid" + +typedef struct DetectCsumData_ { + /* Indicates if the csum- keyword in a rule holds the + keyvalue "valid" or "invalid" */ + int16_t valid; +} DetectCsumData; + +void DetectCsumRegister(void); + +#endif /* __DETECT_CSUM_H__ */ + diff --git a/src/detect.c b/src/detect.c index 7f98a6258c..13a90bc7a2 100644 --- a/src/detect.c +++ b/src/detect.c @@ -43,6 +43,7 @@ #include "detect-pktvar.h" #include "detect-noalert.h" #include "detect-flowbits.h" +#include "detect-csum.h" #include "action-globals.h" #include "tm-modules.h" @@ -2501,6 +2502,7 @@ void SigTableSetup(void) { DetectNoalertRegister(); DetectFlowbitsRegister(); DetectDecodeEventRegister(); + DetectCsumRegister(); uint8_t i = 0; for (i = 0; i < DETECT_TBLSIZE; i++) { @@ -4094,6 +4096,1559 @@ static int SigTest23Wm (void) { return SigTest23Real(MPM_WUMANBER); } +int SigTest24IPV4Keyword(void) +{ + uint8_t valid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t invalid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, + 0xc0, 0xa8, 0x01, 0x06}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + p1.ip4c.comp_csum = -1; + p2.ip4c.comp_csum = -1; + + p1.ip4h = (IPV4Hdr *)valid_raw_ipv4; + + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_TCP; + + p2.ip4h = (IPV4Hdr *)invalid_raw_ipv4; + + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; ipv4-csum:valid; " + "msg:\"ipv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; ipv4-csum:invalid; " + "msg:\"ipv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else { + result &= 0; + printf("signature didn't match, but should have: "); + } + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest25NegativeIPV4Keyword(void) +{ + uint8_t valid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t invalid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, + 0xc0, 0xa8, 0x01, 0x06}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + p1.ip4c.comp_csum = -1; + p2.ip4c.comp_csum = -1; + + p1.ip4h = (IPV4Hdr *)valid_raw_ipv4; + + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_TCP; + + p2.ip4h = (IPV4Hdr *)invalid_raw_ipv4; + + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; ipv4-csum:invalid; " + "msg:\"ipv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; ipv4-csum:valid; " + "msg:\"ipv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 0; + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest26TCPV4Keyword(void) +{ + uint8_t raw_ipv4[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x7e, 0xb2, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t valid_raw_tcp[] = { + 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, + 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, + 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, + 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02}; + + uint8_t invalid_raw_tcp[] = { + 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, + 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, + 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, + 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03}; + + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.tcpc.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)raw_ipv4; + p1.tcph = (TCPHdr *)valid_raw_tcp; + //p1.tcpvars.hlen = TCP_GET_HLEN((&p)); + p1.tcpvars.hlen = 0; + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_TCP; + + p2.tcpc.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)raw_ipv4; + p2.tcph = (TCPHdr *)invalid_raw_tcp; + //p2.tcpvars.hlen = TCP_GET_HLEN((&p)); + p2.tcpvars.hlen = 0; + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv4-csum:valid; " + "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv4-csum:invalid; " + "msg:\"tcpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest27NegativeTCPV4Keyword(void) +{ + uint8_t raw_ipv4[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x7e, 0xb2, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t valid_raw_tcp[] = { + 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, + 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, + 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, + 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02}; + + uint8_t invalid_raw_tcp[] = { + 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c, + 0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0, + 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, + 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73, + 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03}; + + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.tcpc.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)raw_ipv4; + p1.tcph = (TCPHdr *)valid_raw_tcp; + //p1.tcpvars.hlen = TCP_GET_HLEN((&p)); + p1.tcpvars.hlen = 0; + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_TCP; + + p2.tcpc.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)raw_ipv4; + p2.tcph = (TCPHdr *)invalid_raw_tcp; + //p2.tcpvars.hlen = TCP_GET_HLEN((&p)); + p2.tcpvars.hlen = 0; + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv4-csum:invalid; " + "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv4-csum:valid; " + "msg:\"tcpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) { + result &= 0; + } + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest28TCPV6Keyword(void) +{ + static uint8_t valid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, + 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, + 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, + 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, + 0xca, 0x5a, 0x00, 0x01, 0x69, 0x27}; + + static uint8_t invalid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, + 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, + 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, + 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, + 0xca, 0x5a, 0x00, 0x01, 0x69, 0x28}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0tttttttt\r\n" + "\r\n\r\n"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.tcpc.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.tcph = (TCPHdr *) (valid_raw_ipv6 + 54); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.tcpvars.hlen = TCP_GET_HLEN((&p1)); + p1.payload = buf; + p1.payload_len = p1.tcpvars.hlen; + p1.tcpvars.hlen = 0; + p1.proto = IPPROTO_TCP; + + p2.tcpc.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.tcph = (TCPHdr *) (invalid_raw_ipv6 + 54); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.tcpvars.hlen = TCP_GET_HLEN((&p2)); + p2.payload = buf; + p2.payload_len = p2.tcpvars.hlen; + p2.tcpvars.hlen = 0; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv6-csum:valid; " + "msg:\"tcpv6-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv6-csum:invalid; " + "msg:\"tcpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest29NegativeTCPV6Keyword(void) +{ + static uint8_t valid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, + 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, + 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, + 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, + 0xca, 0x5a, 0x00, 0x01, 0x69, 0x27}; + + static uint8_t invalid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, + 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d, 0x0c, 0x7a, + 0x08, 0x77, 0x80, 0x10, 0x21, 0x5c, 0xc2, 0xf1, + 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, + 0xca, 0x5a, 0x00, 0x01, 0x69, 0x28}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0tttttttt\r\n" + "\r\n\r\n"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.tcpc.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.tcph = (TCPHdr *) (valid_raw_ipv6 + 54); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.tcpvars.hlen = TCP_GET_HLEN((&p1)); + p1.payload = buf; + p1.payload_len = p1.tcpvars.hlen; + p1.tcpvars.hlen = 0; + p1.proto = IPPROTO_TCP; + + p2.tcpc.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.tcph = (TCPHdr *) (invalid_raw_ipv6 + 54); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.tcpvars.hlen = TCP_GET_HLEN((&p2)); + p2.payload = buf; + p2.payload_len = p2.tcpvars.hlen; + p2.tcpvars.hlen = 0; + p2.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv6-csum:invalid; " + "msg:\"tcpv6-csum keyword check(1)\"; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert tcp any any -> any any " + "(content:\"/one/\"; tcpv6-csum:valid; " + "msg:\"tcpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 0; + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest30UDPV4Keyword(void) +{ + uint8_t raw_ipv4[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x43, 0xdc, 0xdc, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t valid_raw_udp[] = { + 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0, + 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, + 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63, + 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, + 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b, + 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65, + 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0xc0, 0x26}; + + uint8_t invalid_raw_udp[] = { + 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0, + 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, + 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63, + 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, + 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b, + 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65, + 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0xc0, 0x27}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" + "\r\n\r\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.udpc.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)raw_ipv4; + p1.udph = (UDPHdr *)valid_raw_udp; + p1.udpvars.hlen = UDP_HEADER_LEN; + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = sizeof(valid_raw_udp) - p1.udpvars.hlen; + p1.proto = IPPROTO_UDP; + + p2.udpc.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)raw_ipv4; + p2.udph = (UDPHdr *)invalid_raw_udp; + p2.udpvars.hlen = UDP_HEADER_LEN; + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = sizeof(invalid_raw_udp) - p2.udpvars.hlen; + p2.proto = IPPROTO_UDP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv4-csum:valid; " + "msg:\"udpv4-csum keyword check(1)\"; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv4-csum:invalid; " + "msg:\"udpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest31NegativeUDPV4Keyword(void) +{ + uint8_t raw_ipv4[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x43, 0xdc, 0xdc, + 0xc0, 0xa8, 0x01, 0x03}; + + uint8_t valid_raw_udp[] = { + 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0, + 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, + 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63, + 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, + 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b, + 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65, + 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0xc0, 0x26}; + + uint8_t invalid_raw_udp[] = { + 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0, + 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, + 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63, + 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, + 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b, + 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65, + 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0xc0, 0x27}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n" + "\r\n\r\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.udpc.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)raw_ipv4; + p1.udph = (UDPHdr *)valid_raw_udp; + p1.udpvars.hlen = UDP_HEADER_LEN; + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = sizeof(valid_raw_udp) - p1.udpvars.hlen; + p1.proto = IPPROTO_UDP; + + p2.udpc.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)raw_ipv4; + p2.udph = (UDPHdr *)invalid_raw_udp; + p2.udpvars.hlen = UDP_HEADER_LEN; + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = sizeof(invalid_raw_udp) - p2.udpvars.hlen; + p2.proto = IPPROTO_UDP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv4-csum:invalid; " + "msg:\"udpv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv4-csum:valid; " + "msg:\"udpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) { + result &= 0; + } + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + + +int SigTest32UDPV6Keyword(void) +{ + static uint8_t valid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0, + 0x09, 0x00}; + + static uint8_t invalid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0, + 0x09, 0x01}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP\r\n" + "\r\n\r\n"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.udpc.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.udph = (UDPHdr *) (valid_raw_ipv6 + 54); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.udpvars.hlen = UDP_HEADER_LEN; + p1.payload = buf; + p1.payload_len = IPV6_GET_PLEN((&p1)) - p1.udpvars.hlen; + p1.proto = IPPROTO_UDP; + + p2.udpc.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.udph = (UDPHdr *) (invalid_raw_ipv6 + 54); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.udpvars.hlen = UDP_HEADER_LEN; + p2.payload = buf; + p2.payload_len = IPV6_GET_PLEN((&p2)) - p2.udpvars.hlen; + p2.proto = IPPROTO_UDP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv6-csum:valid; " + "msg:\"udpv6-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv6-csum:invalid; " + "msg:\"udpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest33NegativeUDPV6Keyword(void) +{ + static uint8_t valid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0, + 0x09, 0x00}; + + static uint8_t invalid_raw_ipv6[] = { + 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00, + 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0, + 0x09, 0x01}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP\r\n" + "\r\n\r\n"; + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.udpc.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.udph = (UDPHdr *) (valid_raw_ipv6 + 54); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.udpvars.hlen = UDP_HEADER_LEN; + p1.payload = buf; + p1.payload_len = IPV6_GET_PLEN((&p1)) - p1.udpvars.hlen; + p1.proto = IPPROTO_UDP; + + p2.udpc.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.udph = (UDPHdr *) (invalid_raw_ipv6 + 54); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.udpvars.hlen = UDP_HEADER_LEN; + p2.payload = buf; + p2.payload_len = IPV6_GET_PLEN((&p2)) - p2.udpvars.hlen; + p2.proto = IPPROTO_UDP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv6-csum:invalid; " + "msg:\"udpv6-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert udp any any -> any any " + "(content:\"/one/\"; udpv6-csum:valid; " + "msg:\"udpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 0; + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest34ICMPV4Keyword(void) +{ + uint8_t valid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01, + 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01, + 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a, + 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37}; + + uint8_t invalid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01, + 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01, + 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a, + 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x38}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.icmpv4c.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)(valid_raw_ipv4); + p1.icmpv4h = (ICMPV4Hdr *) (valid_raw_ipv4 + IPV4_GET_RAW_HLEN(p1.ip4h) * 4); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_ICMP; + + p2.icmpv4c.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)(invalid_raw_ipv4); + p2.icmpv4h = (ICMPV4Hdr *) (invalid_raw_ipv4 + IPV4_GET_RAW_HLEN(p2.ip4h) * 4); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_ICMP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert icmp any any -> any any " + "(content:\"/one/\"; icmpv4-csum:valid; " + "msg:\"icmpv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert icmp any any -> any any " + "(content:\"/one/\"; icmpv4-csum:invalid; " + "msg:\"icmpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result = 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest35NegativeICMPV4Keyword(void) +{ + uint8_t valid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01, + 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01, + 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a, + 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37}; + + uint8_t invalid_raw_ipv4[] = { + 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01, + 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01, + 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a, + 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x38}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.icmpv4c.comp_csum = -1; + p1.ip4h = (IPV4Hdr *)(valid_raw_ipv4); + p1.icmpv4h = (ICMPV4Hdr *) (valid_raw_ipv4 + IPV4_GET_RAW_HLEN(p1.ip4h) * 4); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_ICMP; + + p2.icmpv4c.comp_csum = -1; + p2.ip4h = (IPV4Hdr *)(invalid_raw_ipv4); + p2.icmpv4h = (ICMPV4Hdr *) (invalid_raw_ipv4 + IPV4_GET_RAW_HLEN(p2.ip4h) * 4); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_ICMP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert icmp any any -> any any " + "(content:\"/one/\"; icmpv4-csum:invalid; " + "msg:\"icmpv4-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert icmp any any -> any any " + "(content:\"/one/\"; icmpv4-csum:valid; " + "msg:\"icmpv4-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 0; + else { + result &= 1; + } + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest36ICMPV6Keyword(void) +{ + uint8_t valid_raw_ipv6[] = { + 0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60, + 0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60, + 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00, + 0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed, + 0x08, 0x00}; + + uint8_t invalid_raw_ipv6[] = { + 0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60, + 0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60, + 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00, + 0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed, + 0x08, 0x01}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.icmpv6c.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.icmpv6h = (ICMPV6Hdr *) (valid_raw_ipv6 + 54); + p1.ip6c.plen = IPV6_GET_PLEN(&(p1)); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_ICMPV6; + + p2.icmpv6c.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.icmpv6h = (ICMPV6Hdr *) (invalid_raw_ipv6 + 54); + p2.ip6c.plen = IPV6_GET_PLEN(&(p2)); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_ICMPV6; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert icmpv6 any any -> any any " + "(content:\"/one/\"; icmpv6-csum:valid; " + "msg:\"icmpv6-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert icmpv6 any any -> any any " + "(content:\"/one/\"; icmpv6-csum:invalid; " + "msg:\"icmpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 1; + else + result &= 0; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 1; + else + result &= 0; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + +int SigTest37NegativeICMPV6Keyword(void) +{ + uint8_t valid_raw_ipv6[] = { + 0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60, + 0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60, + 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00, + 0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed, + 0x08, 0x00}; + + uint8_t invalid_raw_ipv6[] = { + 0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60, + 0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60, + 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00, + 0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe, + 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, + 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0, + 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75, + 0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01, + 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed, + 0x08, 0x01}; + + Packet p1, p2; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 1; + + uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n" + "\r\n\r\n"; + uint16_t buflen = strlen((char *)buf); + + memset(&th_v, 0, sizeof(ThreadVars)); + memset(&p1, 0, sizeof(Packet)); + memset(&p2, 0, sizeof(Packet)); + + p1.icmpv6c.comp_csum = -1; + p1.ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14); + p1.icmpv6h = (ICMPV6Hdr *) (valid_raw_ipv6 + 54); + p1.ip6c.plen = IPV6_GET_PLEN(&(p1)); + p1.src.family = AF_INET; + p1.dst.family = AF_INET; + p1.payload = buf; + p1.payload_len = buflen; + p1.proto = IPPROTO_ICMPV6; + + p2.icmpv6c.comp_csum = -1; + p2.ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14); + p2.icmpv6h = (ICMPV6Hdr *) (invalid_raw_ipv6 + 54); + p2.ip6c.plen = IPV6_GET_PLEN(&(p2)); + p2.src.family = AF_INET; + p2.dst.family = AF_INET; + p2.payload = buf; + p2.payload_len = buflen; + p2.proto = IPPROTO_ICMPV6; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert icmpv6 any any -> any any " + "(content:\"/one/\"; icmpv6-csum:invalid; " + "msg:\"icmpv6-csum keyword check(1)\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result &= 0; + goto end; + } + + de_ctx->sig_list->next = SigInit(de_ctx, + "alert icmpv6 any any -> any any " + "(content:\"/one/\"; icmpv6-csum:valid; " + "msg:\"icmpv6-csum keyword check(1)\"; " + "sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + result &= 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, MPM_B2G); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); + if (PacketAlertCheck(&p1, 1)) + result &= 0; + else + result &= 1; + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); + if (PacketAlertCheck(&p2, 2)) + result &= 0; + else + result &= 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + + #endif /* UNITTESTS */ @@ -4191,6 +5746,37 @@ void SigRegisterTests(void) { UtRegisterTest("SigTest23B2g -- FLOWBIT test (3)", SigTest23B2g, 1); UtRegisterTest("SigTest23B3g -- FLOWBIT test (3)", SigTest23B3g, 1); UtRegisterTest("SigTest23Wm -- FLOWBIT test (3)", SigTest23Wm, 1); + + UtRegisterTest("SigTest24IPV4Keyword", SigTest24IPV4Keyword, 1); + UtRegisterTest("SigTest25NegativeIPV4Keyword", + SigTest25NegativeIPV4Keyword, 1); + + UtRegisterTest("SigTest26TCPV4Keyword", SigTest26TCPV4Keyword, 1); + UtRegisterTest("SigTest27NegativeTCPV4Keyword", + SigTest27NegativeTCPV4Keyword, 1); + + UtRegisterTest("SigTest28TCPV6Keyword", SigTest28TCPV6Keyword, 1); + UtRegisterTest("SigTest29NegativeTCPV6Keyword", + SigTest29NegativeTCPV6Keyword, 1); + + UtRegisterTest("SigTest30UDPV4Keyword", SigTest30UDPV4Keyword, 1); + UtRegisterTest("SigTest31NegativeUDPV4Keyword", + SigTest31NegativeUDPV4Keyword, 1); + + UtRegisterTest("SigTest32UDPV6Keyword", SigTest32UDPV6Keyword, 1); + UtRegisterTest("SigTest33NegativeUDPV6Keyword", + SigTest33NegativeUDPV6Keyword, 1); + + UtRegisterTest("SigTest34ICMPV4Keyword", SigTest34ICMPV4Keyword, 1); + UtRegisterTest("SigTest35NegativeICMPV4Keyword", + SigTest35NegativeICMPV4Keyword, 1); + + /* We need to enable these tests, as soon as we add the ICMPv6 protocol + support in our rules engine */ + //UtRegisterTest("SigTest36ICMPV6Keyword", SigTest36ICMPV6Keyword, 1); + //UtRegisterTest("SigTest37NegativeICMPV6Keyword", + // SigTest37NegativeICMPV6Keyword, 1); + #endif /* UNITTESTS */ } diff --git a/src/detect.h b/src/detect.h index f3f885842b..b5863c0759 100644 --- a/src/detect.h +++ b/src/detect.h @@ -399,6 +399,13 @@ enum { DETECT_PKTVAR, DETECT_NOALERT, DETECT_FLOWBITS, + DETECT_IPV4_CSUM, + DETECT_TCPV4_CSUM, + DETECT_TCPV6_CSUM, + DETECT_UDPV4_CSUM, + DETECT_UDPV6_CSUM, + DETECT_ICMPV4_CSUM, + DETECT_ICMPV6_CSUM, DETECT_ADDRESS, DETECT_PROTO, diff --git a/src/eidps.c b/src/eidps.c index 2ca38e4c69..09a42a42d7 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -156,6 +156,9 @@ Packet *SetupPkt (void) printf("SetupPkt: allocated a new packet...\n"); } + /* reset the packet csum fields */ + RESET_PACKET_CSUMS(p); + return p; }