]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/http_stat_code: move tests into tests/
authorVictor Julien <victor@inliniac.net>
Mon, 26 Nov 2018 12:13:59 +0000 (13:13 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 29 Jan 2019 12:27:57 +0000 (13:27 +0100)
src/Makefile.am
src/detect-engine-hscd.h [deleted file]
src/detect-engine-mpm.c
src/detect-engine-register.c
src/detect-http-stat-code.c
src/runmode-unittests.c
src/tests/detect-http-stat-code.c [moved from src/detect-engine-hscd.c with 76% similarity]

index 05edb783aad99e7479874246afa232cd7e610af7..b4a62f0d0361087fd15059c585588ee69bbde872 100644 (file)
@@ -135,7 +135,6 @@ detect-engine-hcbd.c detect-engine-hcbd.h \
 detect-engine-hcd.c detect-engine-hcd.h \
 detect-engine-hrhd.c detect-engine-hrhd.h \
 detect-engine-hsbd.c detect-engine-hsbd.h \
-detect-engine-hscd.c detect-engine-hscd.h \
 detect-engine-iponly.c detect-engine-iponly.h \
 detect-engine-loader.c detect-engine-loader.h \
 detect-engine-mpm.c detect-engine-mpm.h \
diff --git a/src/detect-engine-hscd.h b/src/detect-engine-hscd.h
deleted file mode 100644 (file)
index 90fb9d7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (C) 2007-2016 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 <anoopsaldanha@gmail.com>
- */
-
-#ifndef __DETECT_ENGINE_HSCD_H__
-#define __DETECT_ENGINE_HSCD_H__
-
-void DetectEngineHttpStatCodeRegisterTests(void);
-
-#endif /* __DETECT_ENGINE_HSCD_H__ */
index fea3ae9ed16ddea78236722fc40078b6cf2cdae8..b838fdaafab0d19e931cba0cba71b4558bb27314 100644 (file)
@@ -52,7 +52,6 @@
 #include "detect-engine-payload.h"
 #include "detect-engine-hrhd.h"
 #include "detect-engine-hcd.h"
-#include "detect-engine-hscd.h"
 #include "detect-engine-hcbd.h"
 #include "detect-engine-hsbd.h"
 #include "detect-engine-dns.h"
index 57d52b85fef01535e8e3525cb43ed90123ec19e1..15081b7dd0c0d9ca28ffbed33879a713873bbbf0 100644 (file)
 #include "detect-engine-hsbd.h"
 #include "detect-engine-hrhd.h"
 #include "detect-engine-hcd.h"
-#include "detect-engine-hscd.h"
 #include "detect-byte-extract.h"
 #include "detect-file-data.h"
 #include "detect-pkt-data.h"
index a2ef823eb1d6ed3ade136eafa7e06719aa84e2cd..02ad637b4cf8a3792bed0d7089a2373d76b98284 100644 (file)
 
 #include "app-layer-htp.h"
 #include "detect-http-stat-code.h"
-#include "detect-engine-hscd.h"
 #include "stream-tcp-private.h"
 #include "stream-tcp.h"
 
 static int DetectHttpStatCodeSetup(DetectEngineCtx *, Signature *, const char *);
+#ifdef UNITTESTS
 static void DetectHttpStatCodeRegisterTests(void);
+#endif
 static int g_http_stat_code_buffer_id = 0;
-
 static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
         const DetectEngineTransforms *transforms, Flow *_f,
         const uint8_t _flow_flags, void *txv, const int list_id);
@@ -81,8 +81,9 @@ void DetectHttpStatCodeRegister (void)
     sigmatch_table[DETECT_AL_HTTP_STAT_CODE].desc = "content modifier to match only on HTTP stat-code-buffer";
     sigmatch_table[DETECT_AL_HTTP_STAT_CODE].url = DOC_URL DOC_VERSION "/rules/http-keywords.html#http-stat-code";
     sigmatch_table[DETECT_AL_HTTP_STAT_CODE].Setup = DetectHttpStatCodeSetup;
+#ifdef UNITTESTS
     sigmatch_table[DETECT_AL_HTTP_STAT_CODE].RegisterTests = DetectHttpStatCodeRegisterTests;
