file-data: initial file_data support

Support file_data for: content, pcre (relative), byte_test, byte_jump,
byte_extract, isdataat.

File_data support is handled at signature parsing time, all matches
occurring after the file_data in the rule are converted to http_server_body
matches.

Content matches relative to the file_data are converted. Within to depth,
distance to offset. Relative to the start of the body buffer.
remotes/origin/master-1.2.x
Victor Julien 15 years ago
parent 7adac3048d
commit 07e560b137

@ -580,7 +580,29 @@ int DetectByteExtractSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg)
goto error;
}
if (s->alproto == ALPROTO_DCERPC &&
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
if (data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) {
SigMatch *prev_sm = NULL;
prev_sm = SigMatchGetLastSMFromLists(s, 8,
DETECT_AL_HTTP_SERVER_BODY, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]);
if (prev_sm == NULL) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content, "
"byte_test or pcre option after file_data");
goto error;
}
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
} else {
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
}
} else if (s->alproto == ALPROTO_DCERPC &&
data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE) {
SigMatch *pm = NULL;
SigMatch *dm = NULL;
@ -637,6 +659,10 @@ int DetectByteExtractSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg)
}
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
return 0;
}
if ( !(data->flags & DETECT_BYTE_EXTRACT_FLAG_RELATIVE)) {
return 0;
}

@ -561,7 +561,29 @@ int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
}
}
if (s->alproto == ALPROTO_DCERPC &&
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
SigMatch *prev_sm = NULL;
prev_sm = SigMatchGetLastSMFromLists(s, 8,
DETECT_AL_HTTP_SERVER_BODY, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]);
if (prev_sm == NULL) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content, "
"byte_test or pcre option after file_data");
goto error;
}
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
} else {
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
}
} else if (s->alproto == ALPROTO_DCERPC &&
data->flags & DETECT_BYTEJUMP_RELATIVE) {
SigMatch *pm = NULL;
SigMatch *dm = NULL;
@ -603,6 +625,10 @@ int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
SCFree(offset);
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
return 0;
}
if ( !(data->flags & DETECT_BYTEJUMP_RELATIVE)) {
return(0);
}

@ -256,126 +256,6 @@ int DetectBytetestMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
{
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;
uint16_t len = 0;
uint64_t val = 0;
int extbytes;
int neg;
int match;
if (p->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_BYTETEST_RELATIVE) {
ptr = det_ctx->pkt_ptr;
len = GET_PKT_LEN(p) - det_ctx->pkt_off;
/* No match if there is no relative base */
if (ptr == NULL || len == 0) {
return 0;
}
ptr += data->offset;
len -= data->offset;
}
else {
ptr = p->payload + data->offset;
len = p->payload_len - data->offset;
}
/* Validate that the to-be-extracted is within the packet
* \todo Should this validate it is in the *payload*?
*/
if (ptr < GET_PKT_DATA(p) || data->nbytes > len) {
SCLogDebug("Data not within packet pkt=%p, ptr=%p, len=%d, nbytes=%d",
GET_PKT_DATA(p), ptr, len, data->nbytes);
return 0;
}
neg = data->flags & DETECT_BYTETEST_NEGOP;
/* Extract the byte data */
if (data->flags & DETECT_BYTETEST_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;
}
}
SCLogDebug("comparing base %d string 0x%" PRIx64 " %s%c 0x%" PRIx64 "",
data->base, val, (neg ? "!" : ""), data->op, data->value);
}
else {
int endianness = (data->flags & DETECT_BYTETEST_LITTLE) ?
BYTE_LITTLE_ENDIAN : BYTE_BIG_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 -1;
}
SCLogDebug("comparing numeric 0x%" PRIx64 " %s%c 0x%" PRIx64 "",
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) {
match = 1;
}
break;
case DETECT_BYTETEST_OP_LT:
if (val < data->value) {
match = 1;
}
break;
case DETECT_BYTETEST_OP_GT:
if (val > data->value) {
match = 1;
}
break;
case DETECT_BYTETEST_OP_AND:
if (val & data->value) {
match = 1;
}
break;
case DETECT_BYTETEST_OP_OR:
if (val ^ data->value) {
match = 1;
}
break;
default:
/* Should never get here as we handle this in parsing. */
return -1;
}
/* A successful match depends on negation */
if ((!neg && match) || (neg && !match)) {
SCLogDebug("MATCH");
return 1;
}
SCLogDebug("NO MATCH");
return 0;
#endif
}
DetectBytetestData *DetectBytetestParse(char *optstr, char **value, char **offset)
@ -604,19 +484,42 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
}
}
if (s->alproto == ALPROTO_DCERPC &&
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
if (data->flags & DETECT_BYTETEST_RELATIVE) {
SigMatch *prev_sm = NULL;
prev_sm = SigMatchGetLastSMFromLists(s, 8,
DETECT_AL_HTTP_SERVER_BODY, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]);
if (prev_sm == NULL) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content, "
"byte_test or pcre option after file_data");
goto error;
}
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
} else {
s->flags |= SIG_FLAG_APPLAYER;
AppLayerHtpEnableResponseBodyCallback();
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
}
} else if (s->alproto == ALPROTO_DCERPC &&
data->flags & DETECT_BYTETEST_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]);
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]);
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);
@ -661,6 +564,10 @@ int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr)
SCFree(offset);
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
return 0;
}
if ( !(data->flags & DETECT_BYTETEST_RELATIVE)) {
return 0;
}

