diff --git a/src/detect-http-cookie.c b/src/detect-http-cookie.c index 0cfaf99e33..08756e6288 100644 --- a/src/detect-http-cookie.c +++ b/src/detect-http-cookie.c @@ -71,7 +71,7 @@ int DetectHttpCookieMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, DetectHttpCookieData *co = (DetectHttpCookieData *)m->ctx; HtpState *htp_state = (HtpState *)state; if (htp_state == NULL) { - SCLogDebug("No HTTP layer state has been received, so no match!!"); + SCLogDebug("no HTTP layer state has been received, so no match"); return 0; } @@ -86,16 +86,15 @@ int DetectHttpCookieMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, htp_header_t *h = NULL; h = (htp_header_t *)table_getc(tx->request_headers, "Cookie"); if (h == NULL) { - SCLogDebug("No HTTP Cookie hearder in the received request"); + SCLogDebug("no HTTP Cookie hearder in the received request"); ret = 0; } - if (BinSearch(bstr_ptr(h->value), bstr_size(h->value), co->data, co->data_len) != NULL) { - SCLogDebug("Match has been found in received request and given http_" - "cookie rule\n"); + SCLogDebug("match has been found in received request and given http_" + "cookie rule"); ret = 1; } SCMutexUnlock(&f->m); @@ -139,7 +138,7 @@ int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, SCLogWarning(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside " "the rule, without a content context. Please use a " "content keyword before using http_cookie"); - return -1; + return -1; } } @@ -385,9 +384,9 @@ static int DetectHttpCookieSigTest01(void) { goto end; } - s = s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP " + s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP " "cookie\"; content:\"go\"; http_cookie; sid:2;)"); - if (s == NULL) { + if (s->next == NULL) { goto end; } @@ -414,8 +413,11 @@ static int DetectHttpCookieSigTest01(void) { SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); if (!(PacketAlertCheck(&p, 1))) { + printf("sid 1 didn't match but should have: "); goto end; - } else if (PacketAlertCheck(&p, 2)) { + } + if (PacketAlertCheck(&p, 2)) { + printf("sid 2 matched but shouldn't: "); goto end; } diff --git a/src/detect-parse.c b/src/detect-parse.c index 540053c998..801a65c86d 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -634,6 +634,23 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { } } + /* set the packet and app layer flags, but only if the + * app layer flag wasn't already set in which case we + * only consider the app layer */ + if (!(sig->flags & SIG_FLAG_APPLAYER)) { + if (sig->match != NULL) { + SigMatch *sm = sig->match; + for ( ; sm != NULL; sm = sm->next) { + if (sigmatch_table[sm->type].AppLayerMatch != NULL) + sig->flags |= SIG_FLAG_APPLAYER; + if (sigmatch_table[sm->type].Match != NULL) + sig->flags |= SIG_FLAG_PACKET; + } + } else { + sig->flags |= SIG_FLAG_PACKET; + } + } + return sig; error: diff --git a/src/detect-tls-version.c b/src/detect-tls-version.c index 51af1fd93e..685dcf585d 100644 --- a/src/detect-tls-version.c +++ b/src/detect-tls-version.c @@ -221,7 +221,6 @@ int DetectTlsVersionSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c sm->ctx = (void *)tls; SigMatchAppend(s,m,sm); - return 0; error: @@ -329,47 +328,40 @@ static int DetectTlsVersionTestDetect01(void) { int r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1, FALSE); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2, FALSE); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3, FALSE); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf4, tlslen4, FALSE); if (r != 0) { printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } TlsState *tls_state = ssn.aldata[AlpGetStateIdx(ALPROTO_TLS)]; if (tls_state == NULL) { printf("no tls state: "); - result = 0; goto end; } if (tls_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, tls_state->client_content_type); - result = 0; goto end; } if (tls_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); - result = 0; goto end; } @@ -395,7 +387,7 @@ end: } static int DetectTlsVersionTestDetect02(void) { - int result = 1; + int result = 0; Flow f; uint8_t tlsbuf1[] = { 0x16 }; uint32_t tlslen1 = sizeof(tlsbuf1); @@ -426,6 +418,7 @@ static int DetectTlsVersionTestDetect02(void) { f.protoctx = (void *)&ssn; p.flow = &f; p.flowflags |= FLOW_PKT_TOSERVER; + ssn.alproto = ALPROTO_TLS; DetectEngineCtx *de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { @@ -445,54 +438,159 @@ static int DetectTlsVersionTestDetect02(void) { int r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1, FALSE); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2, FALSE); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3, FALSE); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf4, tlslen4, FALSE); if (r != 0) { printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); - result = 0; goto end; } TlsState *tls_state = ssn.aldata[AlpGetStateIdx(ALPROTO_TLS)]; if (tls_state == NULL) { printf("no tls state: "); - result = 0; goto end; } if (tls_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, tls_state->client_content_type); - result = 0; goto end; } if (tls_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); - result = 0; goto end; } /* do detect */ SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); - if (PacketAlertCheck(&p, 1)) { + if (!(PacketAlertCheck(&p, 1))) { + printf("signature 1 didn't match while it should have: "); + goto end; + } + + result = 1; +end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + +static int DetectTlsVersionTestDetect03(void) { + int result = 0; + Flow f; + uint8_t tlsbuf1[] = { 0x16 }; + uint32_t tlslen1 = sizeof(tlsbuf1); + uint8_t tlsbuf2[] = { 0x03 }; + uint32_t tlslen2 = sizeof(tlsbuf2); + uint8_t tlsbuf3[] = { 0x01 }; + uint32_t tlslen3 = sizeof(tlsbuf3); + uint8_t tlsbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x02 }; + uint32_t tlslen4 = sizeof(tlsbuf4); + TcpSession ssn; + Packet p; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + memset(&th_v, 0, sizeof(th_v)); + memset(&p, 0, sizeof(p)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = tlsbuf4; + p.payload_len = tlslen4; + p.proto = IPPROTO_TCP; + + StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize()); + f.protoctx = (void *)&ssn; + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + ssn.alproto = ALPROTO_TLS; + + DetectEngineCtx *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:\"TLS\"; tls.version:1.0; content:\"|01 00 00 AD|\"; sid:1;)"); + if (s == NULL) { + goto end; + } + + if (s->flags & SIG_FLAG_PACKET) { + SCLogDebug("SIG_FLAG_PACKET flags"); + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1, FALSE); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2, FALSE); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3, FALSE); + if (r != 0) { + printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf4, tlslen4, FALSE); + if (r != 0) { + printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + TlsState *tls_state = ssn.aldata[AlpGetStateIdx(ALPROTO_TLS)]; + if (tls_state == NULL) { + printf("no tls state: "); + goto end; + } + + if (tls_state->client_content_type != 0x16) { + printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, tls_state->client_content_type); + goto end; + } + + if (tls_state->client_version != TLS_VERSION_10) { + printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version); + goto end; + } + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + + if (!(PacketAlertCheck(&p, 1))) { printf("signature 1 didn't match while it should have: "); goto end; } @@ -519,6 +617,7 @@ void DetectTlsVersionRegisterTests(void) { UtRegisterTest("DetectTlsVersionTestParse02", DetectTlsVersionTestParse02, 1); UtRegisterTest("DetectTlsVersionTestDetect01", DetectTlsVersionTestDetect01, 1); UtRegisterTest("DetectTlsVersionTestDetect02", DetectTlsVersionTestDetect02, 1); + UtRegisterTest("DetectTlsVersionTestDetect03", DetectTlsVersionTestDetect03, 1); #endif /* UNITTESTS */ } diff --git a/src/detect.c b/src/detect.c index b0f9fe1707..3ec540ffd4 100644 --- a/src/detect.c +++ b/src/detect.c @@ -357,6 +357,8 @@ int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, uint8_ { /* XXX overflow check? */ + SCLogDebug("sid %"PRIu32"", sid); + if (gid > 1) p->alerts.alerts[p->alerts.cnt].gid = gid; else @@ -425,6 +427,7 @@ inline SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx SCReturnPtr(sgh, "SigGroupHead"); } +#include "flow-bit.h" /** \brief application layer detection * * \param sgh signature group head for this proto/addrs/ports @@ -466,14 +469,17 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, sig = sgh->match_array[idx]; s = de_ctx->sig_array[sig]; + SCLogDebug("s->id %"PRIu32"", s->id); + /* only inspect app layer sigs here */ if (!(s->flags & SIG_FLAG_APPLAYER)) continue; /* filter out the sigs that inspects the payload, if packet no payload inspection flag is set*/ - if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->flags & SIG_FLAG_PAYLOAD)) + if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->flags & SIG_FLAG_PAYLOAD)) { continue; + } /* check the source & dst port in the sig */ if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) { @@ -503,7 +509,8 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, continue; } - /* if we don't have sigmatches at this point we're a match */ + /* if we don't have sigmatches at this point we're a match + * XXX VJ can we ever get here? Applayer inspection w/o sigmatches */ if (s->match == NULL) { fmatch = 1; if (!(s->flags & SIG_FLAG_NOALERT)) { @@ -522,10 +529,13 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, while (sm) { if (sigmatch_table[sm->type].AppLayerMatch == NULL) { /* if no match function we assume this sm is a match */ + SCLogDebug("no app layer match function, sigmatch is (pkt)Match only"); match = 1; } else { match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm); + SCLogDebug("sigmatch AppLayerMatch function returned match %"PRIu32"", match); } + if (match) { /* okay, try the next match */ sm = sm->next; @@ -533,12 +543,28 @@ static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, /* only if the last matched as well, we have a hit */ if (sm == NULL) { fmatch = 1; - //printf("DE : sig %" PRIu32 " matched\n", s->id); + + SCLogDebug("DE : sig %" PRIu32 " matched", s->id); + if (!(s->flags & SIG_FLAG_NOALERT)) { + /* if the sig also has a packet portion see if that has matched already */ + if (s->flags & SIG_FLAG_PACKET) { + SCLogDebug("checking sid %"PRIu32"", s->id); + + if (FlowBitIsset(p->flow, s->id) ) { + SCLogDebug("flowbit sid %"PRIu32", isset", s->id); + + PacketAlertAppend(p, 1, s->id, s->rev, s->prio, s->msg); + + /* set verdict on packet */ + p->action = s->action; + } + } else { + PacketAlertAppend(p, 1, s->id, s->rev, s->prio, s->msg); - PacketAlertHandle(de_ctx,s,p); - /* set verdict on packet */ - p->action = s->action; + /* set verdict on packet */ + p->action = s->action; + } } } } else { @@ -635,8 +661,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh continue; } - /* don't inspect app layer sigs here */ - if (s->flags & SIG_FLAG_APPLAYER) + /* don't inspect app layer only sigs here */ + if (!(s->flags & SIG_FLAG_PACKET)) continue; /* filter out sigs that want pattern matches, but @@ -751,8 +777,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SCLogDebug("running match functions, sm %p", sm); while (sm) { + /* if this sm has no Match function we assume it's a match */ if (sigmatch_table[sm->type].Match == NULL) { - /* if no match function we assume this sm is a match */ match = 1; } else { match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm); @@ -765,10 +791,18 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (sm == NULL) { fmatch = 1; if (!(s->flags & SIG_FLAG_NOALERT)) { + SCLogDebug("sig matched, applayer flag set ? %s", s->flags & SIG_FLAG_APPLAYER ? "yes":"no"); - PacketAlertHandle(de_ctx,s,p); - /* set verdict on packet */ - p->action = s->action; + /* set flowbit for this match */ + if (s->flags & SIG_FLAG_APPLAYER) { + SCLogDebug("setting flowbit for sig %"PRIu32"", s->id); + FlowBitSet(p->flow, s->id); + } else { + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg); + + /* set verdict on packet */ + p->action = s->action; + } } } } else { diff --git a/src/detect.h b/src/detect.h index 90d405ab6d..4103d51e65 100644 --- a/src/detect.h +++ b/src/detect.h @@ -130,9 +130,11 @@ typedef struct DetectPort_ { #define SIG_FLAG_PAYLOAD 0x0200 /**< signature is inspecting the packet payload */ #define SIG_FLAG_DSIZE 0x0400 /**< signature has a dsize setting */ #define SIG_FLAG_FLOW 0x0800 /**< signature has a flow setting */ + #define SIG_FLAG_MPM_NEGCONTENT 0x1000 /**< sig has negative mpm portion(!content) */ #define SIG_FLAG_APPLAYER 0x2000 /**< signature applies to app layer instead of packets */ #define SIG_FLAG_BIDIREC 0x4000 /**< signature has bidirectional operator */ +#define SIG_FLAG_PACKET 0x8000 /**< signature has matches against a packet (as opposed to app layer) */ /* Detection Engine flags */ #define DE_QUIET 0x01 /**< DE is quiet (esp for unittests) */