-
+#endif
     sigmatch_table[DETECT_AL_HTTP_STAT_CODE].flags |= SIGMATCH_NOOPT;
 
     DetectAppLayerInspectEngineRegister2("http_stat_code", ALPROTO_HTTP,
@@ -142,583 +143,8 @@ static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
 }
 
 #ifdef UNITTESTS
-
-/**
- * \test Checks if a http_stat_code is registered in a Signature, if content is not
- *       specified in the signature or rawbyes is specified or fast_pattern is
- *       provided in the signature.
- */
-static int DetectHttpStatCodeTest01(void)
-{
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
-        printf("DetectEngineCtxInit failed: ");
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-            "(msg:\"Testing http_stat_code\"; http_stat_code; sid:1;)");
-    if (de_ctx->sig_list != NULL) {
-        printf("sid 1 parse failed to error out: ");
-        goto end;
-    }
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-            "(msg:\"Testing http_stat_code\"; content:\"|FF F1|\";"
-            " rawbytes; http_stat_code; sid:2;)");
-    if (de_ctx->sig_list != NULL) {
-        printf("sid 2 parse failed to error out: ");
-        goto end;
-    }
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-            "(msg:\"Testing http_stat_code\"; content:\"100\";"
-            "fast_pattern; http_stat_code; sid:3;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("sid 3 parse failed: ");
-        goto end;
-    }
-    if (!(((DetectContentData *)de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id]->ctx)->flags &
-        DETECT_CONTENT_FAST_PATTERN))
-    {
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-    return result;
-}
-
-/**
- * \test Checks if a http_stat_code is registered in a Signature and also checks
- *       the nocase
- */
-static int DetectHttpStatCodeTest02(void)
-{
-    SigMatch *sm = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-
-    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
-        goto end;
-
-    de_ctx->flags |= DE_QUIET;
-    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
-                               "(msg:\"Testing http_stat_code\"; content:\"one\"; "
-                               "http_stat_code; content:\"200\"; http_stat_code; "
-                               "content:\"two hundred\"; nocase; http_stat_code; "
-                               "sid:1;)");
-    if (de_ctx->sig_list == NULL) {
-        printf("sig parse failed: ");
-        goto end;
-    }
-
-    result = 0;
-    sm = de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id];
-    if (sm == NULL) {
-        printf("no sigmatch(es): ");
-        goto end;
-    }
-
-    SigMatch *prev = NULL;
-    while (sm != NULL) {
-        if (sm->type == DETECT_CONTENT) {
-            result = 1;
-        } else {
-            printf("expected DETECT_CONTENT for http_stat_code, got %d: ", sm->type);
-            goto end;
-        }
-        prev = sm;
-        sm = sm->next;
-    }
-
-    if (! (((DetectContentData *)prev->ctx)->flags &
-           DETECT_CONTENT_NOCASE))
-    {
-        result = 0;
-    }
-end:
-    if (de_ctx != NULL)
-        DetectEngineCtxFree(de_ctx);
-    return result;
-}
-
-/** \test Check the signature working to alert when http_stat_code is matched . */
-static int DetectHttpStatCodeSigTest01(void)
-{
-    int result = 0;
-    Flow f;
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-    TcpSession ssn;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    ThreadVars th_v;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOCLIENT;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        printf("DetectEngineCtxInit failed: ");
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
-            "\"HTTP status code\"; content:\"200\"; http_stat_code; sid:1;)");
-    if (s == NULL) {
-        printf("sig parse failed: ");
-        goto end;
-    }
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, httpbuf1, httplen1);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-
-    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                            STREAM_TOCLIENT, httpbuf2, httplen2);
-    if (r != 0) {
-        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
-
-    StreamTcpFreeConfig(TRUE);
-
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/** \test Check the signature working to alert when http_stat_code is not matched . */
-static int DetectHttpStatCodeSigTest02(void)
-{
-    int result = 0;
-    Flow f;
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-    TcpSession ssn;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    ThreadVars th_v;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOCLIENT;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
-                                   "\"HTTP status code\"; content:\"no\"; "
-                                   "http_stat_code; sid:1;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
-                        "Status code\"; content:\"100\";"
-                        "http_stat_code; sid:2;)");
-    if (s->next == NULL) {
-        goto end;
-    }
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, httpbuf1, httplen1);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-
-    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                            STREAM_TOCLIENT, httpbuf2, httplen2);
-    if (r != 0) {
-        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 matched but shouldn't: ");
-        goto end;
-    }
-    if ((PacketAlertCheck(p, 2))) {
-        printf("sid 2 match but shouldn't have: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
-
-    StreamTcpFreeConfig(TRUE);
-
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/** \test Check the signature working to alert when http_stat_code is matched for
- *        for nocase or not */
-static int DetectHttpStatCodeSigTest03(void)
-{
-    int result = 0;
-    Flow f;
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-    uint8_t httpbuf2[] = "HTTP/1.0 FAIL OK\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-    TcpSession ssn;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    ThreadVars th_v;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOCLIENT;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
-                                   "\"HTTP status code\"; content:\"FAIL\"; "
-                                   "http_stat_code; sid:1;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
-                        "Status code nocase\"; content:\"fail\"; nocase; "
-                        "http_stat_code; sid:2;)");
-    if (s->next == NULL) {
-        goto end;
-    }
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, httpbuf1, httplen1);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-
-    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                            STREAM_TOCLIENT, httpbuf2, httplen2);
-    if (r != 0) {
-        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-    if (!(PacketAlertCheck(p, 2))) {
-        printf("sid 2 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
-
-    StreamTcpFreeConfig(TRUE);
-
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-/** \test Check the signature working to alert when http_stat_code is matched for
- *        for negatoin or not */
-static int DetectHttpStatCodeSigTest04(void)
-{
-    int result = 0;
-    Flow f;
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-    TcpSession ssn;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    ThreadVars th_v;
-    DetectEngineThreadCtx *det_ctx = NULL;
-    HtpState *http_state = NULL;
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&f, 0, sizeof(f));
-    memset(&ssn, 0, sizeof(ssn));
-
-    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.protoctx = (void *)&ssn;
-    f.proto = IPPROTO_TCP;
-    f.flags |= FLOW_IPV4;
-
-    p->flow = &f;
-    p->flowflags |= FLOW_PKT_TOCLIENT;
-    p->flowflags |= FLOW_PKT_ESTABLISHED;
-    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
-    f.alproto = ALPROTO_HTTP;
-
-    StreamTcpInitConfig(TRUE);
-
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
-                                   "\"HTTP status code\"; content:\"200\"; "
-                                   "http_stat_code; sid:1;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
-                        "Status code negation\"; content:!\"100\"; nocase; "
-                        "http_stat_code; sid:2;)");
-    if (s->next == NULL) {
-        goto end;
-    }
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                                STREAM_TOSERVER, httpbuf1, httplen1);
-    if (r != 0) {
-        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-
-    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
-                            STREAM_TOCLIENT, httpbuf2, httplen2);
-    if (r != 0) {
-        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
-        result = 0;
-        FLOWLOCK_UNLOCK(&f);
-        goto end;
-    }
-    FLOWLOCK_UNLOCK(&f);
-
-    http_state = f.alstate;
-    if (http_state == NULL) {
-        printf("no http state: ");
-        result = 0;
-        goto end;
-    }
-
-    /* do detect */
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    if (!(PacketAlertCheck(p, 1))) {
-        printf("sid 1 didn't match but should have: ");
-        goto end;
-    }
-    if (!(PacketAlertCheck(p, 2))) {
-        printf("sid 2 didn't match but should have: ");
-        goto end;
-    }
-
-    result = 1;
-end:
-    if (alp_tctx != NULL)
-        AppLayerParserThreadCtxFree(alp_tctx);
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
-
-    StreamTcpFreeConfig(TRUE);
-
-    UTHFreePackets(&p, 1);
-    return result;
-}
-
-#endif /* UNITTESTS */
-
-/**
- * \brief   Register the UNITTESTS for the http_stat_code keyword
- */
-void DetectHttpStatCodeRegisterTests (void)
-{
-#ifdef UNITTESTS /* UNITTESTS */
-
-    UtRegisterTest("DetectHttpStatCodeTest01", DetectHttpStatCodeTest01);
-    UtRegisterTest("DetectHttpStatCodeTest02", DetectHttpStatCodeTest02);
-    UtRegisterTest("DetectHttpStatCodeSigTest01", DetectHttpStatCodeSigTest01);
-    UtRegisterTest("DetectHttpStatCodeSigTest02", DetectHttpStatCodeSigTest02);
-    UtRegisterTest("DetectHttpStatCodeSigTest03", DetectHttpStatCodeSigTest03);
-    UtRegisterTest("DetectHttpStatCodeSigTest04", DetectHttpStatCodeSigTest04);
-
+#include "tests/detect-http-stat-code.c"
 #endif /* UNITTESTS */
-}
 
 /**
  * @}
index 81f5e85a74e4349dae566d2864fdd2f3ae9091d6..dc4cba74c9a2e7ddeea90d373d759e41b67c0eed 100644 (file)
@@ -40,7 +40,6 @@
 #include "detect-engine-hsbd.h"
 #include "detect-engine-hrhd.h"
 #include "detect-engine-hcd.h"
-#include "detect-engine-hscd.h"
 #include "detect-engine-state.h"
 #include "detect-engine-tag.h"
 #include "detect-engine-modbus.h"
@@ -197,7 +196,6 @@ static void RegisterUnittests(void)
     DetectEngineHttpServerBodyRegisterTests();
     DetectEngineHttpRawHeaderRegisterTests();
     DetectEngineHttpCookieRegisterTests();
-    DetectEngineHttpStatCodeRegisterTests();
     DetectEngineInspectModbusRegisterTests();
     DetectEngineRegisterTests();
     DetectEngineSMTPFiledataRegisterTests();
similarity index 76%
rename from src/detect-engine-hscd.c
rename to src/tests/detect-http-stat-code.c
index 1507e84e8b91e9698e5878cb7043b6611e509b34..5987b0e3e3ac75ccf097929022c6db88003ffb50 100644 (file)
  * \author Victor Julien <victor@inliniac.net>
  */
 