@ -501,13 +501,31 @@ static int DetectContentSetup (DetectEngineCtx *de_ctx, Signature *s, char *cont
sm->type = DETECT_CONTENT;
sm->ctx = (void *)cd;
//cd->id = DetectContentGetId(de_ctx->mpm_pattern_id_store, cd);
cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_CONTENT);
DetectContentPrint(cd);
SigMatchAppendPayload(s, sm);
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_AL_HTTP_SERVER_BODY);
sm->type = DETECT_AL_HTTP_SERVER_BODY;
/* transfer the sm from the pmatch list to hsbdmatch list */
SigMatchTransferSigMatchAcrossLists(sm,
&s->sm_lists[DETECT_SM_LIST_PMATCH],
&s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
&s->sm_lists[DETECT_SM_LIST_HSBDMATCH],
&s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]);
/* flag the signature to indicate that we scan the app layer data */
s->flags |= SIG_FLAG_APPLAYER;
s->alproto = ALPROTO_HTTP;
/* enable http request body callback in the http app layer parser */
AppLayerHtpEnableResponseBodyCallback();
}
return 0;
error:
@ -1929,6 +1947,126 @@ int DetectContentParseTest35(void)
return result;
}
/**
* \test Parsing test: file_data
*/
static int DetectContentParseTest36(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test\"; file_data; content:\"abc\"; sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
printf("content still in PMATCH list: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("content not in HSBDMATCH list: ");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Parsing test: file_data
*/
static int DetectContentParseTest37(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test\"; file_data; content:\"abc\"; content:\"def\"; sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
printf("content still in PMATCH list: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("content not in HSBDMATCH list: ");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Parsing test: file_data
*/
static int DetectContentParseTest38(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test\"; file_data; content:\"abc\"; content:\"def\"; within:8; sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
printf("content still in PMATCH list: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("content not in HSBDMATCH list: ");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
static int SigTestPositiveTestContent(char *rule, uint8_t *buf)
{
uint16_t buflen = strlen((char *)buf);
@ -1973,6 +2111,86 @@ end:
return result;
}
/**
* \test Parsing test: file_data, within relative to file_data
*/
static int DetectContentParseTest39(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test\"; file_data; content:\"abc\"; within:8; sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
printf("content still in PMATCH list: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("content not in HSBDMATCH list: ");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Parsing test: file_data, distance relative to file_data
*/
static int DetectContentParseTest40(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert tcp any any -> any any "
"(msg:\"test\"; file_data; content:\"abc\"; distance:3; sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
printf("content still in PMATCH list: ");
goto end;
}
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("content not in HSBDMATCH list: ");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
static int SigTestNegativeTestContent(char *rule, uint8_t *buf)
{
uint16_t buflen = strlen((char *)buf);
@ -2392,6 +2610,11 @@ void DetectContentRegisterTests(void)
UtRegisterTest("DetectContentParseTest33", DetectContentParseTest33, 1);
UtRegisterTest("DetectContentParseTest34", DetectContentParseTest34, 1);
UtRegisterTest("DetectContentParseTest35", DetectContentParseTest35, 1);
UtRegisterTest("DetectContentParseTest36", DetectContentParseTest36, 1);
UtRegisterTest("DetectContentParseTest37", DetectContentParseTest37, 1);
UtRegisterTest("DetectContentParseTest38", DetectContentParseTest38, 1);
UtRegisterTest("DetectContentParseTest39", DetectContentParseTest39, 1);
UtRegisterTest("DetectContentParseTest40", DetectContentParseTest40, 1);
/* The reals */
UtRegisterTest("DetectContentLongPatternMatchTest01", DetectContentLongPatternMatchTest01, 1);

@ -506,25 +506,39 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s,
DETECT_AL_HTTP_SERVER_BODY, pm->prev,
DETECT_PCRE, pm->prev);
if (pm == NULL) {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_server_body "
"needs preceeding http_server_body content");
goto error;
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
/* file_data; content:"abc"; distance:0; is valid, in this case
* there will be no previous pm. We convert to offset in this case */
cd->flags &= ~DETECT_CONTENT_DISTANCE;
if (pm->type == DETECT_PCRE) {
DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
} else {
/* reassigning cd */
cd = (DetectContentData *)pm->ctx;
if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword "
"has a fast_pattern:only; set. You can't "
"have relative keywords around a fast_pattern "
"only content");
if (cd->distance < 0) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have negative distance relative to file_data");
goto error;
}
SCLogDebug("converted distance to offset for content relative to file_data");
cd->offset = cd->distance;
} else {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_server_body "
"needs preceeding http_server_body content");
goto error;
}
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
} else {
if (pm->type == DETECT_PCRE) {
DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
} else {
/* reassigning cd */
cd = (DetectContentData *)pm->ctx;
if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword "
"has a fast_pattern:only; set. You can't "
"have relative keywords around a fast_pattern "
"only content");
goto error;
}
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
}
}
break;

@ -45,6 +45,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"
@ -246,6 +247,37 @@ static int DoInspectHttpServerBody(DetectEngineCtx *de_ctx,
} while(1);
} else if (sm->type == DETECT_ISDATAAT) {
{
SCLogDebug("inspecting isdataat");
DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
if (id->flags & ISDATAAT_RELATIVE) {
if (det_ctx->payload_offset + id->dataat > payload_len) {
SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
} else {
SCLogDebug("relative isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
}
} else {
if (id->dataat < payload_len) {
SCLogDebug("absolute isdataat match");
if (id->flags & ISDATAAT_NEGATED)
SCReturnInt(0);
goto match;
} else {
SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", payload_len %"PRIu32"", id->dataat,payload_len);
if (id->flags & ISDATAAT_NEGATED)
goto match;
SCReturnInt(0);
}
}
}
} else if (sm->type == DETECT_PCRE) {
SCLogDebug("inspecting pcre");
DetectPcreData *pe = (DetectPcreData *)sm->ctx;
@ -286,6 +318,48 @@ static int DoInspectHttpServerBody(DetectEngineCtx *de_ctx,
det_ctx->payload_offset = prev_payload_offset;
det_ctx->pcre_match_start_offset = prev_offset;
} while (1);
} else if (sm->type == DETECT_BYTETEST) {
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);
}
goto match;
} else if (sm->type == DETECT_BYTEJUMP) {
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;
} 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);

