From 35f3eafa5e44fa028ddc85f554aef6fb7928a13f Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Sun, 12 Jun 2011 17:49:57 +0530 Subject: [PATCH] byte extract added to the engine. Detection support added for packet payload, uri and dce detection engines --- src/Makefile.am | 1 + src/detect-byte-extract.c | 4403 ++++++++++++++++++++++++++++++++ src/detect-byte-extract.h | 74 + src/detect-bytejump.c | 79 +- src/detect-bytejump.h | 8 +- src/detect-bytetest.c | 155 +- src/detect-bytetest.h | 13 +- src/detect-content.h | 6 + src/detect-depth.c | 226 +- src/detect-distance.c | 178 +- src/detect-engine-dcepayload.c | 131 +- src/detect-engine-payload.c | 314 ++- src/detect-engine-uri.c | 556 +++- src/detect-engine.c | 9 + src/detect-offset.c | 233 +- src/detect-within.c | 223 +- src/detect.c | 2 + src/detect.h | 4 + 18 files changed, 6251 insertions(+), 364 deletions(-) create mode 100644 src/detect-byte-extract.c create mode 100644 src/detect-byte-extract.h diff --git a/src/Makefile.am b/src/Makefile.am index c3b64df5d6..6d22a2a6ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -147,6 +147,7 @@ detect-asn1.c detect-asn1.h \ detect-http-stat-code.c detect-http-stat-code.h \ detect-ssl-version.c detect-ssl-version.h \ detect-ssl-state.c detect-ssl-state.h \ +detect-byte-extract.c detect-byte-extract.h \ util-atomic.h \ util-print.c util-print.h \ util-fmemopen.c util-fmemopen.h \ diff --git a/src/detect-byte-extract.c b/src/detect-byte-extract.c new file mode 100644 index 0000000000..2d8da23cb6 --- /dev/null +++ b/src/detect-byte-extract.c @@ -0,0 +1,4403 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Anoop Saldanha + */ + +#include "suricata-common.h" +#include "threads.h" +#include "decode.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-state.h" +#include "detect-content.h" +#include "detect-pcre.h" +#include "detect-bytejump.h" +#include "detect-bytetest.h" +#include "detect-byte-extract.h" + +#include "app-layer-protos.h" + +#include "flow.h" +#include "flow-var.h" +#include "flow-util.h" + +#include "util-byte.h" +#include "util-debug.h" +#include "util-unittest.h" +#include "util-unittest-helper.h" +#include "util-spm.h" + +/* the default value of endianess to be used, if none's specified */ +#define DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT DETECT_BYTE_EXTRACT_ENDIAN_BIG + +/* the base to be used if string mode is specified. These options would be + * specified in DetectByteParseData->base */ +#define DETECT_BYTE_EXTRACT_BASE_NONE 0 +#define DETECT_BYTE_EXTRACT_BASE_HEX 16 +#define DETECT_BYTE_EXTRACT_BASE_DEC 10 +#define DETECT_BYTE_EXTRACT_BASE_OCT 8 + +/* the default value for multiplier. Either ways we always store a + * multiplier, 1 or otherwise, so that we can always multiply the extracted + * value and store it, instead of checking if a multiplier is set or not */ +#define DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT 1 +/* the min/max limit for multiplier */ +#define DETECT_BYTE_EXTRACT_MULTIPLIER_MIN_LIMIT 1 +#define DETECT_BYTE_EXTRACT_MULTIPLIER_MAX_LIMIT 65535 + +/* the max no of bytes that can be extracted in string mode - (string, hex) + * (string, oct) or (string, dec) */ +#define STRING_MAX_BYTES_TO_EXTRACT_FOR_OCT 23 +#define STRING_MAX_BYTES_TO_EXTRACT_FOR_DEC 20 +#define STRING_MAX_BYTES_TO_EXTRACT_FOR_HEX 14 +/* the max no of bytes that can be extraced in non-string mode */ +#define NO_STRING_MAX_BYTES_TO_EXTRACT 8 + +#define PARSE_REGEX "^" \ + "\\s*([0-9]+)\\s*" \ + ",\\s*([0-9]+)\\s*" \ + ",\\s*([0-9a-zA-Z]+)\\s*" \ + "(?:(?:,\\s*([^\\s,]+)\\s*)|(?:,\\s*([^\\s,]+)\\s+([^\\s,]+)\\s*))?" \ + "(?:(?:,\\s*([^\\s,]+)\\s*)|(?:,\\s*([^\\s,]+)\\s+([^\\s,]+)\\s*))?" \ + "(?:(?:,\\s*([^\\s,]+)\\s*)|(?:,\\s*([^\\s,]+)\\s+([^\\s,]+)\\s*))?" \ + "(?:(?:,\\s*([^\\s,]+)\\s*)|(?:,\\s*([^\\s,]+)\\s+([^\\s,]+)\\s*))?" \ + "(?:(?:,\\s*([^\\s,]+)\\s*)|(?:,\\s*([^\\s,]+)\\s+([^\\s,]+)\\s*))?" \ + "$" + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; + +int byte_extract_max_local_id = 0; + +int DetectByteExtractMatch(ThreadVars *, DetectEngineThreadCtx *, + Packet *, Signature *, SigMatch *); +int DetectByteExtractSetup(DetectEngineCtx *, Signature *, char *); +void DetectByteExtractRegisterTests(void); +void DetectByteExtractFree(void *); + +/** + * \brief Registers the keyword handlers for the "byte_extract" keyword. + */ +void DetectByteExtractRegister(void) +{ + const char *eb; + int eo; + int opts = 0; + + sigmatch_table[DETECT_BYTE_EXTRACT].name = "byte_extract"; + sigmatch_table[DETECT_BYTE_EXTRACT].Match = NULL; + sigmatch_table[DETECT_BYTE_EXTRACT].AppLayerMatch = NULL; + sigmatch_table[DETECT_BYTE_EXTRACT].Setup = DetectByteExtractSetup; + sigmatch_table[DETECT_BYTE_EXTRACT].Free = DetectByteExtractFree; + sigmatch_table[DETECT_BYTE_EXTRACT].RegisterTests = DetectByteExtractRegisterTests; + + sigmatch_table[DETECT_BYTE_EXTRACT].flags |= SIGMATCH_PAYLOAD; + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if (parse_regex == NULL) { + SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed " + "at offset %" PRId32 ": %s", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if (eb != NULL) { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + goto error; + } + + return; + error: + return; +} + +int DetectByteExtractDoMatch(DetectEngineThreadCtx *det_ctx, SigMatch *sm, + Signature *s, uint8_t *payload, + uint16_t payload_len, uint64_t *value, + uint8_t endian) +{ + DetectByteExtractData *data = (DetectByteExtractData *)sm->ctx; + uint8_t *ptr = NULL; + int32_t len = 0; + uint64_t val = 0; + int extbytes; + + if (payload_len == 0) { + return 0; + } + + /* Calculate the ptr value for the bytetest and length remaining in + * the packet from that point. + */ + if (data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) { + SCLogDebug("relative, working with det_ctx->payload_offset %"PRIu32", " + "data->offset %"PRIu32"", det_ctx->payload_offset, data->offset); + + ptr = payload + det_ctx->payload_offset; + len = payload_len - det_ctx->payload_offset; + + /* No match if there is no relative base */ + if (len == 0) { + return 0; + } + + ptr += data->offset; + len -= data->offset; + + //PrintRawDataFp(stdout,ptr,len); + } else { + SCLogDebug("absolute, data->offset %"PRIu32"", data->offset); + + ptr = payload + data->offset; + len = payload_len - data->offset; + } + + /* Validate that the to-be-extracted is within the packet */ + if (data->nbytes > len) { + SCLogDebug("Data not within payload pkt=%p, ptr=%p, len=%"PRIu32", nbytes=%d", + payload, ptr, len, data->nbytes); + return 0; + } + + /* Extract the byte data */ + if (data->flags & DETECT_BYTE_EXTRACT_FLAG_STRING) { + extbytes = ByteExtractStringUint64(&val, data->base, + data->nbytes, (const char *)ptr); + if (extbytes <= 0) { + /* strtoull() return 0 if there is no numeric value in data string */ + if (val == 0) { + SCLogDebug("No Numeric value"); + return 0; + } else { + SCLogError(SC_ERR_INVALID_NUM_BYTES, "Error extracting %d " + "bytes of string data: %d", data->nbytes, extbytes); + return -1; + } + } + } else { + int endianness = (endian == DETECT_BYTE_EXTRACT_ENDIAN_BIG) ? + BYTE_BIG_ENDIAN : BYTE_LITTLE_ENDIAN; + extbytes = ByteExtractUint64(&val, endianness, data->nbytes, ptr); + if (extbytes != data->nbytes) { + SCLogError(SC_ERR_INVALID_NUM_BYTES, "Error extracting %d bytes " + "of numeric data: %d\n", data->nbytes, extbytes); + return 0; + } + } + + /* Adjust the jump value based on flags */ + val *= data->multiplier_value; + if (data->flags & DETECT_BYTE_EXTRACT_FLAG_ALIGN) { + if ((val % data->align_value) != 0) { + val += data->align_value - (val % data->align_value); + } + } + + ptr += extbytes; + + det_ctx->payload_offset = ptr - payload; + + *value = val; + + return 1; +} + + +int DetectByteExtractMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + goto end; + end: + return 1; +} + +/** + * \internal + * \brief Used to parse byte_extract arg. + * + * \arg The argument to parse. + * + * \param bed On success an instance containing the parsed data. + * On failure, NULL. + */ +static inline DetectByteExtractData *DetectByteExtractParse(char *arg) +{ + DetectByteExtractData *bed = NULL; +#define MAX_SUBSTRINGS 100 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + char *str_ptr; + int i = 0; + + ret = pcre_exec(parse_regex, parse_regex_study, arg, + strlen(arg), 0, 0, ov, MAX_SUBSTRINGS); + if (ret < 3 || ret > 19) { + SCLogError(SC_ERR_PCRE_PARSE, "parse error, ret %" PRId32 + ", string \"%s\"", ret, arg); + SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid arg to byte_extract : %s " + "for byte_extract", arg); + goto error; + } + + bed = SCMalloc(sizeof(DetectByteExtractData)); + if (bed == NULL) + goto error; + memset(bed, 0, sizeof(DetectByteExtractData)); + + /* no of bytes to extract */ + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, 1, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg 1 for byte_extract"); + goto error; + } + bed->nbytes = atoi(str_ptr); + + /* offset */ + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, 2, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg 2 for byte_extract"); + goto error; + } + int offset = atoi(str_ptr); + if (offset < -65535 || offset > 65535) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract offset invalid - %d. " + "The right offset range is -65535 to 65535", offset); + goto error; + } + bed->offset = offset; + + /* var name */ + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, 3, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg 3 for byte_extract"); + goto error; + } + bed->name = SCStrdup(str_ptr); + if (bed->name == NULL) + goto error; + + /* check out other optional args */ + for (i = 4; i < ret; i++) { + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, i, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg %d for byte_extract", i); + goto error; + } + + if (strcmp("relative", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "relative specified more " + "than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_RELATIVE; + } else if (strcmp("multiplier", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "multiplier specified more " + "than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER; + i++; + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, i, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg %d for byte_extract", i); + goto error; + } + int multiplier = atoi(str_ptr); + if (multiplier < DETECT_BYTE_EXTRACT_MULTIPLIER_MIN_LIMIT || + multiplier > DETECT_BYTE_EXTRACT_MULTIPLIER_MAX_LIMIT) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "multipiler_value invalid " + "- %d. The range is %d-%d", + multiplier, + DETECT_BYTE_EXTRACT_MULTIPLIER_MIN_LIMIT, + DETECT_BYTE_EXTRACT_MULTIPLIER_MAX_LIMIT); + goto error; + } + bed->multiplier_value = multiplier; + } else if (strcmp("big", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "endian option specified " + "more than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_ENDIAN; + bed->endian = DETECT_BYTE_EXTRACT_ENDIAN_BIG; + } else if (strcmp("little", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "endian option specified " + "more than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_ENDIAN; + bed->endian = DETECT_BYTE_EXTRACT_ENDIAN_LITTLE; + } else if (strcmp("dce", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "endian option specified " + "more than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_ENDIAN; + bed->endian = DETECT_BYTE_EXTRACT_ENDIAN_DCE; + } else if (strcmp("string", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_STRING) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "string specified more " + "than once for byte_extract"); + goto error; + } + if (bed->base != DETECT_BYTE_EXTRACT_BASE_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "The right way to specify " + "base is (string, base) and not (base, string) " + "for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_STRING; + } else if (strcmp("hex", str_ptr) == 0) { + if (!(bed->flags & DETECT_BYTE_EXTRACT_FLAG_STRING)) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Base(hex) specified " + "without specifying string. The right way is " + "(string, base) and not (base, string)"); + goto error; + } + if (bed->base != DETECT_BYTE_EXTRACT_BASE_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "More than one base " + "specified for byte_extract"); + goto error; + } + bed->base = DETECT_BYTE_EXTRACT_BASE_HEX; + } else if (strcmp("oct", str_ptr) == 0) { + if (!(bed->flags & DETECT_BYTE_EXTRACT_FLAG_STRING)) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Base(oct) specified " + "without specifying string. The right way is " + "(string, base) and not (base, string)"); + goto error; + } + if (bed->base != DETECT_BYTE_EXTRACT_BASE_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "More than one base " + "specified for byte_extract"); + goto error; + } + bed->base = DETECT_BYTE_EXTRACT_BASE_OCT; + } else if (strcmp("dec", str_ptr) == 0) { + if (!(bed->flags & DETECT_BYTE_EXTRACT_FLAG_STRING)) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Base(dec) specified " + "without specifying string. The right way is " + "(string, base) and not (base, string)"); + goto error; + } + if (bed->base != DETECT_BYTE_EXTRACT_BASE_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "More than one base " + "specified for byte_extract"); + goto error; + } + bed->base = DETECT_BYTE_EXTRACT_BASE_DEC; + } else if (strcmp("align", str_ptr) == 0) { + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ALIGN) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Align specified more " + "than once for byte_extract"); + goto error; + } + bed->flags |= DETECT_BYTE_EXTRACT_FLAG_ALIGN; + i++; + res = pcre_get_substring((char *)arg, ov, + MAX_SUBSTRINGS, i, (const char **)&str_ptr); + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " + "for arg %d in byte_extract", i); + goto error; + } + bed->align_value = atoi(str_ptr); + if (!(bed->align_value == 2 || bed->align_value == 4)) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid align_value for " + "byte_extract - \"%d\"", bed->align_value); + goto error; + } + } else if (strcmp("", str_ptr) == 0) { + ; + } else { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid option - \"%s\" " + "specified in byte_extract", str_ptr); + goto error; + } + } /* for (i = 4; i < ret; i++) */ + + /* validation */ + if (!(bed->flags & DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER)) { + /* default value */ + bed->multiplier_value = DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT; + } + + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_STRING) { + if (bed->base == DETECT_BYTE_EXTRACT_BASE_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Base not specified for " + "byte_extract, though string was specified. " + "The right options are (string, hex), (string, oct) " + "or (string, dec)"); + goto error; + } + if (bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract can't have " + "endian \"big\" or \"little\" specified along with " + "\"string\""); + goto error; + } + if (bed->base == DETECT_BYTE_EXTRACT_BASE_OCT) { + /* if are dealing with octal nos, the max no that can fit in a 8 + * byte value is 01777777777777777777777 */ + if (bed->nbytes > STRING_MAX_BYTES_TO_EXTRACT_FOR_OCT) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract can't process " + "more than %d bytes in \"string\" extraction", + STRING_MAX_BYTES_TO_EXTRACT_FOR_OCT); + goto error; + } + } else if (bed->base == DETECT_BYTE_EXTRACT_BASE_DEC) { + /* if are dealing with decimal nos, the max no that can fit in a 8 + * byte value is 18446744073709551615 */ + if (bed->nbytes > STRING_MAX_BYTES_TO_EXTRACT_FOR_DEC) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract can't process " + "more than %d bytes in \"string\" extraction", + STRING_MAX_BYTES_TO_EXTRACT_FOR_DEC); + goto error; + } + } else if (bed->base == DETECT_BYTE_EXTRACT_BASE_HEX) { + /* if are dealing with hex nos, the max no that can fit in a 8 + * byte value is 0xFFFFFFFFFFFFFFFF */ + if (bed->nbytes > STRING_MAX_BYTES_TO_EXTRACT_FOR_HEX) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract can't process " + "more than %d bytes in \"string\" extraction", + STRING_MAX_BYTES_TO_EXTRACT_FOR_HEX); + goto error; + } + } else { + ; // just a placeholder. we won't reach here. + } + } else { + if (bed->nbytes > NO_STRING_MAX_BYTES_TO_EXTRACT) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "byte_extract can't process " + "more than %d bytes in \"non-string\" extraction", + NO_STRING_MAX_BYTES_TO_EXTRACT); + goto error; + } + /* if string has not been specified and no endian option has been + * specified, then set the default endian level of BIG */ + if (!(bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN)) + bed->endian = DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT; + } + + return bed; + error: + if (bed != NULL) + DetectByteExtractFree(bed); + return NULL; +} + +/** + * \brief The setup function for the byte_extract keyword for a signature. + * + * \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 SigMatch for the current rule + * being parsed. + * \param arg Pointer to the string holding the keyword value. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int DetectByteExtractSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) +{ + DetectByteExtractData *data = NULL; + SigMatch *sm = NULL; + + data = DetectByteExtractParse(arg); + if (data == NULL) + goto error; + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_BYTE_EXTRACT; + sm->ctx = (void *)data; + + /* assign a local id for the byte extract var */ + DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx; + SigMatch *prev_bed_sm = + SigMatchGetLastSMFromLists(s, 6, + DETECT_BYTE_EXTRACT, + s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + DETECT_BYTE_EXTRACT, + s->sm_lists_tail[DETECT_SM_LIST_DMATCH], + DETECT_BYTE_EXTRACT, + s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); + if (prev_bed_sm == NULL) { + /* first one */ + bed->local_id = 0; + } else { + bed->local_id = ((DetectByteExtractData *)prev_bed_sm->ctx)->local_id + 1; + } + if (bed->local_id > byte_extract_max_local_id) + byte_extract_max_local_id = bed->local_id; + + /* check bytetest modifiers against the signature alproto. In case they conflict + * chuck out invalid signature */ + if ((data->endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE) && + (s->alproto != ALPROTO_DCERPC)) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Non dce alproto sig has " + "bytetest with dce enabled"); + goto error; + } + + if (s->alproto == ALPROTO_DCERPC && + data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) { + SigMatch *pm = NULL; + SigMatch *dm = NULL; + + pm = SigMatchGetLastSMFromLists(s, 6, + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + dm = SigMatchGetLastSMFromLists(s, 6, + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], + DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); + + if (pm == NULL) { + SigMatchAppendDcePayload(s, sm); + } else if (dm == NULL) { + SigMatchAppendDcePayload(s, sm); + } else if (pm->idx > dm->idx) { + SigMatchAppendPayload(s, sm); + } else { + SigMatchAppendDcePayload(s, sm); + } + } else { + if (data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) { + SigMatch *pm = + SigMatchGetLastSMFromLists(s, 12, + DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], + DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], + DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], + DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); + if (pm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content " + "or uricontent or pcre option"); + return -1; + } + int list = SigMatchListSMBelongsTo(s, pm); + if (list == DETECT_SM_LIST_UMATCH) + SigMatchAppendUricontent(s,sm); + else + SigMatchAppendPayload(s, sm); + } else { + SigMatchAppendPayload(s, sm); + } + } + + if ( !(data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE)) { + return 0; + } + + SigMatch *prev_sm = NULL; + prev_sm = SigMatchGetLastSMFromLists(s, 8, + DETECT_CONTENT, sm->prev, + DETECT_URICONTENT, sm->prev, + DETECT_BYTEJUMP, sm->prev, + DETECT_PCRE, sm->prev); + if (prev_sm == NULL) { + if (s->alproto == ALPROTO_DCERPC) { + SCLogDebug("No preceding content or pcre keyword. Possible " + "since this is a dce alproto sig."); + return 0; + } else { + SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content " + "or uricontent or pcre option"); + return -1; + } + } + + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectPcreData *pe = NULL; + + switch (prev_sm->type) { + case DETECT_CONTENT: + /* Set the relative next flag on the prev sigmatch */ + cd = (DetectContentData *)prev_sm->ctx; + if (cd == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" + "previous keyword!"); + return -1; + } + cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; + + break; + + case DETECT_URICONTENT: + /* Set the relative next flag on the prev sigmatch */ + ud = (DetectContentData *)prev_sm->ctx; + if (ud == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" + "previous keyword!"); + return -1; + } + ud->flags |= DETECT_CONTENT_RELATIVE_NEXT; + + break; + + case DETECT_PCRE: + pe = (DetectPcreData *)prev_sm->ctx; + if (pe == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" + "previous keyword!"); + return -1; + } + pe->flags |= DETECT_PCRE_RELATIVE_NEXT; + + break; + + case DETECT_BYTEJUMP: + SCLogDebug("No setting relative_next for bytejump. We " + "have no use for it"); + + break; + + default: + /* this will never hit */ + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" + "previous keyword!"); + return -1; + } /* switch */ + + return 0; + +error: + if (data != NULL) + DetectByteExtractFree(data); + if (sm != NULL) + SCFree(sm); + return -1; +} + +/** + * \brief Used to free instances of DetectByteExtractData. + * + * \param ptr Instance of DetectByteExtractData to be freed. + */ +void DetectByteExtractFree(void *ptr) +{ + if (ptr != NULL) { + DetectByteExtractData *bed = ptr; + if (bed->name != NULL) + SCFree((void *)bed->name); + SCFree(bed); + } + + return; +} + +SigMatch *DetectByteExtractRetrieveSMVar(const char *arg, Signature *s, int list) +{ + DetectByteExtractData *bed = NULL; + SigMatch *sm = s->sm_lists[list]; + + while (sm != NULL) { + if (sm->type == DETECT_BYTE_EXTRACT) { + bed = (DetectByteExtractData *)sm->ctx; + if (strcmp(bed->name, arg) == 0) { + return sm; + } + } + sm = sm->next; + } + + return NULL; +} + +/*************************************Unittests********************************/ + +int DetectByteExtractTest01(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != 0 || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest02(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, relative"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_RELATIVE || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest03(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, multiplier 10"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != 10) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest04(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, relative, multiplier 10"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != 10) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest05(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, big"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_ENDIAN || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_BIG || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest06(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, little"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_ENDIAN || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_LITTLE || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest07(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, dce"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_ENDIAN || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DCE || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest08(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, string, hex"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest09(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, string, oct"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_OCT || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest10(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, string, dec"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_DEC || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest11(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_ALIGN || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest12(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, relative"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_ALIGN | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DEFAULT || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest13(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, relative, big"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_ALIGN | + DETECT_BYTE_EXTRACT_FLAG_ENDIAN | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_BIG || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest14(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, relative, dce"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_ALIGN | + DETECT_BYTE_EXTRACT_FLAG_ENDIAN | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_DCE || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest15(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, relative, little"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_ALIGN | + DETECT_BYTE_EXTRACT_FLAG_ENDIAN | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_LITTLE || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest16(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, relative, little, multiplier 2"); + if (bed == NULL) + goto end; + + if (bed->nbytes != 4 || + bed->offset != 2 || + strcmp(bed->name, "one") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_ALIGN | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_ENDIAN | + DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_LITTLE || + bed->base != DETECT_BYTE_EXTRACT_BASE_NONE || + bed->align_value != 4 || + bed->multiplier_value != 2) { + goto end; + } + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest17(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "relative, little, " + "multiplier 2, string hex"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest18(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "relative, little, " + "multiplier 2, " + "relative"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest19(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "relative, little, " + "multiplier 2, " + "little"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest20(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "relative, " + "multiplier 2, " + "align 2"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest21(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "multiplier 2, " + "relative, " + "multiplier 2"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest22(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "string hex, " + "relative, " + "string hex"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest23(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "string hex, " + "relative, " + "string oct"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest24(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("24, 2, one, align 4, " + "string hex, " + "relative"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest25(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("9, 2, one, align 4, " + "little, " + "relative"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest26(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "little, " + "relative, " + "multiplier 65536"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest27(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("4, 2, one, align 4, " + "little, " + "relative, " + "multiplier 0"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest28(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("23, 2, one, string, oct"); + if (bed == NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest29(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("24, 2, one, string, oct"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest30(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("20, 2, one, string, dec"); + if (bed == NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest31(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("21, 2, one, string, dec"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest32(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("14, 2, one, string, hex"); + if (bed == NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest33(void) +{ + int result = 0; + + DetectByteExtractData *bed = DetectByteExtractParse("15, 2, one, string, hex"); + if (bed != NULL) + goto end; + + result = 1; + end: + if (bed != NULL) + DetectByteExtractFree(bed); + return result; +} + +int DetectByteExtractTest34(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,2,two,relative,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 2 || + strncmp(bed->name, "two", cd->content_len) != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest35(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectPcreData *pd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; pcre:/asf/; " + "byte_extract:4,0,two,relative,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_PCRE) { + result = 0; + goto end; + } + pd = (DetectPcreData *)sm->ctx; + if (pd->flags != DETECT_PCRE_RELATIVE_NEXT) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest36(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectBytejumpData *bjd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; byte_jump:1,13; " + "byte_extract:4,0,two,relative,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTEJUMP) { + result = 0; + goto end; + } + bjd = (DetectBytejumpData *)sm->ctx; + if (bjd->flags != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest37(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; uricontent:two; " + "byte_extract:4,0,two,relative,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + ud = (DetectContentData *)sm->ctx; + if (ud->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)ud->content, "two", cd->content_len) != 0 || + ud->flags & DETECT_CONTENT_NOCASE || + ud->flags & DETECT_CONTENT_WITHIN || + ud->flags & DETECT_CONTENT_DISTANCE || + ud->flags & DETECT_CONTENT_FAST_PATTERN || + !(ud->flags & DETECT_CONTENT_RELATIVE_NEXT) || + ud->flags & DETECT_CONTENT_NEGATED ) { + printf("two failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest38(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; uricontent:two; " + "byte_extract:4,0,two,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags !=DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + ud = (DetectContentData *)sm->ctx; + if (ud->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)ud->content, "two", cd->content_len) != 0 || + ud->flags & DETECT_CONTENT_NOCASE || + ud->flags & DETECT_CONTENT_WITHIN || + ud->flags & DETECT_CONTENT_DISTANCE || + ud->flags & DETECT_CONTENT_FAST_PATTERN || + ud->flags & DETECT_CONTENT_RELATIVE_NEXT || + ud->flags & DETECT_CONTENT_NEGATED ) { + printf("two failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + result = 0; + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest39(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; content:two; http_uri; " + "byte_extract:4,0,two,relative,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + ud = (DetectContentData *)sm->ctx; + if (ud->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)ud->content, "two", cd->content_len) != 0 || + ud->flags & DETECT_CONTENT_NOCASE || + ud->flags & DETECT_CONTENT_WITHIN || + ud->flags & DETECT_CONTENT_DISTANCE || + ud->flags & DETECT_CONTENT_FAST_PATTERN || + !(ud->flags & DETECT_CONTENT_RELATIVE_NEXT) || + ud->flags & DETECT_CONTENT_NEGATED ) { + printf("two failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest40(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; content:two; http_uri; " + "byte_extract:4,0,two,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags !=DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + ud = (DetectContentData *)sm->ctx; + if (ud->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)ud->content, "two", cd->content_len) != 0 || + ud->flags & DETECT_CONTENT_NOCASE || + ud->flags & DETECT_CONTENT_WITHIN || + ud->flags & DETECT_CONTENT_DISTANCE || + ud->flags & DETECT_CONTENT_FAST_PATTERN || + ud->flags & DETECT_CONTENT_RELATIVE_NEXT || + ud->flags & DETECT_CONTENT_NEGATED ) { + printf("two failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + result = 0; + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest41(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "three") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 1) { + result = 0; + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest42(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectContentData *ud = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "uricontent: three; " + "byte_extract:4,0,four,string,hex,relative; " + "byte_extract:4,0,five,string,hex; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "five") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 2) { + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + ud = (DetectContentData *)sm->ctx; + if (ud->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)ud->content, "three", cd->content_len) != 0 || + ud->flags & DETECT_CONTENT_NOCASE || + ud->flags & DETECT_CONTENT_WITHIN || + ud->flags & DETECT_CONTENT_DISTANCE || + ud->flags & DETECT_CONTENT_FAST_PATTERN || + !(ud->flags & DETECT_CONTENT_RELATIVE_NEXT) || + ud->flags & DETECT_CONTENT_NEGATED ) { + printf("two failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "four") != 0 || + bed->flags != (DETECT_BYTE_EXTRACT_FLAG_RELATIVE | + DETECT_BYTE_EXTRACT_FLAG_STRING) || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 1) { + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest43(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "content: three; offset:two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "three", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_OFFSET) || + cd->offset != bed->local_id) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest44(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "content: four; offset:two; " + "content: five; offset:three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_OFFSET) || + cd->offset != bed1->local_id) { + printf("four failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "five", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_OFFSET) || + cd->offset != bed2->local_id) { + printf("five failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest45(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "content: three; depth:two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "three", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_DEPTH) || + cd->depth != bed->local_id || + cd->offset != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest46(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "content: four; depth:two; " + "content: five; depth:three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_DEPTH) || + cd->depth != bed1->local_id) { + printf("four failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "five", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_DEPTH) || + cd->depth != bed2->local_id) { + printf("five failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest47(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "content: three; distance:two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "three", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DISTANCE) || + cd->distance != bed->local_id || + cd->offset != 0 || + cd->depth != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest48(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "content: four; distance:two; " + "content: five; distance:three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DISTANCE | + DETECT_CONTENT_RELATIVE_NEXT) || + cd->distance != bed1->local_id || + cd->depth != 0 || + cd->offset != 0) { + printf("four failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "five", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DISTANCE) || + cd->distance != bed2->local_id || + cd->depth != 0 || + cd->offset != 0) { + printf("five failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest49(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "content: three; within:two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "three", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_WITHIN) || + cd->within != bed->local_id || + cd->offset != 0 || + cd->depth != 0 || + cd->distance != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest50(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "content: four; within:two; " + "content: five; within:three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_WITHIN| + DETECT_CONTENT_RELATIVE_NEXT) || + cd->within != bed1->local_id || + cd->depth != 0 || + cd->offset != 0 || + cd->distance != 0) { + printf("four failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "five", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_WITHIN) || + cd->within != bed2->local_id || + cd->depth != 0 || + cd->offset != 0 || + cd->distance != 0) { + printf("five failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest51(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + DetectBytetestData *btd = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_test: 2,=,10, two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTETEST) { + result = 0; + goto end; + } + btd = (DetectBytetestData *)sm->ctx; + if (btd->flags != DETECT_BYTETEST_OFFSET_BE || + btd->value != 10 || + btd->offset != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest52(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + DetectBytetestData *btd = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "byte_test: 2,=,two,three; " + "byte_test: 3,=,10,three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTETEST) { + result = 0; + goto end; + } + btd = (DetectBytetestData *)sm->ctx; + if (btd->flags != (DETECT_BYTETEST_OFFSET_BE | + DETECT_BYTETEST_VALUE_BE) || + btd->value != 0 || + btd->offset != 1) { + printf("three failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTETEST) { + result = 0; + goto end; + } + btd = (DetectBytetestData *)sm->ctx; + if (btd->flags != DETECT_BYTETEST_OFFSET_BE || + btd->value != 10 || + btd->offset != 1) { + printf("four failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + + + + + + + + + + + + + + + + + + + + +int DetectByteExtractTest53(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed = NULL; + DetectBytejumpData *bjd = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_jump: 2,two; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed = (DetectByteExtractData *)sm->ctx; + if (bed->nbytes != 4 || + bed->offset != 0 || + strcmp(bed->name, "two") != 0 || + bed->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed->align_value != 0 || + bed->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTEJUMP) { + result = 0; + goto end; + } + bjd = (DetectBytejumpData *)sm->ctx; + if (bjd->flags != DETECT_BYTEJUMP_OFFSET_BE || + bjd->offset != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest54(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + DetectBytejumpData *bjd = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "byte_jump: 2,two; " + "byte_jump: 3,three; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTEJUMP) { + result = 0; + goto end; + } + bjd = (DetectBytejumpData *)sm->ctx; + if (bjd->flags != DETECT_BYTEJUMP_OFFSET_BE || + bjd->offset != 0) { + printf("three failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTEJUMP) { + result = 0; + goto end; + } + bjd = (DetectBytejumpData *)sm->ctx; + if (bjd->flags != DETECT_BYTEJUMP_OFFSET_BE || + bjd->offset != 1) { + printf("four failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest55(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + DetectByteExtractData *bed3 = NULL; + DetectByteExtractData *bed4 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "byte_extract:4,0,four,string,hex; " + "byte_extract:4,0,five,string,hex; " + "content: four; within:two; distance:three; offset:four; depth:five; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed3 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed4 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_DISTANCE | + DETECT_CONTENT_DEPTH | + DETECT_CONTENT_OFFSET | + DETECT_CONTENT_WITHIN) || + cd->within != bed1->local_id || + cd->distance != bed2->local_id || + cd->offset != bed3->local_id || + cd->depth != bed4->local_id) { + printf("four failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest56(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + DetectByteExtractData *bed3 = NULL; + DetectByteExtractData *bed4 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "uricontent:urione; " + "content:one; " + "byte_extract:4,0,two,string,hex; " + "byte_extract:4,0,three,string,hex; " + "byte_extract:4,0,four,string,hex; " + "byte_extract:4,0,five,string,hex; " + "content: four; within:two; distance:three; offset:four; depth:five; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "urione", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != DETECT_BYTE_EXTRACT_FLAG_STRING || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed3 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed4 = (DetectByteExtractData *)sm->ctx; + + sm = sm->next; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_DISTANCE | + DETECT_CONTENT_DEPTH | + DETECT_CONTENT_OFFSET | + DETECT_CONTENT_WITHIN) || + cd->within != bed1->local_id || + cd->distance != bed2->local_id || + cd->offset != bed3->local_id || + cd->depth != bed4->local_id) { + printf("four failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +int DetectByteExtractTest57(void) +{ + DetectEngineCtx *de_ctx = NULL; + int result = 0; + Signature *s = NULL; + SigMatch *sm = NULL; + DetectContentData *cd = NULL; + DetectByteExtractData *bed1 = NULL; + DetectByteExtractData *bed2 = NULL; + DetectByteExtractData *bed3 = NULL; + DetectByteExtractData *bed4 = NULL; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + + de_ctx->flags |= DE_QUIET; + s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"Testing bytejump_body\"; " + "content:one; " + "uricontent: urione; " + "byte_extract:4,0,two,string,hex,relative; " + "byte_extract:4,0,three,string,hex,relative; " + "byte_extract:4,0,four,string,hex,relative; " + "byte_extract:4,0,five,string,hex,relative; " + "uricontent: four; within:two; distance:three; offset:four; depth:five; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { + result = 0; + goto end; + } + + sm = s->sm_lists[DETECT_SM_LIST_PMATCH]; + if (sm->type != DETECT_CONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "one", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + cd->flags & DETECT_CONTENT_RELATIVE_NEXT || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) + goto end; + + sm = s->sm_lists[DETECT_SM_LIST_UMATCH]; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (cd->flags & DETECT_CONTENT_RAWBYTES || + strncmp((char *)cd->content, "urione", cd->content_len) != 0 || + cd->flags & DETECT_CONTENT_NOCASE || + cd->flags & DETECT_CONTENT_WITHIN || + cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_FAST_PATTERN || + !(cd->flags & DETECT_CONTENT_RELATIVE_NEXT) || + cd->flags & DETECT_CONTENT_NEGATED ) { + printf("one failed\n"); + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed1 = (DetectByteExtractData *)sm->ctx; + if (bed1->nbytes != 4 || + bed1->offset != 0 || + strcmp(bed1->name, "two") != 0 || + bed1->flags != (DETECT_BYTE_EXTRACT_FLAG_STRING | + DETECT_BYTE_EXTRACT_FLAG_RELATIVE) || + bed1->endian != DETECT_BYTE_EXTRACT_ENDIAN_NONE || + bed1->base != DETECT_BYTE_EXTRACT_BASE_HEX || + bed1->align_value != 0 || + bed1->multiplier_value != DETECT_BYTE_EXTRACT_MULTIPLIER_DEFAULT) { + goto end; + } + if (bed1->local_id != 0) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed2 = (DetectByteExtractData *)sm->ctx; + if (bed2->local_id != 1) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed3 = (DetectByteExtractData *)sm->ctx; + if (bed3->local_id != 2) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_BYTE_EXTRACT) { + result = 0; + goto end; + } + bed4 = (DetectByteExtractData *)sm->ctx; + if (bed4->local_id != 3) { + result = 0; + goto end; + } + + sm = sm->next; + if (sm->type != DETECT_URICONTENT) { + result = 0; + goto end; + } + cd = (DetectContentData *)sm->ctx; + if (strncmp((char *)cd->content, "four", cd->content_len) != 0 || + cd->flags != (DETECT_CONTENT_DISTANCE_BE | + DETECT_CONTENT_DEPTH_BE | + DETECT_CONTENT_OFFSET_BE | + DETECT_CONTENT_WITHIN_BE | + DETECT_CONTENT_DISTANCE | + DETECT_CONTENT_DEPTH | + DETECT_CONTENT_OFFSET | + DETECT_CONTENT_WITHIN) || + cd->within != bed1->local_id || + cd->distance != bed2->local_id || + cd->offset != bed3->local_id || + cd->depth != bed4->local_id) { + printf("four failed\n"); + result = 0; + goto end; + } + + if (sm->next != NULL) { + goto end; + } + + result = 1; + + end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +void DetectByteExtractRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("DetectByteExtractTest01", DetectByteExtractTest01, 1); + UtRegisterTest("DetectByteExtractTest02", DetectByteExtractTest02, 1); + UtRegisterTest("DetectByteExtractTest03", DetectByteExtractTest03, 1); + UtRegisterTest("DetectByteExtractTest04", DetectByteExtractTest04, 1); + UtRegisterTest("DetectByteExtractTest05", DetectByteExtractTest05, 1); + UtRegisterTest("DetectByteExtractTest06", DetectByteExtractTest06, 1); + UtRegisterTest("DetectByteExtractTest07", DetectByteExtractTest07, 1); + UtRegisterTest("DetectByteExtractTest08", DetectByteExtractTest08, 1); + UtRegisterTest("DetectByteExtractTest09", DetectByteExtractTest09, 1); + UtRegisterTest("DetectByteExtractTest10", DetectByteExtractTest10, 1); + UtRegisterTest("DetectByteExtractTest11", DetectByteExtractTest11, 1); + UtRegisterTest("DetectByteExtractTest12", DetectByteExtractTest12, 1); + UtRegisterTest("DetectByteExtractTest13", DetectByteExtractTest13, 1); + UtRegisterTest("DetectByteExtractTest14", DetectByteExtractTest14, 1); + UtRegisterTest("DetectByteExtractTest15", DetectByteExtractTest15, 1); + UtRegisterTest("DetectByteExtractTest16", DetectByteExtractTest16, 1); + UtRegisterTest("DetectByteExtractTest17", DetectByteExtractTest17, 1); + UtRegisterTest("DetectByteExtractTest18", DetectByteExtractTest18, 1); + UtRegisterTest("DetectByteExtractTest19", DetectByteExtractTest19, 1); + UtRegisterTest("DetectByteExtractTest20", DetectByteExtractTest20, 1); + UtRegisterTest("DetectByteExtractTest21", DetectByteExtractTest21, 1); + UtRegisterTest("DetectByteExtractTest22", DetectByteExtractTest22, 1); + UtRegisterTest("DetectByteExtractTest23", DetectByteExtractTest23, 1); + UtRegisterTest("DetectByteExtractTest24", DetectByteExtractTest24, 1); + UtRegisterTest("DetectByteExtractTest25", DetectByteExtractTest25, 1); + UtRegisterTest("DetectByteExtractTest26", DetectByteExtractTest26, 1); + UtRegisterTest("DetectByteExtractTest27", DetectByteExtractTest27, 1); + UtRegisterTest("DetectByteExtractTest28", DetectByteExtractTest28, 1); + UtRegisterTest("DetectByteExtractTest29", DetectByteExtractTest29, 1); + UtRegisterTest("DetectByteExtractTest30", DetectByteExtractTest30, 1); + UtRegisterTest("DetectByteExtractTest31", DetectByteExtractTest31, 1); + UtRegisterTest("DetectByteExtractTest32", DetectByteExtractTest32, 1); + UtRegisterTest("DetectByteExtractTest33", DetectByteExtractTest33, 1); + UtRegisterTest("DetectByteExtractTest34", DetectByteExtractTest34, 1); + UtRegisterTest("DetectByteExtractTest35", DetectByteExtractTest35, 1); + UtRegisterTest("DetectByteExtractTest36", DetectByteExtractTest36, 1); + UtRegisterTest("DetectByteExtractTest37", DetectByteExtractTest37, 1); + UtRegisterTest("DetectByteExtractTest38", DetectByteExtractTest38, 1); + UtRegisterTest("DetectByteExtractTest39", DetectByteExtractTest39, 1); + UtRegisterTest("DetectByteExtractTest40", DetectByteExtractTest40, 1); + UtRegisterTest("DetectByteExtractTest41", DetectByteExtractTest41, 1); + UtRegisterTest("DetectByteExtractTest42", DetectByteExtractTest42, 1); + + UtRegisterTest("DetectByteExtractTest43", DetectByteExtractTest43, 1); + UtRegisterTest("DetectByteExtractTest44", DetectByteExtractTest44, 1); + + UtRegisterTest("DetectByteExtractTest45", DetectByteExtractTest45, 1); + UtRegisterTest("DetectByteExtractTest46", DetectByteExtractTest46, 1); + + UtRegisterTest("DetectByteExtractTest47", DetectByteExtractTest47, 1); + UtRegisterTest("DetectByteExtractTest48", DetectByteExtractTest48, 1); + + UtRegisterTest("DetectByteExtractTest49", DetectByteExtractTest49, 1); + UtRegisterTest("DetectByteExtractTest50", DetectByteExtractTest50, 1); + + UtRegisterTest("DetectByteExtractTest51", DetectByteExtractTest51, 1); + UtRegisterTest("DetectByteExtractTest52", DetectByteExtractTest52, 1); + + UtRegisterTest("DetectByteExtractTest53", DetectByteExtractTest53, 1); + UtRegisterTest("DetectByteExtractTest54", DetectByteExtractTest54, 1); + + UtRegisterTest("DetectByteExtractTest55", DetectByteExtractTest55, 1); + UtRegisterTest("DetectByteExtractTest56", DetectByteExtractTest56, 1); + UtRegisterTest("DetectByteExtractTest57", DetectByteExtractTest57, 1); +#endif /* UNITTESTS */ + + return; +} diff --git a/src/detect-byte-extract.h b/src/detect-byte-extract.h new file mode 100644 index 0000000000..0c13fbfae1 --- /dev/null +++ b/src/detect-byte-extract.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Anoop Saldanha + */ + +#ifndef __DETECT_BYTEEXTRACT_H__ +#define __DETECT_BYTEEXTRACT_H__ + +/* flags */ +#define DETECT_BYTE_EXTRACT_FLAG_RELATIVE 0x01 +#define DETECT_BYTE_EXTRACT_FLAG_MULTIPLIER 0x02 +#define DETECT_BYTE_EXTRACT_FLAG_STRING 0x04 +#define DETECT_BYTE_EXTRACT_FLAG_ALIGN 0x08 +#define DETECT_BYTE_EXTRACT_FLAG_ENDIAN 0x10 + +/* endian value to be used. Would be stored in DetectByteParseData->endian */ +#define DETECT_BYTE_EXTRACT_ENDIAN_NONE 0 +#define DETECT_BYTE_EXTRACT_ENDIAN_BIG 1 +#define DETECT_BYTE_EXTRACT_ENDIAN_LITTLE 2 +#define DETECT_BYTE_EXTRACT_ENDIAN_DCE 3 + +/** + * \brief Holds data related to byte_extract keyword. + */ +typedef struct DetectByteExtractData_ { + /* local id used by other keywords in the sig to reference this */ + uint8_t local_id; + + uint8_t nbytes; + int16_t pad; + int32_t offset; + const char *name; + uint8_t flags; + uint8_t endian; + uint8_t base; + uint8_t align_value; + + uint16_t multiplier_value; + /* unique id used to reference this byte_extract keyword */ + uint16_t id; + +} DetectByteExtractData; + +/* the max local id used amongst all sigs */ +extern int byte_extract_max_local_id; + +void DetectByteExtractRegister(void); +int DetectByteExtractSetup(DetectEngineCtx *, Signature *, char *); +void DetectByteExtractFree(void *); +int DetectByteExtractMatch(ThreadVars *, DetectEngineThreadCtx *, + Packet *, Signature *, SigMatch *); +SigMatch *DetectByteExtractRetrieveSMVar(const char *, Signature *, int); +int DetectByteExtractDoMatch(DetectEngineThreadCtx *, SigMatch *, Signature *, + uint8_t *, uint16_t, uint64_t *, uint8_t); + +#endif /* __DETECT_BYTEEXTRACT_H__ */ diff --git a/src/detect-bytejump.c b/src/detect-bytejump.c index 8b3d2b322d..58e8ec3629 100644 --- a/src/detect-bytejump.c +++ b/src/detect-bytejump.c @@ -32,6 +32,7 @@ #include "app-layer.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "detect-content.h" #include "detect-uricontent.h" @@ -105,7 +106,8 @@ error: * \retval 0 no match */ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, - SigMatch *m, uint8_t *payload, uint32_t payload_len) + SigMatch *m, uint8_t *payload, uint32_t payload_len, + uint8_t flags, int32_t offset) { SCEnter(); @@ -123,7 +125,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, /* Calculate the ptr value for the bytejump and length remaining in * the packet from that point. */ - if (data->flags & DETECT_BYTEJUMP_RELATIVE) { + if (flags & DETECT_BYTEJUMP_RELATIVE) { ptr = payload + det_ctx->payload_offset; len = payload_len - det_ctx->payload_offset; @@ -132,12 +134,12 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SCReturnInt(0); } - ptr += data->offset; - len -= data->offset; + ptr += offset; + len -= offset; } else { - ptr = payload + data->offset; - len = payload_len - data->offset; + ptr = payload + offset; + len = payload_len - offset; } /* Verify the to-be-extracted data is within the packet */ @@ -149,7 +151,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, } /* Extract the byte data */ - if (data->flags & DETECT_BYTEJUMP_STRING) { + if (flags & DETECT_BYTEJUMP_STRING) { extbytes = ByteExtractStringUint64(&val, data->base, data->nbytes, (const char *)ptr); if(extbytes <= 0) { @@ -159,7 +161,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, } } else { - int endianness = (data->flags & DETECT_BYTEJUMP_LITTLE) ? BYTE_LITTLE_ENDIAN : BYTE_BIG_ENDIAN; + int endianness = (flags & DETECT_BYTEJUMP_LITTLE) ? BYTE_LITTLE_ENDIAN : BYTE_BIG_ENDIAN; extbytes = ByteExtractUint64(&val, endianness, data->nbytes, ptr); if (extbytes != data->nbytes) { SCLogError(SC_ERR_BYTE_EXTRACT_FAILED,"Error extracting %d bytes " @@ -172,7 +174,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, /* Adjust the jump value based on flags */ val *= data->multiplier; - if (data->flags & DETECT_BYTEJUMP_ALIGN) { + if (flags & DETECT_BYTEJUMP_ALIGN) { if ((val % 4) != 0) { val += 4 - (val % 4); } @@ -180,7 +182,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, val += extbytes + data->post_offset; /* Calculate the jump location */ - if (data->flags & DETECT_BYTEJUMP_BEGIN) { + if (flags & DETECT_BYTEJUMP_BEGIN) { jumpptr = payload + val; //printf("NEWVAL: payload %p + %ld = %p\n", p->payload, val, jumpptr); } @@ -201,7 +203,7 @@ int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, #ifdef DEBUG if (SCLogDebugEnabled()) { - uint8_t *sptr = (data->flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr; + uint8_t *sptr = (flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr; SCLogDebug("jumping %" PRId64 " bytes from %p (%08x) to %p (%08x)", val, sptr, (int)(sptr - payload), jumpptr, (int)(jumpptr - payload)); @@ -323,7 +325,7 @@ int DetectBytejumpMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, return 1; } -DetectBytejumpData *DetectBytejumpParse(char *optstr) +DetectBytejumpData *DetectBytejumpParse(char *optstr, char **offset) { DetectBytejumpData *data = NULL; char *args[10] = { @@ -412,12 +414,23 @@ DetectBytejumpData *DetectBytejumpParse(char *optstr) } /* Offset */ - if (ByteExtractStringInt32(&data->offset, 0, strlen(args[1]), args[1]) <= 0) { - SCLogError(SC_ERR_INVALID_VALUE, "Malformed offset: %s", optstr); - goto error; + if (args[1][0] != '-' && isalpha(args[1][0])) { + if (offset == NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "byte_jump supplied with " + "var name for offset. \"value\" argument supplied to " + "this function has to be non-NULL"); + goto error; + } + *offset = SCStrdup(args[1]); + if (*offset == NULL) + goto error; + } else { + if (ByteExtractStringInt32(&data->offset, 0, strlen(args[1]), args[1]) <= 0) { + SCLogError(SC_ERR_INVALID_VALUE, "Malformed offset: %s", optstr); + goto error; + } } - /* The remaining options are flags. */ /** \todo Error on dups? */ for (i = 2; i < numargs; i++) { @@ -514,8 +527,9 @@ int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) { DetectBytejumpData *data = NULL; SigMatch *sm = NULL; + char *offset = NULL; - data = DetectBytejumpParse(optstr); + data = DetectBytejumpParse(optstr, &offset); if (data == NULL) goto error; @@ -574,6 +588,21 @@ int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) SigMatchAppendPayload(s, sm); } + if (offset != NULL) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(offset, s, + SigMatchListSMBelongsTo(s, sm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in byte_jump - %s\n", offset); + goto error; + } + DetectBytejumpData *bjd = sm->ctx; + bjd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + bjd->flags |= DETECT_BYTEJUMP_OFFSET_BE; + SCFree(offset); + } + if ( !(data->flags & DETECT_BYTEJUMP_RELATIVE)) { return(0); } @@ -681,7 +710,7 @@ void DetectBytejumpFree(void *ptr) int DetectBytejumpTestParse01(void) { int result = 0; DetectBytejumpData *data = NULL; - data = DetectBytejumpParse("4,0"); + data = DetectBytejumpParse("4,0", NULL); if (data != NULL) { DetectBytejumpFree(data); result = 1; @@ -696,7 +725,7 @@ int DetectBytejumpTestParse01(void) { int DetectBytejumpTestParse02(void) { int result = 0; DetectBytejumpData *data = NULL; - data = DetectBytejumpParse("4, 0"); + data = DetectBytejumpParse("4, 0", NULL); if (data != NULL) { if ( (data->nbytes == 4) && (data->offset == 0) @@ -720,7 +749,7 @@ int DetectBytejumpTestParse03(void) { int result = 0; DetectBytejumpData *data = NULL; data = DetectBytejumpParse(" 4,0 , relative , little, string, " - "dec, align, from_beginning"); + "dec, align, from_beginning", NULL); if (data != NULL) { if ( (data->nbytes == 4) && (data->offset == 0) @@ -752,7 +781,7 @@ int DetectBytejumpTestParse04(void) { DetectBytejumpData *data = NULL; data = DetectBytejumpParse(" 4,0 , relative , little, string, " "dec, align, from_beginning , " - "multiplier 2 , post_offset -16 "); + "multiplier 2 , post_offset -16 ", NULL); if (data != NULL) { if ( (data->nbytes == 4) && (data->offset == 0) @@ -780,7 +809,7 @@ int DetectBytejumpTestParse05(void) { int result = 0; DetectBytejumpData *data = NULL; data = DetectBytejumpParse(" 4,0 , relative , little, dec, " - "align, from_beginning"); + "align, from_beginning", NULL); if (data == NULL) { result = 1; } @@ -794,7 +823,7 @@ int DetectBytejumpTestParse05(void) { int DetectBytejumpTestParse06(void) { int result = 0; DetectBytejumpData *data = NULL; - data = DetectBytejumpParse("9, 0"); + data = DetectBytejumpParse("9, 0", NULL); if (data == NULL) { result = 1; } @@ -808,7 +837,7 @@ int DetectBytejumpTestParse06(void) { int DetectBytejumpTestParse07(void) { int result = 0; DetectBytejumpData *data = NULL; - data = DetectBytejumpParse("24, 0, string, dec"); + data = DetectBytejumpParse("24, 0, string, dec", NULL); if (data == NULL) { result = 1; } @@ -822,7 +851,7 @@ int DetectBytejumpTestParse07(void) { int DetectBytejumpTestParse08(void) { int result = 0; DetectBytejumpData *data = NULL; - data = DetectBytejumpParse("4, 0xffffffffffffffff"); + data = DetectBytejumpParse("4, 0xffffffffffffffff", NULL); if (data == NULL) { result = 1; } diff --git a/src/detect-bytejump.h b/src/detect-bytejump.h index ca0afbf00e..e7a8eabb65 100644 --- a/src/detect-bytejump.h +++ b/src/detect-bytejump.h @@ -38,6 +38,7 @@ #define DETECT_BYTEJUMP_RELATIVE 0x10 /**< "relative" offset */ #define DETECT_BYTEJUMP_ALIGN 0x20 /**< "align" offset */ #define DETECT_BYTEJUMP_DCE 0x40 /**< "dce" enabled */ +#define DETECT_BYTEJUMP_OFFSET_BE 0x80 /**< "byte extract" enabled */ typedef struct DetectBytejumpData_ { uint8_t nbytes; /**< Number of bytes to compare */ @@ -86,11 +87,13 @@ void DetectBytejumpFree(void *ptr); * "align", "from beginning", "multiplier N", "post_offset N" * * \param optstr Pointer to the user provided byte_jump options + * \param offset Used to pass the offset back, if byte_jump uses a byte_extract + * var. * * \retval data pointer to DetectBytejumpData on success * \retval NULL on failure */ -DetectBytejumpData *DetectBytejumpParse(char *optstr); +DetectBytejumpData *DetectBytejumpParse(char *optstr, char **offset); /** * This function is used to match byte_jump @@ -111,7 +114,8 @@ DetectBytejumpData *DetectBytejumpParse(char *optstr); */ int DetectBytejumpMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m); -int DetectBytejumpDoMatch(DetectEngineThreadCtx *, Signature *, SigMatch *, uint8_t *, uint32_t); +int DetectBytejumpDoMatch(DetectEngineThreadCtx *, Signature *, SigMatch *, + uint8_t *, uint32_t, uint8_t, int32_t); #endif /* __DETECT_BYTEJUMP_H__ */ diff --git a/src/detect-bytetest.c b/src/detect-bytetest.c index 68f1e1d8bb..3755c27590 100644 --- a/src/detect-bytetest.c +++ b/src/detect-bytetest.c @@ -34,6 +34,7 @@ #include "detect-uricontent.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "app-layer.h" #include "util-byte.h" @@ -109,7 +110,8 @@ error: * \retval 1 match * \retval 0 no match */ -int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *m, uint8_t *payload, uint32_t payload_len) { +int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *m, uint8_t *payload, uint32_t payload_len, + uint8_t flags, int32_t offset, uint64_t value) { SCEnter(); DetectBytetestData *data = (DetectBytetestData *)m->ctx; @@ -127,7 +129,7 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch /* Calculate the ptr value for the bytetest and length remaining in * the packet from that point. */ - if (data->flags & DETECT_BYTETEST_RELATIVE) { + if (flags & DETECT_BYTETEST_RELATIVE) { SCLogDebug("relative, working with det_ctx->payload_offset %"PRIu32", " "data->offset %"PRIu32"", det_ctx->payload_offset, data->offset); @@ -139,16 +141,16 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch SCReturnInt(0); } - ptr += data->offset; - len -= data->offset; + ptr += offset; + len -= offset; //PrintRawDataFp(stdout,ptr,len); } else { SCLogDebug("absolute, data->offset %"PRIu32"", data->offset); - ptr = payload + data->offset; - len = payload_len - data->offset; + ptr = payload + offset; + len = payload_len - offset; } /* Validate that the to-be-extracted is within the packet @@ -160,10 +162,10 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch SCReturnInt(0); } - neg = data->flags & DETECT_BYTETEST_NEGOP; + neg = flags & DETECT_BYTETEST_NEGOP; /* Extract the byte data */ - if (data->flags & DETECT_BYTETEST_STRING) { + if (flags & DETECT_BYTETEST_STRING) { extbytes = ByteExtractStringUint64(&val, data->base, data->nbytes, (const char *)ptr); if (extbytes <= 0) { @@ -182,7 +184,7 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch data->base, val, (neg ? "!" : ""), data->op, data->value); } else { - int endianness = (data->flags & DETECT_BYTETEST_LITTLE) ? + int endianness = (flags & DETECT_BYTETEST_LITTLE) ? BYTE_LITTLE_ENDIAN : BYTE_BIG_ENDIAN; extbytes = ByteExtractUint64(&val, endianness, data->nbytes, ptr); if (extbytes != data->nbytes) { @@ -195,42 +197,41 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch val, (neg ? "!" : ""), data->op, data->value); } - /* Compare using the configured operator */ match = 0; switch (data->op) { case DETECT_BYTETEST_OP_EQ: - if (val == data->value) { + if (val == value) { match = 1; } break; case DETECT_BYTETEST_OP_LT: - if (val < data->value) { + if (val < value) { match = 1; } break; case DETECT_BYTETEST_OP_GT: - if (val > data->value) { + if (val > value) { match = 1; } break; case DETECT_BYTETEST_OP_AND: - if (val & data->value) { + if (val & value) { match = 1; } break; case DETECT_BYTETEST_OP_OR: - if (val ^ data->value) { + if (val ^ value) { match = 1; } break; case DETECT_BYTETEST_OP_GE: - if (val >= data->value) { + if (val >= value) { match = 1; } break; case DETECT_BYTETEST_OP_LE: - if (val <= data->value) { + if (val <= value) { match = 1; } break; @@ -253,7 +254,8 @@ int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch int DetectBytetestMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { - return DetectBytetestDoMatch(det_ctx, s, m, p->payload, p->payload_len); + return DetectBytetestDoMatch(det_ctx, s, m, p->payload, p->payload_len, + ((DetectBytetestData *)m->ctx)->flags, 0, 0); #if 0 DetectBytetestData *data = (DetectBytetestData *)m->ctx; uint8_t *ptr = NULL; @@ -376,7 +378,7 @@ int DetectBytetestMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, #endif } -DetectBytetestData *DetectBytetestParse(char *optstr) +DetectBytetestData *DetectBytetestParse(char *optstr, char **value, char **offset) { DetectBytetestData *data = NULL; char *args[9] = { @@ -457,18 +459,41 @@ DetectBytetestData *DetectBytetestParse(char *optstr) } /* Value */ - if (ByteExtractStringUint64(&data->value, 0, 0, args[3]) <= 0) { - SCLogError(SC_ERR_INVALID_VALUE, "Malformed value: %s", str_ptr); - goto error; + if (args[3][0] != '-' && isalpha(args[3][0])) { + if (value == NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "byte_test supplied with " + "var name for value. \"value\" argument supplied to " + "this function has to be non-NULL"); + goto error; + } + *value = SCStrdup(args[3]); + if (*value == NULL) + goto error; + } else { + if (ByteExtractStringUint64(&data->value, 0, 0, args[3]) <= 0) { + SCLogError(SC_ERR_INVALID_VALUE, "Malformed value: %s", str_ptr); + goto error; + } } /* Offset */ - if (ByteExtractStringInt32(&data->offset, 0, 0, args[4]) <= 0) { - SCLogError(SC_ERR_INVALID_VALUE, " Malformed offset: %s", str_ptr); - goto error; + if (args[4][0] != '-' && isalpha(args[4][0])) { + if (offset == NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "byte_test supplied with " + "var name for offset. \"offset\" argument supplied to " + "this function has to be non-NULL"); + goto error; + } + *offset = SCStrdup(args[4]); + if (*offset == NULL) + goto error; + } else { + if (ByteExtractStringInt32(&data->offset, 0, 0, args[4]) <= 0) { + SCLogError(SC_ERR_INVALID_VALUE, " Malformed offset: %s", str_ptr); + goto error; + } } - /* The remaining options are flags. */ /** \todo Error on dups? */ for (i = 5; i < (ret - 1); i++) { @@ -545,8 +570,10 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) { DetectBytetestData *data = NULL; SigMatch *sm = NULL; + char *value = NULL; + char *offset = NULL; - data = DetectBytetestParse(optstr); + data = DetectBytetestParse(optstr, &value, &offset); if (data == NULL) goto error; @@ -604,6 +631,36 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) SigMatchAppendPayload(s, sm); } + if (value != NULL) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(value, s, + SigMatchListSMBelongsTo(s, sm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in byte_test - %s\n", value); + goto error; + } + DetectBytetestData *btd = sm->ctx; + btd->value = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + btd->flags |= DETECT_BYTETEST_VALUE_BE; + SCFree(value); + } + + if (offset != NULL) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(offset, s, + SigMatchListSMBelongsTo(s, sm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in byte_test - %s\n", offset); + goto error; + } + DetectBytetestData *btd = sm->ctx; + btd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + btd->flags |= DETECT_BYTETEST_OFFSET_BE; + SCFree(offset); + } + if ( !(data->flags & DETECT_BYTETEST_RELATIVE)) { return 0; } @@ -682,10 +739,10 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) return 0; error: - if (data != NULL) - DetectBytetestFree(data); - if (sm != NULL) - SCFree(sm); + //if (data != NULL) + // DetectBytetestFree(data); + //if (sm != NULL) + // SCFree(sm); return -1; } @@ -711,7 +768,7 @@ void DetectBytetestFree(void *ptr) int DetectBytetestTestParse01(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, =, 1 , 0"); + data = DetectBytetestParse("4, =, 1 , 0", NULL, NULL); if (data != NULL) { DetectBytetestFree(data); result = 1; @@ -726,7 +783,7 @@ int DetectBytetestTestParse01(void) { int DetectBytetestTestParse02(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, !=, 1, 0"); + data = DetectBytetestParse("4, !=, 1, 0", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 4) @@ -749,7 +806,7 @@ int DetectBytetestTestParse02(void) { int DetectBytetestTestParse03(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, !=, 1, 0, relative"); + data = DetectBytetestParse("4, !=, 1, 0, relative", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 4) @@ -773,7 +830,7 @@ int DetectBytetestTestParse03(void) { int DetectBytetestTestParse04(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, !=, 1, 0, string, oct"); + data = DetectBytetestParse("4, !=, 1, 0, string, oct", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 4) @@ -797,7 +854,7 @@ int DetectBytetestTestParse04(void) { int DetectBytetestTestParse05(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, =, 1, 0, string, dec"); + data = DetectBytetestParse("4, =, 1, 0, string, dec", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 4) @@ -820,7 +877,7 @@ int DetectBytetestTestParse05(void) { int DetectBytetestTestParse06(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, >, 1, 0, string, hex"); + data = DetectBytetestParse("4, >, 1, 0, string, hex", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_GT) && (data->nbytes == 4) @@ -843,7 +900,7 @@ int DetectBytetestTestParse06(void) { int DetectBytetestTestParse07(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, <, 5, 0, big"); + data = DetectBytetestParse("4, <, 5, 0, big", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_LT) && (data->nbytes == 4) @@ -866,7 +923,7 @@ int DetectBytetestTestParse07(void) { int DetectBytetestTestParse08(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, <, 5, 0, little"); + data = DetectBytetestParse("4, <, 5, 0, little", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_LT) && (data->nbytes == 4) @@ -889,7 +946,7 @@ int DetectBytetestTestParse08(void) { int DetectBytetestTestParse09(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, !, 5, 0"); + data = DetectBytetestParse("4, !, 5, 0", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 4) @@ -912,7 +969,7 @@ int DetectBytetestTestParse09(void) { int DetectBytetestTestParse10(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse(" 4 , ! &, 5 , 0 , little "); + data = DetectBytetestParse(" 4 , ! &, 5 , 0 , little ", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_AND) && (data->nbytes == 4) @@ -935,7 +992,7 @@ int DetectBytetestTestParse10(void) { int DetectBytetestTestParse11(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4,!^,5,0,little,string,relative,hex"); + data = DetectBytetestParse("4,!^,5,0,little,string,relative,hex", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_OR) && (data->nbytes == 4) @@ -961,7 +1018,7 @@ int DetectBytetestTestParse11(void) { int DetectBytetestTestParse12(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, =, 1, 0, hex"); + data = DetectBytetestParse("4, =, 1, 0, hex", NULL, NULL); if (data == NULL) { result = 1; } @@ -975,7 +1032,7 @@ int DetectBytetestTestParse12(void) { int DetectBytetestTestParse13(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("9, =, 1, 0"); + data = DetectBytetestParse("9, =, 1, 0", NULL, NULL); if (data == NULL) { result = 1; } @@ -989,7 +1046,7 @@ int DetectBytetestTestParse13(void) { int DetectBytetestTestParse14(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("23,=,0xffffffffffffffffULL,0,string,oct"); + data = DetectBytetestParse("23,=,0xffffffffffffffffULL,0,string,oct", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_EQ) && (data->nbytes == 23) @@ -1012,7 +1069,7 @@ int DetectBytetestTestParse14(void) { int DetectBytetestTestParse15(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("24, =, 0xffffffffffffffffULL, 0, string"); + data = DetectBytetestParse("24, =, 0xffffffffffffffffULL, 0, string", NULL, NULL); if (data == NULL) { result = 1; } @@ -1026,7 +1083,7 @@ int DetectBytetestTestParse15(void) { int DetectBytetestTestParse16(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4,=,0,0xffffffffffffffffULL"); + data = DetectBytetestParse("4,=,0,0xffffffffffffffffULL", NULL, NULL); if (data == NULL) { result = 1; } @@ -1040,7 +1097,7 @@ int DetectBytetestTestParse16(void) { int DetectBytetestTestParse17(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, <, 5, 0, dce"); + data = DetectBytetestParse("4, <, 5, 0, dce", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_LT) && (data->nbytes == 4) && @@ -1061,7 +1118,7 @@ int DetectBytetestTestParse17(void) { int DetectBytetestTestParse18(void) { int result = 0; DetectBytetestData *data = NULL; - data = DetectBytetestParse("4, <, 5, 0"); + data = DetectBytetestParse("4, <, 5, 0", NULL, NULL); if (data != NULL) { if ( (data->op == DETECT_BYTETEST_OP_LT) && (data->nbytes == 4) && diff --git a/src/detect-bytetest.h b/src/detect-bytetest.h index 21ccfec662..55cc3961c8 100644 --- a/src/detect-bytetest.h +++ b/src/detect-bytetest.h @@ -46,6 +46,8 @@ #define DETECT_BYTETEST_STRING 0x08 /**< "string" value */ #define DETECT_BYTETEST_RELATIVE 0x10 /**< "relative" offset */ #define DETECT_BYTETEST_DCE 0x20 /**< dce enabled */ +#define DETECT_BYTETEST_VALUE_BE 0x40 /**< byte extract value enabled */ +#define DETECT_BYTETEST_OFFSET_BE 0x80 /**< byte extract value enabled */ typedef struct DetectBytetestData_ { uint8_t nbytes; /**< Number of bytes to compare */ @@ -93,11 +95,16 @@ void DetectBytetestFree(void *ptr); * flags: "big", "little", "relative", "string", "oct", "dec", "hex" * * \param optstr Pointer to the user provided byte_test options + * \param value Used to pass the value back, if byte_test uses a byte_extract + * var. + * \param offset Used to pass the offset back, if byte_test uses a byte_extract + * var. * * \retval data pointer to DetectBytetestData on success * \retval NULL on failure */ -DetectBytetestData *DetectBytetestParse(char *optstr); +DetectBytetestData *DetectBytetestParse(char *optstr, char **value, + char **offset); /** * This function is used to match byte_test @@ -115,7 +122,7 @@ DetectBytetestData *DetectBytetestParse(char *optstr); */ int DetectBytetestMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m); -int DetectBytetestDoMatch(DetectEngineThreadCtx *, Signature *, SigMatch *, uint8_t *, uint32_t); +int DetectBytetestDoMatch(DetectEngineThreadCtx *, Signature *, SigMatch *, uint8_t *, uint32_t, + uint8_t, int32_t, uint64_t); #endif /* __DETECT_BYTETEST_H__ */ - diff --git a/src/detect-content.h b/src/detect-content.h index bbc30da4a8..52bf6f0c8c 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -52,6 +52,12 @@ #define DETECT_CONTENT_HCD_MPM 0x00040000 #define DETECT_CONTENT_HRUD_MPM 0x00080000 +/* BE - byte extract */ +#define DETECT_CONTENT_OFFSET_BE 0x00100000 +#define DETECT_CONTENT_DEPTH_BE 0x00200000 +#define DETECT_CONTENT_DISTANCE_BE 0x00400000 +#define DETECT_CONTENT_WITHIN_BE 0x00800000 + #define DETECT_CONTENT_IS_SINGLE(c) (!((c)->flags & DETECT_CONTENT_DISTANCE || \ (c)->flags & DETECT_CONTENT_WITHIN || \ (c)->flags & DETECT_CONTENT_RELATIVE_NEXT || \ diff --git a/src/detect-depth.c b/src/detect-depth.c index 2b3f46b23e..ceecc12aa4 100644 --- a/src/detect-depth.c +++ b/src/detect-depth.c @@ -32,6 +32,7 @@ #include "detect-parse.h" #include "detect-content.h" #include "detect-uricontent.h" +#include "detect-byte-extract.h" #include "detect-parse.h" #include "flow-var.h" @@ -134,14 +135,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - ud->depth = (uint32_t)atoi(str); - if (ud->depth < ud->content_len) { - ud->depth = ud->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - ud->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + ud->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + ud->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + ud->depth = (uint32_t)atoi(str); + if (ud->depth < ud->content_len) { + ud->depth = ud->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + ud->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + ud->depth += ud->offset; } - /* Now update the real limit, as depth is relative to the offset */ - ud->depth += ud->offset; + ud->flags |= DETECT_CONTENT_DEPTH; break; @@ -168,14 +183,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -196,14 +225,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -224,14 +267,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -252,14 +309,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -280,14 +351,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -308,14 +393,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; break; @@ -336,15 +435,28 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths } } - cd->depth = (uint32_t)atoi(str); - if (cd->depth < cd->content_len) { - cd->depth = cd->content_len; - SCLogDebug("depth increased to %"PRIu32" to match pattern len ", - cd->depth); + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in depth - %s\n", str); + goto error; + } + cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DEPTH_BE; + } else { + cd->depth = (uint32_t)atoi(str); + if (cd->depth < cd->content_len) { + cd->depth = cd->content_len; + SCLogDebug("depth increased to %"PRIu32" to match pattern len ", + cd->depth); + } + /* Now update the real limit, as depth is relative to the offset */ + cd->depth += cd->offset; + cd->flags |= DETECT_CONTENT_DEPTH; } - /* Now update the real limit, as depth is relative to the offset */ - cd->depth += cd->offset; - cd->flags |= DETECT_CONTENT_DEPTH; break; diff --git a/src/detect-distance.c b/src/detect-distance.c index 879f4d242b..0c17ee03aa 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -37,6 +37,7 @@ #include "detect-content.h" #include "detect-uricontent.h" #include "detect-pcre.h" +#include "detect-byte-extract.h" #include "flow-var.h" @@ -215,10 +216,23 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - ud->distance = strtol(str, NULL, 10); - if (ud->flags & DETECT_CONTENT_WITHIN) { - if ((ud->distance + ud->content_len) > ud->within) { - ud->within = ud->distance + ud->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + ud->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + ud->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + ud->distance = strtol(str, NULL, 10); + if (ud->flags & DETECT_CONTENT_WITHIN) { + if ((ud->distance + ud->content_len) > ud->within) { + ud->within = ud->distance + ud->content_len; + } } } @@ -303,14 +317,28 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - cd->flags |= DETECT_CONTENT_DISTANCE; - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; + pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, pm->prev, DETECT_PCRE, pm->prev, @@ -377,10 +405,24 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, case DETECT_AL_HTTP_CLIENT_BODY: cd = (DetectContentData *)pm->ctx; - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } @@ -444,12 +486,26 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; /* reassigning pm */ @@ -496,12 +552,26 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; /* reassigning pm */ @@ -549,12 +619,26 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; /* reassigning pm */ @@ -602,12 +686,26 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; /* reassigning pm */ @@ -655,12 +753,26 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, } } - cd->distance = strtol(str, NULL, 10); - if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((cd->distance + cd->content_len) > cd->within) { - cd->within = cd->distance + cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in distance - %s\n", str); + goto error; + } + cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_DISTANCE_BE; + } else { + cd->distance = strtol(str, NULL, 10); + if (cd->flags & DETECT_CONTENT_WITHIN) { + if ((cd->distance + cd->content_len) > cd->within) { + cd->within = cd->distance + cd->content_len; + } } } + cd->flags |= DETECT_CONTENT_DISTANCE; /* reassigning pm */ diff --git a/src/detect-engine-dcepayload.c b/src/detect-engine-dcepayload.c index 94809a240d..d554e5b4dc 100644 --- a/src/detect-engine-dcepayload.c +++ b/src/detect-engine-dcepayload.c @@ -34,6 +34,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "util-spm.h" #include "util-spm-bm.h" @@ -124,50 +125,77 @@ static int DoInspectDcePayload(DetectEngineCtx *de_ctx, offset = prev_payload_offset; depth = stub_len; + int distance = cd->distance; if (cd->flags & DETECT_CONTENT_DISTANCE) { - if (cd->distance < 0 && (uint32_t)(abs(cd->distance)) > offset) { - offset = 0; - } else { - offset += cd->distance; + if (cd->flags & DETECT_CONTENT_DISTANCE_BE) { + distance = det_ctx->bj_values[cd->distance]; } + if (distance < 0 && (uint32_t)(abs(distance)) > offset) + offset = 0; + else + offset += distance; SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32, cd->distance, offset, depth); } if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + cd->distance)) { - depth = prev_payload_offset + cd->within + cd->distance; - } + if (cd->flags & DETECT_CONTENT_WITHIN_BE) { + if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[cd->within] + distance)) { + depth = prev_payload_offset + det_ctx->bj_values[cd->within] + distance; + } + } else { + if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + distance)) { + depth = prev_payload_offset + cd->within + distance; + } - SCLogDebug("cd->within %"PRIi32", prev_payload_offset " - "%"PRIu32", depth %"PRIu32, cd->within, - prev_payload_offset, depth); + SCLogDebug("cd->within %"PRIi32", prev_payload_offset " + "%"PRIu32", depth %"PRIu32, cd->within, + prev_payload_offset, depth); + } } - if (cd->depth != 0) { - if ((cd->depth + prev_payload_offset) < depth) { - depth = prev_payload_offset + cd->depth; - } + if (cd->flags & DETECT_CONTENT_DEPTH_BE) { + if ((det_ctx->bj_values[cd->depth] + prev_payload_offset) < depth) { + depth = prev_payload_offset + det_ctx->bj_values[cd->depth]; + } + } else { + if (cd->depth != 0) { + if ((cd->depth + prev_payload_offset) < depth) { + depth = prev_payload_offset + cd->depth; + } - SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, - cd->depth, depth); + SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, + cd->depth, depth); + } } - if (cd->offset > offset) { - offset = cd->offset; - SCLogDebug("setting offset %"PRIu32, offset); + if (cd->flags & DETECT_CONTENT_OFFSET_BE) { + if (det_ctx->bj_values[cd->offset] > offset) + offset = det_ctx->bj_values[cd->offset]; + } else { + if (cd->offset > offset) { + offset = cd->offset; + SCLogDebug("setting offset %"PRIu32, offset); + } } /* implied no relative matches */ } else { /* set depth */ - if (cd->depth != 0) { - depth = cd->depth; + if (cd->flags & DETECT_CONTENT_DEPTH_BE) { + depth = det_ctx->bj_values[cd->depth]; + } else { + if (cd->depth != 0) { + depth = cd->depth; + } } /* set offset */ - offset = cd->offset; + if (cd->flags & DETECT_CONTENT_OFFSET_BE) + offset = det_ctx->bj_values[cd->offset]; + else + offset = cd->offset; prev_payload_offset = 0; } @@ -340,47 +368,76 @@ static int DoInspectDcePayload(DetectEngineCtx *de_ctx, case DETECT_BYTETEST: { DetectBytetestData *data = (DetectBytetestData *)sm->ctx; - uint32_t temp_flags = data->flags; + uint8_t flags = data->flags; + int32_t offset = data->offset;; + uint64_t value = data->value; + if (flags & DETECT_BYTETEST_OFFSET_BE) { + offset = det_ctx->bj_values[offset]; + } + if (flags & DETECT_BYTETEST_VALUE_BE) { + value = det_ctx->bj_values[value]; + } /* if we have dce enabled we will have to use the endianness * specified by the dce header */ - if (data->flags & DETECT_BYTETEST_DCE) { + if (flags & DETECT_BYTETEST_DCE) { /* enable the endianness flag temporarily. once we are done * processing we reset the flags to the original value*/ - data->flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ? - DETECT_BYTETEST_LITTLE: 0); + flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ? + DETECT_BYTETEST_LITTLE: 0); } - if (DetectBytetestDoMatch(det_ctx, s, sm, stub, stub_len) != 1) { + if (DetectBytetestDoMatch(det_ctx, s, sm, stub, stub_len, flags, offset, value) != 1) { SCReturnInt(0); } - /* reset the flags */ - data->flags = temp_flags; - goto match; } case DETECT_BYTEJUMP: { DetectBytejumpData *data = (DetectBytejumpData *)sm->ctx; - uint32_t temp_flags = data->flags; + uint8_t flags = data->flags; + int32_t offset = data->offset;; + if (flags & DETECT_BYTEJUMP_OFFSET_BE) { + offset = det_ctx->bj_values[offset]; + } /* if we have dce enabled we will have to use the endianness * specified by the dce header */ - if (data->flags & DETECT_BYTEJUMP_DCE) { + if (flags & DETECT_BYTEJUMP_DCE) { /* enable the endianness flag temporarily. once we are done * processing we reset the flags to the original value*/ - data->flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ? - DETECT_BYTEJUMP_LITTLE : 0); + flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ? + DETECT_BYTEJUMP_LITTLE : 0); } - if (DetectBytejumpDoMatch(det_ctx, s, sm, stub, stub_len) != 1) { + if (DetectBytejumpDoMatch(det_ctx, s, sm, stub, stub_len, flags, offset) != 1) { SCReturnInt(0); } - /* reset the flags */ - data->flags = temp_flags; + goto match; + } + + case DETECT_BYTE_EXTRACT: + { + DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx; + uint8_t endian = bed->endian; + + /* if we have dce enabled we will have to use the endianness + * specified by the dce header */ + if (bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN && + endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE) { + + /* enable the endianness flag temporarily. once we are done + * processing we reset the flags to the original value*/ + endian |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ? + DETECT_BYTE_EXTRACT_ENDIAN_LITTLE : DETECT_BYTE_EXTRACT_ENDIAN_BIG); + } + if (DetectByteExtractDoMatch(det_ctx, sm, s, stub, stub_len, + &det_ctx->bj_values[bed->local_id], endian) != 1) { + SCReturnInt(0); + } goto match; } diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index e260dcacfa..c5b849fb0e 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -36,6 +36,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "util-spm.h" #include "util-spm-bm.h" @@ -131,45 +132,73 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, offset = prev_payload_offset; depth = payload_len; + int distance = cd->distance; if (cd->flags & DETECT_CONTENT_DISTANCE) { - if (cd->distance < 0 && (uint32_t)(abs(cd->distance)) > offset) + if (cd->flags & DETECT_CONTENT_DISTANCE_BE) { + distance = det_ctx->bj_values[cd->distance]; + } + if (distance < 0 && (uint32_t)(abs(distance)) > offset) offset = 0; else - offset += cd->distance; + offset += distance; SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32, - cd->distance, offset, depth); + distance, offset, depth); } if (cd->flags & DETECT_CONTENT_WITHIN) { - if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + cd->distance)) { - depth = prev_payload_offset + cd->within + cd->distance; + if (cd->flags & DETECT_CONTENT_WITHIN_BE) { + if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[cd->within] + distance)) { + depth = prev_payload_offset + det_ctx->bj_values[cd->within] + distance; + } + } else { + if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + distance)) { + depth = prev_payload_offset + cd->within + distance; + } + + SCLogDebug("cd->within %"PRIi32", det_ctx->payload_offset %"PRIu32", depth %"PRIu32, + cd->within, prev_payload_offset, depth); } - - SCLogDebug("cd->within %"PRIi32", det_ctx->payload_offset %"PRIu32", depth %"PRIu32, - cd->within, prev_payload_offset, depth); } - if (cd->depth != 0) { - if ((cd->depth + prev_payload_offset) < depth) { - depth = prev_payload_offset + cd->depth; + if (cd->flags & DETECT_CONTENT_DEPTH_BE) { + if ((det_ctx->bj_values[cd->depth] + prev_payload_offset) < depth) { + depth = prev_payload_offset + det_ctx->bj_values[cd->depth]; } + } else { + if (cd->depth != 0) { + if ((cd->depth + prev_payload_offset) < depth) { + depth = prev_payload_offset + cd->depth; + } - SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth); + SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth); + } } - if (cd->offset > offset) { - offset = cd->offset; - SCLogDebug("setting offset %"PRIu32, offset); + if (cd->flags & DETECT_CONTENT_OFFSET_BE) { + if (det_ctx->bj_values[cd->offset] > offset) + offset = det_ctx->bj_values[cd->offset]; + } else { + if (cd->offset > offset) { + offset = cd->offset; + SCLogDebug("setting offset %"PRIu32, offset); + } } } else { /* implied no relative matches */ /* set depth */ - if (cd->depth != 0) { - depth = cd->depth; + if (cd->flags & DETECT_CONTENT_DEPTH_BE) { + depth = det_ctx->bj_values[cd->depth]; + } else { + if (cd->depth != 0) { + depth = cd->depth; + } } /* set offset */ - offset = cd->offset; + if (cd->flags & DETECT_CONTENT_OFFSET_BE) + offset = det_ctx->bj_values[cd->offset]; + else + offset = cd->offset; prev_payload_offset = 0; } @@ -339,7 +368,18 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, } case DETECT_BYTETEST: { - if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len) != 1) { + DetectBytetestData *btd = (DetectBytetestData *)sm->ctx; + int32_t offset = btd->offset; + uint64_t value = btd->value; + if (btd->flags & DETECT_BYTETEST_OFFSET_BE) { + offset = det_ctx->bj_values[offset]; + } + if (btd->flags & DETECT_BYTETEST_VALUE_BE) { + value = det_ctx->bj_values[value]; + } + + if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len, btd->flags, + offset, value) != 1) { SCReturnInt(0); } @@ -347,7 +387,28 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, } case DETECT_BYTEJUMP: { - if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len) != 1) { + DetectBytejumpData *bjd = (DetectBytejumpData *)sm->ctx; + int32_t offset = bjd->offset; + + if (bjd->flags & DETECT_BYTEJUMP_OFFSET_BE) { + offset = det_ctx->bj_values[offset]; + } + + if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len, + bjd->flags, offset) != 1) { + SCReturnInt(0); + } + + goto match; + } + case DETECT_BYTE_EXTRACT: + { + DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx; + + if (DetectByteExtractDoMatch(det_ctx, sm, s, payload, + payload_len, + &det_ctx->bj_values[bed->local_id], + bed->endian) != 1) { SCReturnInt(0); } @@ -940,6 +1001,211 @@ end: return result; } +static int PayloadTestSig18(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "content:|0C 0D 0E 0F|; distance:one; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig19(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,hex,relative; " + "content:|0C 0D 0E 0F|; distance:one; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig20(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "content:|06 35 07 08|; offset:one; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig21(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x36, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "content:|03 04 05 06|; depth:one; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig22(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x36, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "content:|09 0A 0B 0C|; within:one; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig23(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x32, /* the last byte is 2 */ + 0x07, 0x08, 0x09, 0x33, 0x0B, 0x0C, 0x0D, + 0x32, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "byte_extract:1,3,two,string,dec,relative; " + "byte_test:1,=,one,two,string,dec,relative; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + +static int PayloadTestSig24(void) +{ + uint8_t buf[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x32, /* the last byte is 2 */ + 0x07, 0x08, 0x33, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + }; + uint16_t buflen = sizeof(buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "content:|01 02 03 04|; " + "byte_extract:1,2,one,string,dec,relative; " + "byte_jump:1,one,string,dec,relative; " + "content:|0D 0E 0F|; distance:0; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) { + result = 0; + goto end; + } + + result = 1; + +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + #endif /* UNITTESTS */ void PayloadRegisterTests(void) { @@ -961,6 +1227,14 @@ void PayloadRegisterTests(void) { UtRegisterTest("PayloadTestSig15", PayloadTestSig15, 1); UtRegisterTest("PayloadTestSig16", PayloadTestSig16, 1); UtRegisterTest("PayloadTestSig17", PayloadTestSig17, 1); + + UtRegisterTest("PayloadTestSig18", PayloadTestSig18, 1); + UtRegisterTest("PayloadTestSig19", PayloadTestSig19, 1); + UtRegisterTest("PayloadTestSig20", PayloadTestSig20, 1); + UtRegisterTest("PayloadTestSig21", PayloadTestSig21, 1); + UtRegisterTest("PayloadTestSig22", PayloadTestSig22, 1); + UtRegisterTest("PayloadTestSig23", PayloadTestSig23, 1); + UtRegisterTest("PayloadTestSig24", PayloadTestSig24, 1); #endif /* UNITTESTS */ return; diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index 877b6c12fa..eae0e9613f 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -37,6 +37,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "flow-util.h" #include "util-spm.h" @@ -125,45 +126,73 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, offset = prev_payload_offset; depth = payload_len; + int distance = ud->distance; if (ud->flags & DETECT_CONTENT_DISTANCE) { - if (ud->distance < 0 && (uint32_t)(abs(ud->distance)) > offset) + if (ud->flags & DETECT_CONTENT_DISTANCE_BE) { + distance = det_ctx->bj_values[ud->distance]; + } + + if (distance < 0 && (uint32_t)(abs(distance)) > offset) offset = 0; else - offset += ud->distance; + offset += distance; SCLogDebug("ud->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32, - ud->distance, offset, depth); + distance, offset, depth); } if (ud->flags & DETECT_CONTENT_WITHIN) { - if ((int32_t)depth > (int32_t)(prev_payload_offset + ud->within + ud->distance)) { - depth = prev_payload_offset + ud->within + ud->distance; + if (ud->flags & DETECT_CONTENT_WITHIN_BE) { + if ((int32_t)depth > (int32_t)(prev_payload_offset + det_ctx->bj_values[ud->within] + distance)) { + depth = prev_payload_offset + det_ctx->bj_values[ud->within] + distance; + } + } else { + if ((int32_t)depth > (int32_t)(prev_payload_offset + ud->within + distance)) { + depth = prev_payload_offset + ud->within + distance; + } + SCLogDebug("ud->within %"PRIi32", prev_payload_offset %"PRIu32", depth %"PRIu32, + ud->within, prev_payload_offset, depth); } - - SCLogDebug("ud->within %"PRIi32", prev_payload_offset %"PRIu32", depth %"PRIu32, - ud->within, prev_payload_offset, depth); } - if (ud->depth != 0) { - if ((ud->depth + prev_payload_offset) < depth) { - depth = prev_payload_offset + ud->depth; + if (ud->flags & DETECT_CONTENT_DEPTH_BE) { + if ((det_ctx->bj_values[ud->depth] + prev_payload_offset) < depth) { + depth = prev_payload_offset + det_ctx->bj_values[ud->depth]; } + } else { + if (ud->depth != 0) { + if ((ud->depth + prev_payload_offset) < depth) { + depth = prev_payload_offset + ud->depth; + } - SCLogDebug("ud->depth %"PRIu32", depth %"PRIu32, ud->depth, depth); + SCLogDebug("ud->depth %"PRIu32", depth %"PRIu32, ud->depth, depth); + } } - if (ud->offset > offset) { - offset = ud->offset; - SCLogDebug("setting offset %"PRIu32, offset); + if (ud->flags & DETECT_CONTENT_OFFSET_BE) { + if (det_ctx->bj_values[ud->offset] > offset) + offset = det_ctx->bj_values[ud->offset]; + } else { + if (ud->offset > offset) { + offset = ud->offset; + SCLogDebug("setting offset %"PRIu32, offset); + } } } else { /* implied no relative matches */ /* set depth */ - if (ud->depth != 0) { - depth = ud->depth; + if (ud->flags & DETECT_CONTENT_DEPTH_BE) { + depth = det_ctx->bj_values[ud->depth]; + } else { + if (ud->depth != 0) { + depth = ud->depth; + } } /* set offset */ - offset = ud->offset; + if (ud->flags & DETECT_CONTENT_OFFSET_BE) + offset = det_ctx->bj_values[ud->offset]; + else + offset = ud->offset; prev_payload_offset = 0; } @@ -356,6 +385,16 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, } SCReturnInt(0); + } else if (sm->type == DETECT_BYTE_EXTRACT) { + DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx; + if (DetectByteExtractDoMatch(det_ctx, sm, s, payload, + payload_len, + &det_ctx->bj_values[bed->local_id], + bed->endian) != 1) { + SCReturnInt(0); + } + + goto match; } else { /* we should never get here, but bail out just in case */ SCLogDebug("sm->type %u", sm->type); @@ -3294,6 +3333,481 @@ end: return result; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +static int UriTestSig28(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /this_b5ig_string_now_in_http HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet *p = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p = UTHBuildPacket(http_buf, http_buf_len, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p->flow = &f; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any (msg:\"dummy\"; " + "uricontent:this; " + "byte_extract:1,2,one,string,dec,relative; " + "uricontent:ring; distance:one; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 1)) { + printf("sig 1 didn't alert, but should have: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + +static int UriTestSig29(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /this_b5ig_string_now_in_http HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet *p = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p = UTHBuildPacket(http_buf, http_buf_len, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p->flow = &f; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any (msg:\"dummy\"; " + "uricontent:this; " + "byte_extract:1,2,one,string,dec,relative; " + "uricontent:ring; distance:one; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 1)) { + printf("sig 1 didn't alert, but should have: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + +static int UriTestSig30(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /this_b5ig_string_now_in_http HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet *p = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p = UTHBuildPacket(http_buf, http_buf_len, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p->flow = &f; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any (msg:\"dummy\"; " + "uricontent:this; " + "byte_extract:1,2,one,string,dec,relative; " + "uricontent:_b5ig; offset:one; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 1)) { + printf("sig 1 didn't alert, but should have: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + +static int UriTestSig31(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /this_b5ig_string_now_in_http HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet *p = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p = UTHBuildPacket(http_buf, http_buf_len, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p->flow = &f; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any (msg:\"dummy\"; " + "uricontent:this; " + "byte_extract:1,2,one,string,dec,relative; " + "uricontent:his; depth:one; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 1)) { + printf("sig 1 didn't alert, but should have: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + +static int UriTestSig32(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /this_b5ig_string_now_in_http HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet *p = NULL; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p = UTHBuildPacket(http_buf, http_buf_len, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p->flow = &f; + p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; + p->flowflags |= FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, + "alert tcp any any -> any any (msg:\"dummy\"; " + "uricontent:this; " + "byte_extract:1,2,one,string,dec,relative; " + "uricontent:g_st; within:one; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + + if (!PacketAlertCheck(p, 1)) { + printf("sig 1 didn't alert, but should have: "); + goto end; + } + + result = 1; + +end: + if (det_ctx != NULL) + DetectEngineThreadCtxDeinit(&tv, det_ctx); + if (de_ctx != NULL) + SigGroupCleanup(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + UTHFreePacket(p); + return result; +} + #endif /* UNITTESTS */ void UriRegisterTests(void) @@ -3327,6 +3841,12 @@ void UriRegisterTests(void) UtRegisterTest("UriTestSig25", UriTestSig25, 1); UtRegisterTest("UriTestSig26", UriTestSig26, 1); UtRegisterTest("UriTestSig27", UriTestSig27, 1); + + UtRegisterTest("UriTestSig28", UriTestSig28, 1); + UtRegisterTest("UriTestSig29", UriTestSig29, 1); + UtRegisterTest("UriTestSig30", UriTestSig30, 1); + UtRegisterTest("UriTestSig31", UriTestSig31, 1); + UtRegisterTest("UriTestSig32", UriTestSig32, 1); #endif /* UNITTESTS */ return; diff --git a/src/detect-engine.c b/src/detect-engine.c index ece4debb92..599d6797da 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -41,6 +41,7 @@ #include "detect-engine.h" +#include "detect-byte-extract.h" #include "detect-content.h" #include "detect-uricontent.h" #include "detect-engine-threshold.h" @@ -441,6 +442,11 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data) { /* this detection engine context belongs to this thread instance */ det_ctx->tv = tv; + det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) * byte_extract_max_local_id); + if (det_ctx->bj_values == NULL) { + return TM_ECODE_FAILED; + } + *data = (void *)det_ctx; return TM_ECODE_OK; @@ -469,6 +475,9 @@ TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data) { if (det_ctx->de_state_sig_array != NULL) SCFree(det_ctx->de_state_sig_array); + if (det_ctx->bj_values != NULL) + SCFree(det_ctx->bj_values); + SCFree(det_ctx); return TM_ECODE_OK; diff --git a/src/detect-offset.c b/src/detect-offset.c index 68abd1ee99..82ca82517b 100644 --- a/src/detect-offset.c +++ b/src/detect-offset.c @@ -32,6 +32,7 @@ #include "detect-parse.h" #include "detect-content.h" #include "detect-uricontent.h" +#include "detect-byte-extract.h" #include "app-layer.h" #include "flow-var.h" @@ -131,15 +132,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - ud->offset = (uint32_t)atoi(str); - if (ud->depth != 0) { - if (ud->depth < ud->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - ud->content_len); - ud->depth = ud->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + ud->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + ud->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + ud->offset = (uint32_t)atoi(str); + if (ud->depth != 0) { + if (ud->depth < ud->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + ud->content_len); + ud->depth = ud->content_len; + } + /* Updating the depth as is relative to the offset */ + ud->depth += ud->offset; } - /* Updating the depth as is relative to the offset */ - ud->depth += ud->offset; } ud->flags |= DETECT_CONTENT_OFFSET; @@ -169,15 +183,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -200,15 +227,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -231,15 +271,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -262,15 +315,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -293,15 +359,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -324,15 +403,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; @@ -355,15 +447,28 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) } } - cd->offset = (uint32_t)atoi(str); - if (cd->depth != 0) { - if (cd->depth < cd->content_len) { - SCLogDebug("depth increased to %"PRIu32" to match pattern len", - cd->content_len); - cd->depth = cd->content_len; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in offset - %s\n", str); + goto error; + } + cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_OFFSET_BE; + } else { + cd->offset = (uint32_t)atoi(str); + if (cd->depth != 0) { + if (cd->depth < cd->content_len) { + SCLogDebug("depth increased to %"PRIu32" to match pattern len", + cd->content_len); + cd->depth = cd->content_len; + } + /* Updating the depth as is relative to the offset */ + cd->depth += cd->offset; } - /* Updating the depth as is relative to the offset */ - cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_OFFSET; diff --git a/src/detect-within.c b/src/detect-within.c index 19fc386bf1..017547fa31 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -33,6 +33,7 @@ #include "detect-content.h" #include "detect-uricontent.h" #include "detect-bytejump.h" +#include "detect-byte-extract.h" #include "app-layer.h" #include "detect-parse.h" @@ -217,13 +218,26 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - ud->within = strtol(str, NULL, 10); - if (ud->within < (int32_t)ud->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", ud->within, - ud->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + ud->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + ud->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + ud->within = strtol(str, NULL, 10); + if (ud->within < (int32_t)ud->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", ud->within, + ud->content_len); + goto error; + } } ud->flags |= DETECT_CONTENT_WITHIN; @@ -314,13 +328,26 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } cd->flags |= DETECT_CONTENT_WITHIN; @@ -397,13 +424,27 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi case DETECT_AL_HTTP_CLIENT_BODY: cd = (DetectContentData *)pm->ctx; - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } if (cd->flags & DETECT_CONTENT_NEGATED) { @@ -466,14 +507,28 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } + cd->flags |= DETECT_CONTENT_WITHIN; /* reassigning pm */ @@ -520,14 +575,28 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } + cd->flags |= DETECT_CONTENT_WITHIN; /* reassigning pm */ @@ -574,14 +643,28 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } + cd->flags |= DETECT_CONTENT_WITHIN; /* reassigning pm */ @@ -628,14 +711,28 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } + cd->flags |= DETECT_CONTENT_WITHIN; /* reassigning pm */ @@ -682,14 +779,28 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi } } - cd->within = strtol(str, NULL, 10); - if (cd->within < (int32_t)cd->content_len) { - SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " - "less than the content length \"%"PRIu32"\" which is invalid, since " - "this will never match. Invalidating signature", cd->within, - cd->content_len); - goto error; + if (str[0] != '-' && isalpha(str[0])) { + SigMatch *bed_sm = + DetectByteExtractRetrieveSMVar(str, s, + SigMatchListSMBelongsTo(s, pm)); + if (bed_sm == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " + "seen in within - %s\n", str); + goto error; + } + cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; + cd->flags |= DETECT_CONTENT_WITHIN_BE; + } else { + cd->within = strtol(str, NULL, 10); + if (cd->within < (int32_t)cd->content_len) { + SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " + "less than the content length \"%"PRIu32"\" which is invalid, since " + "this will never match. Invalidating signature", cd->within, + cd->content_len); + goto error; + } } + cd->flags |= DETECT_CONTENT_WITHIN; /* reassigning pm */ diff --git a/src/detect.c b/src/detect.c index ead3284979..fc1290e7bb 100644 --- a/src/detect.c +++ b/src/detect.c @@ -122,6 +122,7 @@ #include "detect-engine-hmd.h" #include "detect-engine-hcd.h" #include "detect-engine-hrud.h" +#include "detect-byte-extract.h" #include "util-rule-vars.h" @@ -4256,6 +4257,7 @@ void SigTableSetup(void) { DetectSshSoftwareVersionRegister(); DetectHttpStatCodeRegister(); DetectSslVersionRegister(); + DetectByteExtractRegister(); uint8_t i = 0; for (i = 0; i < DETECT_TBLSIZE; i++) { diff --git a/src/detect.h b/src/detect.h index fa12f0a112..d5748bf310 100644 --- a/src/detect.h +++ b/src/detect.h @@ -787,6 +787,9 @@ typedef struct DetectionEngineThreadCtx_ { /** ip only rules ctx */ DetectEngineIPOnlyThreadCtx io_ctx; + /* byte jump values */ + uint64_t *bj_values; + DetectEngineCtx *de_ctx; #ifdef __SC_CUDA_SUPPORT__ /* each detection thread would have it's own queue where the cuda dispatcher @@ -999,6 +1002,7 @@ enum { DETECT_AL_SSH_SOFTWAREVERSION, DETECT_AL_SSL_VERSION, DETECT_AL_SSL_STATE, + DETECT_BYTE_EXTRACT, DETECT_DCE_IFACE, DETECT_DCE_OPNUM,