-#include "suricata-common.h"
-#include "suricata.h"
-#include "decode.h"
-
-#include "detect.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-hscd.h"
-#include "detect-parse.h"
-#include "detect-engine-state.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-engine-prefilter.h"
-
-#include "flow-util.h"
-#include "util-debug.h"
-#include "util-print.h"
-#include "flow.h"
-
-#include "stream-tcp.h"
-
-#include "app-layer-parser.h"
-
-#include "util-unittest.h"
-#include "util-unittest-helper.h"
-#include "app-layer.h"
-#include "app-layer-htp.h"
-#include "app-layer-protos.h"
-#include "util-validate.h"
-
-/***********************************Unittests**********************************/
-
-#ifdef UNITTESTS
+#include "../suricata-common.h"
+#include "../suricata.h"
+#include "../flow-util.h"
+#include "../flow.h"
+#include "../app-layer-parser.h"
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+#include "../app-layer.h"
+#include "../app-layer-htp.h"
+#include "../app-layer-protos.h"
 
 static int DetectEngineHttpStatCodeTest01(void)
- {
+{
     TcpSession ssn;
     Packet *p1 = NULL;
     Packet *p2 = NULL;
@@ -1957,12 +1935,569 @@ end:
     return result;
 }
 
-#endif /* UNITTESTS */
+/**
+ * \test Checks if a http_stat_code is registered in a Signature, if content is not
+ *       specified in the signature or rawbyes is specified or fast_pattern is
+ *       provided in the signature.
+ */
+static int DetectHttpStatCodeTest01(void)
+{
+    DetectEngineCtx *de_ctx = NULL;
+    int result = 0;
+
+    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
+        printf("DetectEngineCtxInit failed: ");
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+            "(msg:\"Testing http_stat_code\"; http_stat_code; sid:1;)");
+    if (de_ctx->sig_list != NULL) {
+        printf("sid 1 parse failed to error out: ");
+        goto end;
+    }
+
+    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+            "(msg:\"Testing http_stat_code\"; content:\"|FF F1|\";"
+            " rawbytes; http_stat_code; sid:2;)");
+    if (de_ctx->sig_list != NULL) {
+        printf("sid 2 parse failed to error out: ");
+        goto end;
+    }
+
+    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+            "(msg:\"Testing http_stat_code\"; content:\"100\";"
+            "fast_pattern; http_stat_code; sid:3;)");
+    if (de_ctx->sig_list == NULL) {
+        printf("sid 3 parse failed: ");
+        goto end;
+    }
+    if (!(((DetectContentData *)de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id]->ctx)->flags &
+        DETECT_CONTENT_FAST_PATTERN))
+    {
+        goto end;
+    }
+
+    result = 1;
+end:
+    if (de_ctx != NULL)
+        DetectEngineCtxFree(de_ctx);
+    return result;
+}
 