@ -73,5 +73,7 @@ static int DetectFiledataSetup (DetectEngineCtx *de_ctx, Signature *s, char *str
{
SCEnter();
s->init_flags |= SIG_FLAG_INIT_FILE_DATA;
return 0;
}

@ -367,7 +367,7 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatst
list_type = DETECT_SM_LIST_HCBDMATCH;
break;
case DETECT_AL_HTTP_SERVER_BODY:
list_type = DETECT_SM_LIST_HCBDMATCH;
list_type = DETECT_SM_LIST_HSBDMATCH;
break;
case DETECT_AL_HTTP_RAW_HEADER:
list_type = DETECT_SM_LIST_HRHDMATCH;
@ -1015,6 +1015,54 @@ int DetectIsdataatTestParse13(void)
return result;
}
static int DetectIsdataatTestParse14(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
Signature *s = NULL;
DetectIsdataatData *data = NULL;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing file_data and isdataat\"; "
"file_data; content:\"one\"; "
"isdataat:!4,relative; sid:1;)");
if (de_ctx->sig_list == NULL) {
goto end;
}
s = de_ctx->sig_list;
if (s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH] == NULL) {
printf("server body list empty: ");
goto end;
}
if (s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]->type != DETECT_ISDATAAT) {
printf("last server body sm not isdataat: ");
goto end;
}
data = (DetectIsdataatData *)s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]->ctx;
if ( !(data->flags & ISDATAAT_RELATIVE) ||
(data->flags & ISDATAAT_RAWBYTES) ||
!(data->flags & ISDATAAT_NEGATED) ) {
result = 0;
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test DetectIsdataatTestPacket01 is a test to check matches of
* isdataat, and isdataat relative
@ -1122,7 +1170,7 @@ end:
* \brief this function registers unit tests for DetectIsdataat
*/
void DetectIsdataatRegisterTests(void) {
#ifdef UNITTESTS
#ifdef UNITTESTS
UtRegisterTest("DetectIsdataatTestParse01", DetectIsdataatTestParse01, 1);
UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02, 1);
UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03, 1);
@ -1136,8 +1184,9 @@ void DetectIsdataatRegisterTests(void) {
UtRegisterTest("DetectIsdataatTestParse11", DetectIsdataatTestParse11, 1);
UtRegisterTest("DetectIsdataatTestParse12", DetectIsdataatTestParse12, 1);
UtRegisterTest("DetectIsdataatTestParse13", DetectIsdataatTestParse13, 1);
UtRegisterTest("DetectIsdataatTestParse14", DetectIsdataatTestParse14, 1);
UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01, 1);
UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02, 1);
UtRegisterTest("DetectIsdataatTestPacket03", DetectIsdataatTestPacket03, 1);
#endif
#endif
}