-void DetectEngineHttpStatCodeRegisterTests(void)
+/**
+ * \test Checks if a http_stat_code is registered in a Signature and also checks
+ *       the nocase
+ */
+static int DetectHttpStatCodeTest02(void)
 {
+    SigMatch *sm = NULL;
+    DetectEngineCtx *de_ctx = NULL;
+    int result = 0;
+
+    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+        goto end;
+
+    de_ctx->flags |= DE_QUIET;
+    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+                               "(msg:\"Testing http_stat_code\"; content:\"one\"; "
+                               "http_stat_code; content:\"200\"; http_stat_code; "
+                               "content:\"two hundred\"; nocase; http_stat_code; "
+                               "sid:1;)");
+    if (de_ctx->sig_list == NULL) {
+        printf("sig parse failed: ");
+        goto end;
+    }
 
-#ifdef UNITTESTS
+    result = 0;
+    sm = de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id];
+    if (sm == NULL) {
+        printf("no sigmatch(es): ");
+        goto end;
+    }
+
+    SigMatch *prev = NULL;
+    while (sm != NULL) {
+        if (sm->type == DETECT_CONTENT) {
+            result = 1;
+        } else {
+            printf("expected DETECT_CONTENT for http_stat_code, got %d: ", sm->type);
+            goto end;
+        }
+        prev = sm;
+        sm = sm->next;
+    }
+
+    if (! (((DetectContentData *)prev->ctx)->flags &
+           DETECT_CONTENT_NOCASE))
+    {
+        result = 0;
+    }
+end:
+    if (de_ctx != NULL)
+        DetectEngineCtxFree(de_ctx);
+    return result;
+}
+
+/** \test Check the signature working to alert when http_stat_code is matched . */
+static int DetectHttpStatCodeSigTest01(void)
+{
+    int result = 0;
+    Flow f;
+    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
+    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+    TcpSession ssn;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+    HtpState *http_state = NULL;
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+    memset(&th_v, 0, sizeof(th_v));
+    memset(&f, 0, sizeof(f));
+    memset(&ssn, 0, sizeof(ssn));
+
+    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+    FLOW_INITIALIZE(&f);
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
+
+    p->flow = &f;
+    p->flowflags |= FLOW_PKT_TOCLIENT;
+    p->flowflags |= FLOW_PKT_ESTABLISHED;
+    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+    f.alproto = ALPROTO_HTTP;
+
+    StreamTcpInitConfig(TRUE);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        printf("DetectEngineCtxInit failed: ");
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
+            "\"HTTP status code\"; content:\"200\"; http_stat_code; sid:1;)");
+    if (s == NULL) {
+        printf("sig parse failed: ");
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                                STREAM_TOSERVER, httpbuf1, httplen1);
+    if (r != 0) {
+        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+
+    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                            STREAM_TOCLIENT, httpbuf2, httplen2);
+    if (r != 0) {
+        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+    FLOWLOCK_UNLOCK(&f);
+
+    http_state = f.alstate;
+    if (http_state == NULL) {
+        printf("no http state: ");
+        goto end;
+    }
+
+    /* do detect */
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    if (!(PacketAlertCheck(p, 1))) {
+        printf("sid 1 didn't match but should have: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    if (alp_tctx != NULL)
+        AppLayerParserThreadCtxFree(alp_tctx);
+    if (det_ctx != NULL) {
+        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    }
+    if (de_ctx != NULL) {
+        DetectEngineCtxFree(de_ctx);
+    }
+
+    StreamTcpFreeConfig(TRUE);
+
+    UTHFreePackets(&p, 1);
+    return result;
+}
+
+/** \test Check the signature working to alert when http_stat_code is not matched . */
+static int DetectHttpStatCodeSigTest02(void)
+{
+    int result = 0;
+    Flow f;
+    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
+    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+    TcpSession ssn;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+    HtpState *http_state = NULL;
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+    memset(&th_v, 0, sizeof(th_v));
+    memset(&f, 0, sizeof(f));
+    memset(&ssn, 0, sizeof(ssn));
+
+    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+    FLOW_INITIALIZE(&f);
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
+
+    p->flow = &f;
+    p->flowflags |= FLOW_PKT_TOCLIENT;
+    p->flowflags |= FLOW_PKT_ESTABLISHED;
+    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+    f.alproto = ALPROTO_HTTP;
+
+    StreamTcpInitConfig(TRUE);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
+                                   "\"HTTP status code\"; content:\"no\"; "
+                                   "http_stat_code; sid:1;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+                        "Status code\"; content:\"100\";"
+                        "http_stat_code; sid:2;)");
+    if (s->next == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                                STREAM_TOSERVER, httpbuf1, httplen1);
+    if (r != 0) {
+        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+
+    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                            STREAM_TOCLIENT, httpbuf2, httplen2);
+    if (r != 0) {
+        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+    FLOWLOCK_UNLOCK(&f);
+
+    http_state = f.alstate;
+    if (http_state == NULL) {
+        printf("no http state: ");
+        result = 0;
+        goto end;
+    }
+
+    /* do detect */
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    if (PacketAlertCheck(p, 1)) {
+        printf("sid 1 matched but shouldn't: ");
+        goto end;
+    }
+    if ((PacketAlertCheck(p, 2))) {
+        printf("sid 2 match but shouldn't have: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    if (alp_tctx != NULL)
+        AppLayerParserThreadCtxFree(alp_tctx);
+    if (det_ctx != NULL) {
+        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    }
+    if (de_ctx != NULL) {
+        DetectEngineCtxFree(de_ctx);
+    }
+
+    StreamTcpFreeConfig(TRUE);
+
+    UTHFreePackets(&p, 1);
+    return result;
+}
+
+/** \test Check the signature working to alert when http_stat_code is matched for
+ *        for nocase or not */
+static int DetectHttpStatCodeSigTest03(void)
+{
+    int result = 0;
+    Flow f;
+    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+    uint8_t httpbuf2[] = "HTTP/1.0 FAIL OK\r\n\r\n";
+    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+    TcpSession ssn;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+    HtpState *http_state = NULL;
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+    memset(&th_v, 0, sizeof(th_v));
+    memset(&f, 0, sizeof(f));
+    memset(&ssn, 0, sizeof(ssn));
+
+    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+    FLOW_INITIALIZE(&f);
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
+
+    p->flow = &f;
+    p->flowflags |= FLOW_PKT_TOCLIENT;
+    p->flowflags |= FLOW_PKT_ESTABLISHED;
+    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+    f.alproto = ALPROTO_HTTP;
+
+    StreamTcpInitConfig(TRUE);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
+                                   "\"HTTP status code\"; content:\"FAIL\"; "
+                                   "http_stat_code; sid:1;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+                        "Status code nocase\"; content:\"fail\"; nocase; "
+                        "http_stat_code; sid:2;)");
+    if (s->next == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                                STREAM_TOSERVER, httpbuf1, httplen1);
+    if (r != 0) {
+        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+
+    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                            STREAM_TOCLIENT, httpbuf2, httplen2);
+    if (r != 0) {
+        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+    FLOWLOCK_UNLOCK(&f);
+
+    http_state = f.alstate;
+    if (http_state == NULL) {
+        printf("no http state: ");
+        result = 0;
+        goto end;
+    }
+
+    /* do detect */
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    if (!(PacketAlertCheck(p, 1))) {
+        printf("sid 1 didn't match but should have: ");
+        goto end;
+    }
+    if (!(PacketAlertCheck(p, 2))) {
+        printf("sid 2 didn't match but should have: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    if (alp_tctx != NULL)
+        AppLayerParserThreadCtxFree(alp_tctx);
+    if (det_ctx != NULL) {
+        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    }
+    if (de_ctx != NULL) {
+        DetectEngineCtxFree(de_ctx);
+    }
+
+    StreamTcpFreeConfig(TRUE);
+
+    UTHFreePackets(&p, 1);
+    return result;
+}
+
+/** \test Check the signature working to alert when http_stat_code is matched for
+ *        for negatoin or not */
+static int DetectHttpStatCodeSigTest04(void)
+{
+    int result = 0;
+    Flow f;
+    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
+    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+    TcpSession ssn;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+    HtpState *http_state = NULL;
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+    memset(&th_v, 0, sizeof(th_v));
+    memset(&f, 0, sizeof(f));
+    memset(&ssn, 0, sizeof(ssn));
+
+    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+    FLOW_INITIALIZE(&f);
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
+
+    p->flow = &f;
+    p->flowflags |= FLOW_PKT_TOCLIENT;
+    p->flowflags |= FLOW_PKT_ESTABLISHED;
+    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+    f.alproto = ALPROTO_HTTP;
+
+    StreamTcpInitConfig(TRUE);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
+                                   "\"HTTP status code\"; content:\"200\"; "
+                                   "http_stat_code; sid:1;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+                        "Status code negation\"; content:!\"100\"; nocase; "
+                        "http_stat_code; sid:2;)");
+    if (s->next == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                                STREAM_TOSERVER, httpbuf1, httplen1);
+    if (r != 0) {
+        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+
+    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
+                            STREAM_TOCLIENT, httpbuf2, httplen2);
+    if (r != 0) {
+        printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        FLOWLOCK_UNLOCK(&f);
+        goto end;
+    }
+    FLOWLOCK_UNLOCK(&f);
+
+    http_state = f.alstate;
+    if (http_state == NULL) {
+        printf("no http state: ");
+        result = 0;
+        goto end;
+    }
+
+    /* do detect */
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    if (!(PacketAlertCheck(p, 1))) {
+        printf("sid 1 didn't match but should have: ");
+        goto end;
+    }
+    if (!(PacketAlertCheck(p, 2))) {
+        printf("sid 2 didn't match but should have: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    if (alp_tctx != NULL)
+        AppLayerParserThreadCtxFree(alp_tctx);
+    if (det_ctx != NULL) {
+        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    }
+    if (de_ctx != NULL) {
+        DetectEngineCtxFree(de_ctx);
+    }
+
+    StreamTcpFreeConfig(TRUE);
+
+    UTHFreePackets(&p, 1);
+    return result;
+}
+
+/**
+ * \brief   Register the UNITTESTS for the http_stat_code keyword
+ */
+void DetectHttpStatCodeRegisterTests (void)
+{
     UtRegisterTest("DetectEngineHttpStatCodeTest01",
                    DetectEngineHttpStatCodeTest01);
     UtRegisterTest("DetectEngineHttpStatCodeTest02",
@@ -1993,9 +2528,13 @@ void DetectEngineHttpStatCodeRegisterTests(void)
                    DetectEngineHttpStatCodeTest14);
     UtRegisterTest("DetectEngineHttpStatCodeTest15",
                    DetectEngineHttpStatCodeTest15);
-#endif /* UNITTESTS */
 
-    return;
+    UtRegisterTest("DetectHttpStatCodeTest01", DetectHttpStatCodeTest01);
+    UtRegisterTest("DetectHttpStatCodeTest02", DetectHttpStatCodeTest02);
+    UtRegisterTest("DetectHttpStatCodeSigTest01", DetectHttpStatCodeSigTest01);
+    UtRegisterTest("DetectHttpStatCodeSigTest02", DetectHttpStatCodeSigTest02);
+    UtRegisterTest("DetectHttpStatCodeSigTest03", DetectHttpStatCodeSigTest03);
+    UtRegisterTest("DetectHttpStatCodeSigTest04", DetectHttpStatCodeSigTest04);
 }
 
 /**