@ -2489,6 +2489,31 @@ end:
return result;
}
/**
* \test file_data with rawbytes
*/
static int SigParseTest12(void) {
int result = 0;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
Signature *s = NULL;
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
if (s != NULL) {
printf("sig 1 should have given an error: ");
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/** \test Direction operator validation (invalid) */
int SigParseBidirecTest06 (void) {
int result = 1;
@ -3362,6 +3387,7 @@ void SigParseRegisterTests(void) {
UtRegisterTest("SigParseTest09", SigParseTest09, 1);
UtRegisterTest("SigParseTest10", SigParseTest10, 1);
UtRegisterTest("SigParseTest11", SigParseTest11, 1);
UtRegisterTest("SigParseTest12", SigParseTest12, 1);
UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06, 1);
UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07, 1);

@ -54,10 +54,15 @@ static int DetectRawbytesSetup (DetectEngineCtx *de_ctx, Signature *s, char *nul
SCEnter();
if (nullstr != NULL) {
SCLogError(SC_ERR_INVALID_VALUE, "nocase has no value");
SCLogError(SC_ERR_INVALID_VALUE, "rawbytes has no value");
return -1;
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
SCLogError(SC_ERR_RAWBYTES_FILE_DATA, "\"rawbytes\" cannot be combined with \"file_data\"");
SCReturnInt(-1);
}
SigMatch *pm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]);
if (pm == NULL) {
SCLogError(SC_ERR_RAWBYTES_MISSING_CONTENT, "\"rawbytes\" needs a preceeding content option");

@ -529,27 +529,35 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi
DETECT_AL_HTTP_SERVER_BODY, pm->prev,
DETECT_PCRE, pm->prev);
if (pm == NULL) {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_server_body "
"needs preceeding http_server_body content");
goto error;
}
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
/* file_data; content:"abc"; within:3; is valid, in this case
* there will be no previous pm. We convert to depth in this case */
cd->flags &= ~DETECT_CONTENT_WITHIN;
if (pm->type == DETECT_PCRE) {
DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
} else {
/* reassigning cd */
cd = (DetectContentData *)pm->ctx;
if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword "
"has a fast_pattern:only; set. You can't "
"have relative keywords around a fast_pattern "
"only content");
SCLogDebug("converted within to depth for content relative to file_data");
cd->depth = cd->within;
} else {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "within for http_server_body "
"needs preceeding http_server_body content");
goto error;
}
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
} else {
if (pm->type == DETECT_PCRE) {
DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
} else {
/* reassigning cd */
cd = (DetectContentData *)pm->ctx;
if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "Previous keyword "
"has a fast_pattern:only; set. You can't "
"have relative keywords around a fast_pattern "
"only content");
goto error;
}
cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
}
}
break;
case DETECT_AL_HTTP_HEADER:

@ -252,6 +252,7 @@ typedef struct DetectPort_ {
#define SIG_FLAG_INIT_FLOW (1<<2) /**< signature has a flow setting */
#define SIG_FLAG_INIT_BIDIREC (1<<3) /**< signature has bidirectional operator */
#define SIG_FLAG_INIT_PAYLOAD (1<<4) /**< signature is inspecting the packet payload */
#define SIG_FLAG_INIT_FILE_DATA (1<<5) /**< file_data set */
/* signature mask flags */
#define SIG_MASK_REQUIRE_PAYLOAD 1

@ -211,6 +211,7 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_AFP_DISPATCH);
CASE_CODE (SC_ERR_CMD_LINE);
CASE_CODE (SC_ERR_SIZE_PARSE);
CASE_CODE (SC_ERR_RAWBYTES_FILE_DATA);
default:
return "UNKNOWN_ERROR";

@ -226,6 +226,7 @@ typedef enum {
SC_ERR_MAGIC_OPEN,
SC_ERR_MAGIC_LOAD,
SC_ERR_SIZE_PARSE,
SC_ERR_RAWBYTES_FILE_DATA,
} SCError;
const char *SCErrorToString(SCError);

Loading…
Cancel
Save