summaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /src/tests
parentInitial commit. (diff)
downloadsuricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz
suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/app-layer-htp-file.c92
-rw-r--r--src/tests/detect-bsize.c175
-rw-r--r--src/tests/detect-engine-alert.c77
-rw-r--r--src/tests/detect-engine-content-inspection.c321
-rw-r--r--src/tests/detect-file-data.c69
-rw-r--r--src/tests/detect-http-client-body.c3010
-rw-r--r--src/tests/detect-http-cookie.c2623
-rw-r--r--src/tests/detect-http-header.c4651
-rw-r--r--src/tests/detect-http-host.c7111
-rw-r--r--src/tests/detect-http-method.c2207
-rw-r--r--src/tests/detect-http-raw-header.c3960
-rw-r--r--src/tests/detect-http-server-body.c8044
-rw-r--r--src/tests/detect-http-stat-code.c2324
-rw-r--r--src/tests/detect-http-stat-msg.c2213
-rw-r--r--src/tests/detect-http-uri.c6920
-rw-r--r--src/tests/detect-http-user-agent.c1221
-rw-r--r--src/tests/detect-http2.c161
-rw-r--r--src/tests/detect-icmpv4hdr.c45
-rw-r--r--src/tests/detect-icmpv6-mtu.c50
-rw-r--r--src/tests/detect-icmpv6hdr.c47
-rw-r--r--src/tests/detect-ipaddr.c47
-rw-r--r--src/tests/detect-ipv4hdr.c47
-rw-r--r--src/tests/detect-ipv6hdr.c47
-rw-r--r--src/tests/detect-parse.c154
-rw-r--r--src/tests/detect-snmp-community.c113
-rw-r--r--src/tests/detect-snmp-pdu_type.c40
-rw-r--r--src/tests/detect-snmp-version.c57
-rw-r--r--src/tests/detect-ssl-state.c137
-rw-r--r--src/tests/detect-ssl-version.c95
-rw-r--r--src/tests/detect-tcphdr.c47
-rw-r--r--src/tests/detect-template-buffer.c104
-rw-r--r--src/tests/detect-template.c63
-rw-r--r--src/tests/detect-tls-cert-fingerprint.c372
-rw-r--r--src/tests/detect-tls-cert-issuer.c376
-rw-r--r--src/tests/detect-tls-cert-serial.c374
-rw-r--r--src/tests/detect-tls-cert-subject.c376
-rw-r--r--src/tests/detect-tls-cert-validity.c1422
-rw-r--r--src/tests/detect-tls-certs.c364
-rw-r--r--src/tests/detect-tls-version.c63
-rw-r--r--src/tests/detect-transform-pcrexform.c86
-rw-r--r--src/tests/detect-transform-xor.c67
-rw-r--r--src/tests/detect-ttl.c223
-rw-r--r--src/tests/detect-udphdr.c47
-rw-r--r--src/tests/detect.c5150
-rw-r--r--src/tests/fuzz/fuzz_applayerparserparse.c213
-rw-r--r--src/tests/fuzz/fuzz_applayerprotodetectgetproto.c99
-rw-r--r--src/tests/fuzz/fuzz_confyamlloadstring.c31
-rw-r--r--src/tests/fuzz/fuzz_decodepcapfile.c101
-rw-r--r--src/tests/fuzz/fuzz_mimedecparseline.c66
-rw-r--r--src/tests/fuzz/fuzz_predefpcap_aware.c165
-rw-r--r--src/tests/fuzz/fuzz_siginit.c59
-rw-r--r--src/tests/fuzz/fuzz_sigpcap.c208
-rw-r--r--src/tests/fuzz/fuzz_sigpcap_aware.c203
-rw-r--r--src/tests/fuzz/onefile.c88
-rw-r--r--src/tests/reputation.c184
-rw-r--r--src/tests/source-pcap.c232
-rw-r--r--src/tests/stream-tcp-inline.c196
-rw-r--r--src/tests/stream-tcp-list.c732
-rw-r--r--src/tests/stream-tcp-reassemble.c209
-rw-r--r--src/tests/stream-tcp.c3463
60 files changed, 61441 insertions, 0 deletions
diff --git a/src/tests/app-layer-htp-file.c b/src/tests/app-layer-htp-file.c
new file mode 100644
index 0000000..6f7891c
--- /dev/null
+++ b/src/tests/app-layer-htp-file.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2019 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.
+ */
+
+#include "../app-layer-htp-file.h"
+#include "../util-unittest.h"
+
+/**
+ * \test AppLayerHtpFileParseContentRangeTest01 is a test
+ * for setting up a valid range value.
+ */
+
+static int AppLayerHtpFileParseContentRangeTest01 (void)
+{
+ HTTPContentRange range;
+ bstr * rawvalue = bstr_dup_c("bytes 12-25/100");
+ FAIL_IF_NOT(HTPParseContentRange(rawvalue, &range) == 0);
+ FAIL_IF_NOT(range.start == 12);
+ FAIL_IF_NOT(range.end == 25);
+ FAIL_IF_NOT(range.size == 100);
+ bstr_free(rawvalue);
+ PASS;
+}
+
+/**
+ * \test AppLayerHtpFileParseContentRangeTest02 is a regression test
+ * for setting up an invalid range value.
+ */
+
+static int AppLayerHtpFileParseContentRangeTest02 (void)
+{
+ HTTPContentRange range;
+ bstr * rawvalue = bstr_dup_c("bytes 15335424-27514354/");
+ FAIL_IF(HTPParseContentRange(rawvalue, &range) == 0);
+ bstr_free(rawvalue);
+ PASS;
+}
+
+/**
+ * \test AppLayerHtpFileParseContentRangeTest03 is a regression test
+ * for setting up an invalid range value.
+ */
+
+static int AppLayerHtpFileParseContentRangeTest03 (void)
+{
+ HTTPContentRange range;
+ bstr * rawvalue = bstr_dup_c("bytes 15335424-");
+ FAIL_IF(HTPParseContentRange(rawvalue, &range) == 0);
+ bstr_free(rawvalue);
+ PASS;
+}
+
+
+/**
+ * \test AppLayerHtpFileParseContentRangeTest04 is a test
+ * for setting up a valid range value without the size.
+ */
+
+static int AppLayerHtpFileParseContentRangeTest04 (void)
+{
+ HTTPContentRange range;
+ bstr * rawvalue = bstr_dup_c("bytes 24-42/*");
+ FAIL_IF_NOT(HTPParseContentRange(rawvalue, &range) == 0);
+ FAIL_IF_NOT(range.start == 24);
+ FAIL_IF_NOT(range.end == 42);
+ bstr_free(rawvalue);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for AppLayerHtpFile
+ */
+void AppLayerHtpFileRegisterTests(void)
+{
+ UtRegisterTest("AppLayerHtpFileParseContentRangeTest01", AppLayerHtpFileParseContentRangeTest01);
+ UtRegisterTest("AppLayerHtpFileParseContentRangeTest02", AppLayerHtpFileParseContentRangeTest02);
+ UtRegisterTest("AppLayerHtpFileParseContentRangeTest03", AppLayerHtpFileParseContentRangeTest03);
+ UtRegisterTest("AppLayerHtpFileParseContentRangeTest04", AppLayerHtpFileParseContentRangeTest04);
+}
diff --git a/src/tests/detect-bsize.c b/src/tests/detect-bsize.c
new file mode 100644
index 0000000..2fcd656
--- /dev/null
+++ b/src/tests/detect-bsize.c
@@ -0,0 +1,175 @@
+/* Copyright (C) 2017-2022 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.
+ */
+
+#include "../util-unittest.h"
+
+#define TEST_OK(str, m, lo, hi) \
+ { \
+ DetectU64Data *bsz = DetectBsizeParse((str)); \
+ FAIL_IF_NULL(bsz); \
+ FAIL_IF_NOT(bsz->mode == (m)); \
+ DetectBsizeFree(NULL, bsz); \
+ SCLogDebug("str %s OK", (str)); \
+ }
+#define TEST_FAIL(str) \
+ { \
+ DetectU64Data *bsz = DetectBsizeParse((str)); \
+ FAIL_IF_NOT_NULL(bsz); \
+ }
+
+static int DetectBsizeTest01(void)
+{
+ TEST_OK("50", DETECT_UINT_EQ, 50, 0);
+ TEST_OK(" 50", DETECT_UINT_EQ, 50, 0);
+ TEST_OK(" 50", DETECT_UINT_EQ, 50, 0);
+ TEST_OK(" 50 ", DETECT_UINT_EQ, 50, 0);
+ TEST_OK(" 50 ", DETECT_UINT_EQ, 50, 0);
+
+ TEST_FAIL("AA");
+ TEST_FAIL("5A");
+ TEST_FAIL("A5");
+ // bigger than UINT64_MAX
+ TEST_FAIL("100000000000000000001");
+ TEST_OK(" 1000000001 ", DETECT_UINT_EQ, 1000000001, 0);
+ PASS;
+}
+
+static int DetectBsizeTest02(void)
+{
+ TEST_OK(">50", DETECT_UINT_GT, 50, 0);
+ TEST_OK("> 50", DETECT_UINT_GT, 50, 0);
+ TEST_OK("> 50", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" >50", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" > 50", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" > 50", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" >50 ", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" > 50 ", DETECT_UINT_GT, 50, 0);
+ TEST_OK(" > 50 ", DETECT_UINT_GT, 50, 0);
+
+ TEST_FAIL(">>50");
+ TEST_FAIL("<>50");
+ TEST_FAIL(" > 50A");
+ PASS;
+}
+
+static int DetectBsizeTest03(void)
+{
+ TEST_OK("<50", DETECT_UINT_LT, 50, 0);
+ TEST_OK("< 50", DETECT_UINT_LT, 50, 0);
+ TEST_OK("< 50", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" <50", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" < 50", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" < 50", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" <50 ", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" < 50 ", DETECT_UINT_LT, 50, 0);
+ TEST_OK(" < 50 ", DETECT_UINT_LT, 50, 0);
+
+ TEST_FAIL(">>50");
+ TEST_FAIL(" < 50A");
+ PASS;
+}
+
+static int DetectBsizeTest04(void)
+{
+ TEST_OK("50<>100", DETECT_UINT_RA, 50, 100);
+
+ TEST_FAIL("50<$50");
+ TEST_FAIL("100<>50");
+ TEST_FAIL(">50<>100");
+ PASS;
+}
+
+#undef TEST_OK
+#undef TEST_FAIL
+
+#define TEST_OK(rule) \
+ { \
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
+ FAIL_IF_NULL(de_ctx); \
+ SCLogNotice("rule: %s", rule); \
+ Signature *s = DetectEngineAppendSig(de_ctx, (rule)); \
+ FAIL_IF_NULL(s); \
+ DetectEngineCtxFree(de_ctx); \
+ }
+
+#define TEST_FAIL(rule) \
+ { \
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
+ FAIL_IF_NULL(de_ctx); \
+ SCLogNotice("rule: %s", rule); \
+ Signature *s = DetectEngineAppendSig(de_ctx, (rule)); \
+ FAIL_IF_NOT_NULL(s); \
+ DetectEngineCtxFree(de_ctx); \
+ }
+
+static int DetectBsizeSigTest01(void)
+{
+ TEST_OK("alert http any any -> any any (http_request_line; bsize:10; sid:1;)");
+ TEST_OK("alert http any any -> any any (file_data; bsize:>1000; sid:2;)");
+
+ /* bsize validation with buffer */
+ TEST_OK("alert http any any -> any any (http.uri; content:\"/index.php\"; bsize:>1024; "
+ "sid:6;)");
+ TEST_OK("alert http any any -> any any (http.uri; content:\"abcdefgh123456\"; bsize:<20; "
+ " sid:9;)");
+ TEST_OK("alert http any any -> any any (http.uri; content:\"abcdefgh123456\"; bsize:15<>25; "
+ "sid:10;)");
+ TEST_OK("alert http any any -> any any (http.uri; content:\"abcdefgh123456\"; bsize:10<>15; "
+ "sid:13;)");
+
+ TEST_FAIL("alert tcp any any -> any any (content:\"abc\"; bsize:10; sid:3;)");
+ TEST_FAIL("alert http any any -> any any (content:\"GET\"; http_method; bsize:10; sid:4;)");
+ TEST_FAIL("alert http any any -> any any (http_request_line; content:\"GET\"; bsize:<10>; "
+ "sid:5;)");
+
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abcdefgh123456\"; bsize:2; "
+ "sid:11;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abcdefgh123456\"; bsize:<13; "
+ "sid:12;)");
+ TEST_FAIL(
+ "alert http any any -> any any (http.uri; content:\"abcdef\"; content: \"g\"; bsize:1; "
+ "sid:7;)");
+ TEST_FAIL(
+ "alert http any any -> any any (http.uri; content:\"abcdef\"; content: \"g\"; bsize:4; "
+ "sid:8;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abcdefghi123456\"; offset:12; "
+ "bsize:3; sid:14;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abc\"; offset:3; depth:3; "
+ "bsize:3; sid:15;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abcdef\"; content: \"gh\"; "
+ "bsize:1; sid:16;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abc\"; offset:3; bsize:3; "
+ "sid:17;)");
+ TEST_FAIL("alert http any any -> any any (http.uri; content:\"abc\"; offset:65535; bsize:3; "
+ "sid:18;)");
+ TEST_FAIL("alert http any any -> any any (http.user_agent; content:\"Suricata-UA\"; bsize:11; "
+ "content:!\"abc\"; distance:2; within:3; sid: 19;)");
+ PASS;
+}
+
+#undef TEST_OK
+#undef TEST_FAIL
+
+static void DetectBsizeRegisterTests(void)
+{
+ UtRegisterTest("DetectBsizeTest01 EQ", DetectBsizeTest01);
+ UtRegisterTest("DetectBsizeTest02 GT", DetectBsizeTest02);
+ UtRegisterTest("DetectBsizeTest03 LT", DetectBsizeTest03);
+ UtRegisterTest("DetectBsizeTest04 RA", DetectBsizeTest04);
+
+ UtRegisterTest("DetectBsizeSigTest01", DetectBsizeSigTest01);
+}
diff --git a/src/tests/detect-engine-alert.c b/src/tests/detect-engine-alert.c
new file mode 100644
index 0000000..86bc8d4
--- /dev/null
+++ b/src/tests/detect-engine-alert.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2022 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-engine.h"
+#include "../detect-engine-alert.h"
+#include "../detect-parse.h"
+
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+
+/**
+ * \brief Tests that the reject action is correctly set in Packet->action
+ */
+static int TestDetectAlertPacketApplySignatureActions01(void)
+{
+#ifdef HAVE_LIBNET11
+ uint8_t payload[] = "Hi all!";
+ uint16_t length = sizeof(payload) - 1;
+ Packet *p = UTHBuildPacketReal(
+ (uint8_t *)payload, length, IPPROTO_TCP, "192.168.1.5", "192.168.1.1", 41424, 80);
+ FAIL_IF_NULL(p);
+
+ const char sig[] = "reject tcp any any -> any 80 (content:\"Hi all\"; sid:1; rev:1;)";
+ FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
+ FAIL_IF_NOT(PacketTestAction(p, ACTION_REJECT_ANY));
+
+ UTHFreePackets(&p, 1);
+#endif /* HAVE_LIBNET11 */
+ PASS;
+}
+
+/**
+ * \brief Tests that the packet has the drop action correctly updated in Packet->action
+ */
+static int TestDetectAlertPacketApplySignatureActions02(void)
+{
+ uint8_t payload[] = "Hi all!";
+ uint16_t length = sizeof(payload) - 1;
+ Packet *p = UTHBuildPacketReal(
+ (uint8_t *)payload, length, IPPROTO_TCP, "192.168.1.5", "192.168.1.1", 41424, 80);
+ FAIL_IF_NULL(p);
+
+ const char sig[] = "drop tcp any any -> any any (msg:\"sig 1\"; content:\"Hi all\"; sid:1;)";
+ FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
+ FAIL_IF_NOT(PacketTestAction(p, ACTION_DROP));
+
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ * \brief Registers Detect Engine Alert unit tests
+ */
+void DetectEngineAlertRegisterTests(void)
+{
+ UtRegisterTest("TestDetectAlertPacketApplySignatureActions01",
+ TestDetectAlertPacketApplySignatureActions01);
+ UtRegisterTest("TestDetectAlertPacketApplySignatureActions02",
+ TestDetectAlertPacketApplySignatureActions02);
+}
diff --git a/src/tests/detect-engine-content-inspection.c b/src/tests/detect-engine-content-inspection.c
new file mode 100644
index 0000000..8539d46
--- /dev/null
+++ b/src/tests/detect-engine-content-inspection.c
@@ -0,0 +1,321 @@
+/* Copyright (C) 2007-2017 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 Victor Julien <victor@inliniac.net>
+ *
+ * Tests for the content inspection engine.
+ */
+
+#include "../suricata-common.h"
+#include "../decode.h"
+#include "../flow.h"
+#include "../detect.h"
+#include "detect-engine-build.h"
+
+#define TEST_HEADER \
+ ThreadVars tv; \
+ memset(&tv, 0, sizeof(tv)); \
+ Flow f; \
+ memset(&f, 0, sizeof(f));
+
+#define TEST_RUN(buf, buflen, sig, match, steps) \
+{ \
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
+ FAIL_IF_NULL(de_ctx); \
+ DetectEngineThreadCtx *det_ctx = NULL; \
+ char rule[2048]; \
+ snprintf(rule, sizeof(rule), "alert tcp any any -> any any (%s sid:1; rev:1;)", (sig)); \
+ Signature *s = DetectEngineAppendSig(de_ctx, rule); \
+ FAIL_IF_NULL(s); \
+ SigGroupBuild(de_ctx); \
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); \
+ FAIL_IF_NULL(det_ctx); \
+ int r = DetectEngineContentInspection(de_ctx, det_ctx, \
+ s, s->sm_arrays[DETECT_SM_LIST_PMATCH], NULL, &f, \
+ (uint8_t *)(buf), (buflen), 0, DETECT_CI_FLAGS_SINGLE, \
+ DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD); \
+ FAIL_IF_NOT(r == (match)); \
+ FAIL_IF_NOT(det_ctx->inspection_recursion_counter == (steps)); \
+ DetectEngineThreadCtxDeinit(&tv, det_ctx); \
+ DetectEngineCtxFree(de_ctx); \
+}
+#define TEST_FOOTER \
+ PASS
+
+/** \test simple match with distance */
+static int DetectEngineContentInspectionTest01(void) {
+ TEST_HEADER;
+ TEST_RUN("ab", 2, "content:\"a\"; content:\"b\";", true, 2);
+ TEST_RUN("ab", 2, "content:\"a\"; content:\"b\"; distance:0; ", true, 2);
+ TEST_RUN("ba", 2, "content:\"a\"; content:\"b\"; distance:0; ", false, 2);
+ TEST_FOOTER;
+}
+
+/** \test simple match with pcre/R */
+static int DetectEngineContentInspectionTest02(void) {
+ TEST_HEADER;
+ TEST_RUN("ab", 2, "content:\"a\"; pcre:\"/b/\";", true, 2);
+ TEST_RUN("ab", 2, "content:\"a\"; pcre:\"/b/R\";", true, 2);
+ TEST_RUN("ba", 2, "content:\"a\"; pcre:\"/b/R\";", false, 2);
+ TEST_FOOTER;
+}
+
+/** \test simple recursion logic */
+static int DetectEngineContentInspectionTest03(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
+
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0;", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; content:\"d\"; distance:0;", false, 3);
+
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"d\"; distance:0; within:1;", false, 5);
+
+ // 5 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1;", true, 5);
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) bab
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; content:\"bab\";", true, 6);
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) no not found
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; content:\"no\";", false, 6);
+
+ // 5 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\";", true, 5);
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) bab
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\"; content:\"bab\";", true, 6);
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, (6) no not found
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; pcre:\"/^c$/R\"; content:\"no\";", false, 6);
+
+ TEST_FOOTER;
+}
+
+/** \test pcre recursion logic */
+static int DetectEngineContentInspectionTest04(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
+
+ // simple chain of pcre
+ TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/c/R\"; ", true, 3);
+ TEST_RUN("ababc", 5, "pcre:\"/a/\"; pcre:\"/^b/R\"; pcre:\"/^c/R\"; ", true, 5);
+ TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/d/R\"; ", false, 3);
+ TEST_RUN("ababc", 5, "pcre:\"/^a/\"; pcre:\"/^b/R\"; pcre:\"/c/R\"; pcre:\"/d/\"; ", false, 4);
+
+ TEST_FOOTER;
+}
+
+/** \test multiple independent blocks recursion logic */
+static int DetectEngineContentInspectionTest05(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
+
+ // first block 2: (1) a, (2) b
+ // second block 3: (1) b, (2) c not found, (x) b continues within loop, (3) c found
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"b\"; content:\"c\"; distance:0; within:1;", true, 5);
+
+ TEST_FOOTER;
+}
+
+/** \test isdataat recursion logic */
+static int DetectEngineContentInspectionTest06(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"c\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:\"d\";", false, 3);
+
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, isdataat
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:!1,relative;", true, 5);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:1,relative;", false, 6);
+
+ TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:!1,relative;", true, 7);
+ TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; isdataat:1,relative;", true, 6);
+
+ TEST_RUN("abcXYZ", 6, "content:\"abc\"; content:\"XYZ\"; distance:0; within:3; isdataat:!1,relative;", true, 2);
+ TEST_RUN("abcXYZ", 6, "content:\"XYZ\"; distance:3; within:3; isdataat:!1,relative;", true, 1);
+ TEST_RUN("abcXYZ", 6, "content:\"cXY\"; distance:2; within:3; isdataat:!1,relative;", false, 1);
+
+ TEST_RUN("xxxxxxxxxxxxxxxxxyYYYYYYYYYYYYYYYY", 34, "content:\"yYYYYYYYYYYYYYYYY\"; distance:9; within:29; isdataat:!1,relative;", true, 1);
+ TEST_FOOTER;
+}
+
+/** \test extreme recursion */
+static int DetectEngineContentInspectionTest07(void) {
+ TEST_HEADER;
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\";", true, 4);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\"; within:1; distance:0; ", true, 31);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; content:\"d\"; within:1; distance:0; ", false, 31);
+
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; ", false, 4);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; pcre:\"/^d/R\"; ", false, 13);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; isdataat:!1,relative; ", false, 3);
+ TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
+ "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; content:\"e\"; distance:0; ", false, 5);
+ TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
+ "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; pcre:\"/^e/R\"; ", false, 14); // TODO should be 5?
+ TEST_RUN("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdx", 41,
+ "content:\"a\"; content:\"b\"; distance:0; content:\"c\"; distance:0; content:\"d\"; distance:0; isdataat:!1,relative; ", false, 4);
+
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/\";", true, 4);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/R\";", true, 4);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcd", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/^d/R\";", true, 31);
+
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/\";", false, 4);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/d/R\";", false, 31);
+ TEST_RUN("abcabcabcabcabcabcabcabcabcabcx", 31, "content:\"a\"; content:\"b\"; within:1; distance:0; content:\"c\"; distance:0; within:1; pcre:\"/^d/R\";", false, 31);
+ TEST_FOOTER;
+}
+
+/** \test mix in negation */
+static int DetectEngineContentInspectionTest08(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"d\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"c\";", false, 3);
+
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:!\"a\"; distance:0; within:1;", true, 5);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:!\"a\"; distance:0; ", true, 5);
+
+ TEST_RUN("abcdefghy", 9, "content:\"a\"; content:!\"x\"; content:\"c\"; distance:0; within:2; ",
+ true, 3);
+ TEST_RUN("abcdefghx", 9, "content:\"a\"; content:!\"x\"; content:\"c\"; distance:0; within:2; ",
+ false, 2);
+ TEST_RUN("abcdefghy", 9,
+ "content:\"a\"; content:!\"x\"; content:!\"c\"; distance:2; within:1; ", true, 3);
+
+ TEST_FOOTER;
+}
+
+/** \test mix in byte_jump */
+static int DetectEngineContentInspectionTest09(void) {
+ TEST_HEADER;
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"d\";", true, 3);
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; content:!\"c\";", false, 3);
+
+ TEST_RUN("abc03abcxyz", 11, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3;", true, 3);
+ TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3;", true, 5);
+ TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; isdataat:!1,relative;", true, 5);
+ TEST_RUN("abc03abc03abcxyz", 16, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/klm$/R\";", false, 7);
+ TEST_RUN("abc03abc03abcxyzklm", 19, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/klm$/R\";", true, 6);
+ TEST_RUN("abc03abc03abcxyzklx", 19, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/^klm$/R\";", false, 7);
+ TEST_RUN("abc03abc03abc03abcxyzklm", 24, "content:\"abc\"; byte_jump:2,0,relative,string,dec; content:\"xyz\"; within:3; pcre:\"/^klm$/R\";", true, 8);
+
+ TEST_FOOTER;
+}
+
+/** \test mix in byte_extract */
+static int DetectEngineContentInspectionTest10(void) {
+ TEST_HEADER;
+ /* extract first byte as length field and check with isdataat */
+ TEST_RUN("9abcdefghi", 10, "byte_extract:1,0,data_size,string; isdataat:data_size;", true, 2);
+ TEST_RUN("9abcdefgh", 9, "byte_extract:1,0,data_size,string; isdataat:!data_size;", true, 2);
+ /* anchor len field to pattern 'x' to test recursion */
+ TEST_RUN("x9x9abcdefghi", 13, "content:\"x\"; byte_extract:1,0,data_size,string,relative; isdataat:data_size,relative;", true, 3);
+ TEST_RUN("x9x9abcdefgh", 12, "content:\"x\"; byte_extract:1,0,data_size,string,relative; isdataat:!data_size,relative;", true, 5);
+ TEST_RUN("x9x9abcdefgh", 12, "content:\"x\"; depth:1; byte_extract:1,0,data_size,string,relative; isdataat:!data_size,relative;", false, 3);
+ /* check for super high extracted values */
+ TEST_RUN("100000000abcdefghi", 18, "byte_extract:0,0,data_size,string; isdataat:data_size;", false, 2);
+ TEST_RUN("100000000abcdefghi", 18, "byte_extract:0,0,data_size,string; isdataat:!data_size;", true, 2);
+ TEST_FOOTER;
+}
+
+static int DetectEngineContentInspectionTest11(void) {
+ TEST_HEADER;
+ TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\";", true, 2);
+ TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; within:1; distance:0;", true, 2);
+ TEST_RUN("ab", 2, "content:\"ab\"; startswith;", true, 1);
+ TEST_RUN("ab", 2, "content:\"a\"; startswith;", true, 1);
+ TEST_RUN("ab", 2, "content:\"b\"; startswith;", false, 1);
+ TEST_FOOTER;
+}
+
+/** \test endswith (isdataat) recursion logic
+ * based on DetectEngineContentInspectionTest06 */
+static int DetectEngineContentInspectionTest12(void) {
+ TEST_HEADER;
+ // 6 steps: (1) a, (2) 1st b, (3) c not found, (4) 2nd b, (5) c found, endswith
+ TEST_RUN("ababc", 5, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 5);
+
+ TEST_RUN("ababcabc", 8, "content:\"a\"; content:\"b\"; distance:0; within:1; content:\"c\"; distance:0; within:1; endswith;", true, 7);
+
+ TEST_RUN("abcXYZ", 6, "content:\"abc\"; content:\"XYZ\"; distance:0; within:3; endswith;", true, 2);
+ TEST_RUN("abcXYZ", 6, "content:\"XYZ\"; distance:3; within:3; endswith;", true, 1);
+ TEST_RUN("abcXYZ", 6, "content:\"cXY\"; distance:2; within:3; endswith;", false, 1);
+ TEST_RUN("abcXYZ", 6, "content:!\"cXY\"; endswith;", true, 1);
+ TEST_RUN("abcXYZ", 6, "content:!\"XYZ\"; endswith;", false, 1);
+
+ TEST_RUN("xxxxxxxxxxxxxxxxxyYYYYYYYYYYYYYYYY", 34, "content:\"yYYYYYYYYYYYYYYYY\"; distance:9; within:29; endswith;", true, 1);
+ TEST_FOOTER;
+}
+
+static int DetectEngineContentInspectionTest13(void) {
+ TEST_HEADER;
+ TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; endswith;", true, 2);
+ TEST_RUN("ab", 2, "content:\"a\"; startswith; content:\"b\"; within:1; distance:0; endswith;", true, 2);
+ TEST_RUN("ab", 2, "content:\"ab\"; startswith; endswith;", true, 1);
+ TEST_RUN("ab", 2, "content:\"a\"; startswith; endswith;", false, 1);
+ TEST_RUN("ab", 2, "content:\"b\"; startswith;", false, 1);
+ TEST_RUN("ab", 2, "content:\"b\"; startswith; endswith;", false, 1);
+ TEST_FOOTER;
+}
+
+/** \brief negative distance */
+static int DetectEngineContentInspectionTest17(void)
+{
+ TEST_HEADER;
+ TEST_RUN("aaabbbcccdddee", 14,
+ "content:\"aaa\"; content:\"ee\"; within:2; distance:9; content:\"bbb\"; within:3; "
+ "distance:-11; content:\"ccc\"; within:3; distance:0;",
+ true, 4);
+ TEST_FOOTER;
+}
+
+void DetectEngineContentInspectionRegisterTests(void)
+{
+ UtRegisterTest("DetectEngineContentInspectionTest01",
+ DetectEngineContentInspectionTest01);
+ UtRegisterTest("DetectEngineContentInspectionTest02",
+ DetectEngineContentInspectionTest02);
+ UtRegisterTest("DetectEngineContentInspectionTest03",
+ DetectEngineContentInspectionTest03);
+ UtRegisterTest("DetectEngineContentInspectionTest04",
+ DetectEngineContentInspectionTest04);
+ UtRegisterTest("DetectEngineContentInspectionTest05",
+ DetectEngineContentInspectionTest05);
+ UtRegisterTest("DetectEngineContentInspectionTest06",
+ DetectEngineContentInspectionTest06);
+ UtRegisterTest("DetectEngineContentInspectionTest07",
+ DetectEngineContentInspectionTest07);
+ UtRegisterTest("DetectEngineContentInspectionTest08",
+ DetectEngineContentInspectionTest08);
+ UtRegisterTest("DetectEngineContentInspectionTest09",
+ DetectEngineContentInspectionTest09);
+ UtRegisterTest("DetectEngineContentInspectionTest10",
+ DetectEngineContentInspectionTest10);
+ UtRegisterTest("DetectEngineContentInspectionTest11 startswith",
+ DetectEngineContentInspectionTest11);
+ UtRegisterTest("DetectEngineContentInspectionTest12 endswith",
+ DetectEngineContentInspectionTest12);
+ UtRegisterTest("DetectEngineContentInspectionTest13 mix startswith/endswith",
+ DetectEngineContentInspectionTest13);
+ UtRegisterTest("DetectEngineContentInspectionTest17 negative distance",
+ DetectEngineContentInspectionTest17);
+}
+
+#undef TEST_HEADER
+#undef TEST_RUN
+#undef TEST_FOOTER
diff --git a/src/tests/detect-file-data.c b/src/tests/detect-file-data.c
new file mode 100644
index 0000000..cb01686
--- /dev/null
+++ b/src/tests/detect-file-data.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2007-2022 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 Giuseppe Longo <giuseppelng@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ */
+
+#ifdef UNITTESTS
+
+#include "../stream-tcp.h"
+#include "../detect.h"
+#include "../detect-isdataat.h"
+
+static int DetectEngineSMTPFiledataTest02(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NOT(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert smtp any any -> any any "
+ "(msg:\"file_data smtp test\"; "
+ "file_data; content:\"message\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ FAIL_IF_NOT(s->flags & SIG_FLAG_TOSERVER);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the file_data fails with flow:to_server.
+ */
+static int DetectFiledataParseTest04(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert smtp any any -> any any "
+ "(msg:\"test\"; flow:to_client,established; file_data; content:\"abc\"; sid:1;)");
+ FAIL_IF_NOT_NULL(s);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectFiledataRegisterTests(void)
+{
+ UtRegisterTest("DetectEngineSMTPFiledataTest02", DetectEngineSMTPFiledataTest02);
+ UtRegisterTest("DetectFiledataParseTest04", DetectFiledataParseTest04);
+}
+#endif
diff --git a/src/tests/detect-http-client-body.c b/src/tests/detect-http-client-body.c
new file mode 100644
index 0000000..c87d667
--- /dev/null
+++ b/src/tests/detect-http-client-body.c
@@ -0,0 +1,3010 @@
+/* Copyright (C) 2007-2021 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * \brief Handle HTTP request body match corresponding to http_client_body
+ * keyword.
+ *
+ */
+
+#include "../suricata-common.h"
+#include "../suricata.h"
+#include "../decode.h"
+
+#include "detect.h"
+#include "detect-engine.h"
+#include "detect-engine-mpm.h"
+#include "detect-parse.h"
+#include "detect-engine-state.h"
+#include "detect-engine-content-inspection.h"
+#include "detect-engine-prefilter.h"
+#include "detect-isdataat.h"
+#include "stream-tcp-reassemble.h"
+#include "detect-engine-build.h"
+
+#include "flow-util.h"
+#include "util-debug.h"
+#include "util-print.h"
+#include "flow.h"
+
+#include "app-layer-parser.h"
+
+#include "stream-tcp.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 "conf.h"
+#include "conf-yaml-loader.h"
+
+#include "util-validate.h"
+
+#ifdef UNITTESTS
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpClientBodyParserTest01(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; http_client_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; nocase; http_client_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; endswith; http_client_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; http_client_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; endswith; http_client_body; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; rawbytes; http_client_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http_client_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; content:\"abc\"; http_client_body; sid:1;)", false));
+ PASS;
+}
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpClientBodyParserTest02(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; nocase; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; startswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; startswith; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; bsize:10; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.request_body; content:\"abc\"; rawbytes; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http.request_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; http.request_body; content:\"abc\"; sid:1;)", false));
+ PASS;
+}
+
+struct TestSteps {
+ const uint8_t *input;
+ size_t input_size; /**< if 0 strlen will be used */
+ int direction; /**< STREAM_TOSERVER, STREAM_TOCLIENT */
+ int expect;
+};
+
+static int RunTest (struct TestSteps *steps, const char *sig, const char *yaml)
+{
+ TcpSession ssn;
+ Flow f;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ if (yaml) {
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(yaml, strlen(yaml));
+ HTPConfigure();
+ }
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ f.alproto = ALPROTO_HTTP1;
+
+ SCLogDebug("sig %s", sig);
+ Signature *s = DetectEngineAppendSig(de_ctx, (char *)sig);
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ struct TestSteps *b = steps;
+ int i = 0;
+ while (b->input != NULL) {
+ SCLogDebug("chunk %p %d", b, i);
+ Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+ p->flow = &f;
+ p->flowflags = (b->direction == STREAM_TOSERVER) ? FLOW_PKT_TOSERVER : FLOW_PKT_TOCLIENT;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, b->direction,
+ (uint8_t *)b->input,
+ b->input_size ? b->input_size : strlen((const char *)b->input));
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ int match = PacketAlertCheck(p, 1);
+ FAIL_IF_NOT (b->expect == match);
+
+ UTHFreePackets(&p, 1);
+ b++;
+ i++;
+ }
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+
+ if (yaml) {
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+ }
+ PASS;
+}
+
+static int DetectEngineHttpClientBodyTest01(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1This\"; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest02(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; offset:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest03(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; offset:16; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest04(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; offset:16; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest05(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; depth:25; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest06(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; depth:25; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest07(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:!\"body1\"; http_client_body; depth:15; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest08(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"This is dummy body1This is dummy message body2\"; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest09(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"This\"; http_client_body; within:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest10(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"boom\"; http_client_body; within:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest11(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"boom\"; http_client_body; within:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest12(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"This\"; http_client_body; within:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest13(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"dummy\"; http_client_body; distance:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest14(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"dummy\"; http_client_body; distance:10; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest15(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"dummy\"; http_client_body; distance:10; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest16(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:!\"dummy\"; http_client_body; distance:5; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest17(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"bambu\"; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest18(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"body1\"; http_client_body; content:\"bambu\"; http_client_body; fast_pattern; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest19(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"bambu\"; http_client_body; content:\"is\"; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest20(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"is\"; http_client_body; fast_pattern; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest21(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; http_client_body; within:7; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest22(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; within:7; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest23(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; distance:3; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest24(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:!\"dummy\"; distance:13; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest25(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; within:15; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest26(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; within:10; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest27(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; distance:8; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest28(void)
+{
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (pcre:/body1/P; content:\"dummy\"; distance:14; http_client_body; sid:1;)";
+ return RunTest(steps, sig, NULL);
+}
+
+static int DetectEngineHttpClientBodyTest29(void)
+{
+ const char *request_buffer = "GET /one HTTP/1.0\r\n"
+ "Host: localhost\r\n\r\n";
+#define TOTAL_REQUESTS 45
+ uint8_t *http_buf = SCMalloc(TOTAL_REQUESTS * strlen(request_buffer));
+ if (unlikely(http_buf == NULL))
+ return 0;
+ for (int i = 0; i < TOTAL_REQUESTS; i++) {
+ memcpy(http_buf + i * strlen(request_buffer), request_buffer,
+ strlen(request_buffer));
+ }
+ uint32_t http_buf_len = TOTAL_REQUESTS * strlen(request_buffer);
+#undef TOTAL_REQUESTS
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)http_buf,
+ (size_t)http_buf_len, STREAM_TOSERVER, 0 },
+
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 5\r\n"
+ "\r\n"
+ "dummy",
+ 0, STREAM_TOCLIENT, 0 },
+
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"dummyone\"; fast_pattern:0,3; http_server_body; sid:1;)";
+ int result = RunTest(steps, sig, NULL);
+ SCFree(http_buf);
+ return result;
+}
+
+static int DetectEngineHttpClientBodyTest30(void)
+{
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+ personality: IDS\n\
+ request-body-limit: 0\n\
+ response-body-limit: 0\n\
+\n\
+ request-body-inspect-window: 0\n\
+ response-body-inspect-window: 0\n\
+ request-body-minimal-inspect-size: 0\n\
+ response-body-minimal-inspect-size: 0\n\
+";
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"bags\"; within:4; http_client_body; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpClientBodyTest31(void)
+{
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+ personality: IDS\n\
+ request-body-limit: 0\n\
+ response-body-limit: 0\n\
+\n\
+ request-body-inspect-window: 0\n\
+ response-body-inspect-window: 0\n\
+ request-body-minimal-inspect-size: 0\n\
+ response-body-minimal-inspect-size: 0\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"This is dummy message body2",
+ 0, STREAM_TOSERVER, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (content:\"bags\"; depth:4; http_client_body; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+/**
+ * \test Test that a signature containing a http_client_body is correctly parsed
+ * and the keyword is registered.
+ */
+static int DetectHttpClientBodyTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"Testing http_client_body\"; "
+ "content:\"one\"; http_client_body; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigMatch *sm = de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test that a signature containing an valid http_client_body entry is
+ * parsed.
+ * \todo error in sig 'http_client_body:;'
+ */
+static int DetectHttpClientBodyTest02(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"Testing http_client_body\"; "
+ "content:\"one\"; http_client_body:; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test invalid signatures
+ */
+static int DetectHttpClientBodyTest03(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ const char *sigs[] = {
+ "alert tcp any any -> any any (http_client_body; sid:1;)",
+ "alert tcp any any -> any any "
+ "(msg:\"Testing http_client_body\"; "
+ "content:\"one\"; rawbytes; http_client_body; sid:2;)",
+ NULL,
+ };
+
+ for (uint32_t i = 0; sigs[i] != NULL; i++) {
+ Signature *s = DetectEngineAppendSig(de_ctx, sigs[i]);
+ FAIL_IF_NOT_NULL(s);
+ }
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test that an invalid signature containing a rawbytes along with a
+ * http_client_body is invalidated.
+ */
+static int DetectHttpClientBodyTest05(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ const char *sigs[] = {
+ "alert tcp any any -> any any (content:\"one\"; http_client_body; nocase; sid:1;)",
+ NULL,
+ };
+
+ for (uint32_t i = 0; sigs[i] != NULL; i++) {
+ Signature *s = DetectEngineAppendSig(de_ctx, sigs[i]);
+ FAIL_IF_NULL(s);
+ }
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpClientBodyTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"message\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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\n");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpClientBodyTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 54\r\n"
+ "\r\n"
+ "This is dummy message body1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"message\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched on p1 but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match on p2 but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpClientBodyTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"message\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpClientBodyTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"body1This\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpClientBodyTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy bodY1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"body1This\"; http_client_body; nocase;"
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the negated http_client_body content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpClientBodyTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:!\"message1\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Negative test that the negated http_client_body content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpClientBodyTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:!\"message\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_client_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpClientBodyTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 55\r\n"
+ "\r\n"
+ "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_client_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test multiple http transactions and body chunks of request handling */
+static int DetectHttpClientBodyTest14(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
+ uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
+ uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
+ uint8_t httpbuf4[] = "Body one!!";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
+ uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
+ uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
+ uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
+ uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
+ uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"one\"; http_client_body; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; content:\"two\"; http_client_body; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("signature matched, but shouldn't have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
+ if (r != 0) {
+ printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (5): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
+ if (r != 0) {
+ printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
+ printf("sig 1 alerted (request 2, chunk 6): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ SCLogDebug("sending data chunk 7");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
+ if (r != 0) {
+ printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("signature 2 didn't match, but should have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+/** \test multiple http transactions and body chunks of request handling */
+static int DetectHttpClientBodyTest15(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
+ uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
+ uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
+ uint8_t httpbuf4[] = "Body one!!";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
+ uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
+ uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
+ uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
+ uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
+ uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"one\"; http_client_body; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; content:\"two\"; http_client_body; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("signature matched, but shouldn't have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
+ if (r != 0) {
+ printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (5): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
+ if (r != 0) {
+ printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
+ printf("sig 1 alerted (request 2, chunk 6): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ SCLogDebug("sending data chunk 7");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
+ if (r != 0) {
+ printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("signature 2 didn't match, but should have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ /* hardcoded check of the transactions and it's client body chunks */
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ goto end;
+ }
+
+ htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 0);
+ htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 1);
+
+ HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
+
+ HtpBodyChunk *cur = htud->request_body.first;
+ if (htud->request_body.first == NULL) {
+ SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
+ goto end;
+ }
+
+ if (StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg,
+ (uint8_t *)"Body one!!", 10) != 1)
+ {
+ SCLogDebug("Body data in t1 is not correctly set: ");
+ goto end;
+ }
+
+ htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
+
+ cur = htud->request_body.first;
+ if (htud->request_body.first == NULL) {
+ SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
+ goto end;
+ }
+
+ if (StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg,
+ (uint8_t *)"Body two!!", 10) != 1)
+ {
+ SCLogDebug("Body data in t1 is not correctly set: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+static int DetectHttpClientBodyTest22(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"one\"; content:\"two\"; http_client_body; "
+ "content:\"three\"; distance:10; http_client_body; content:\"four\"; sid:1;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
+ FAIL_IF(DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL);
+ SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ DetectContentData *cd1 =
+ (DetectContentData *)s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ FAIL_IF(cd1->flags != 0);
+ FAIL_IF(memcmp(cd1->content, "one", cd1->content_len) != 0);
+ FAIL_IF(cd2->flags != 0);
+ FAIL_IF(memcmp(cd2->content, "four", cd2->content_len) != 0);
+ FAIL_IF(hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT);
+ FAIL_IF(memcmp(hcbd1->content, "two", hcbd1->content_len) != 0);
+ FAIL_IF(hcbd2->flags != DETECT_CONTENT_DISTANCE);
+ FAIL_IF(memcmp(hcbd2->content, "three", hcbd1->content_len) != 0);
+
+ FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd1));
+ FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd2));
+ FAIL_IF(DETECT_CONTENT_IS_SINGLE(hcbd1));
+ FAIL_IF(DETECT_CONTENT_IS_SINGLE(hcbd2));
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+static int DetectHttpClientBodyTest23(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; pcre:/two/; "
+ "content:\"three\"; distance:10; http_client_body; content:\"four\"; sid:1;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
+ FAIL_IF_NULL(DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id));
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ FAIL_IF(pd1->flags != 0);
+ FAIL_IF(cd2->flags != 0);
+ FAIL_IF(memcmp(cd2->content, "four", cd2->content_len) != 0);
+ FAIL_IF(hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT);
+ FAIL_IF(memcmp(hcbd1->content, "one", hcbd1->content_len) != 0);
+ FAIL_IF(hcbd2->flags != DETECT_CONTENT_DISTANCE);
+ FAIL_IF(memcmp(hcbd2->content, "three", hcbd1->content_len) != 0);
+ FAIL_IF(!DETECT_CONTENT_IS_SINGLE(cd2));
+ FAIL_IF(DETECT_CONTENT_IS_SINGLE(hcbd1));
+ FAIL_IF(DETECT_CONTENT_IS_SINGLE(hcbd2));
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+static int DetectHttpClientBodyTest24(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; pcre:/two/; "
+ "content:\"three\"; distance:10; within:15; "
+ "http_client_body; content:\"four\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != 0 ||
+ cd2->flags != 0 || memcmp(cd2->content, "four", cd2->content_len) != 0 ||
+ hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
+ memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ if (!DETECT_CONTENT_IS_SINGLE(cd2) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd1) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd2)) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest25(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; pcre:/two/; "
+ "content:\"three\"; distance:10; http_client_body; "
+ "content:\"four\"; distance:10; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != DETECT_PCRE_RELATIVE_NEXT ||
+ cd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(cd2->content, "four", cd2->content_len) != 0 ||
+ hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ if (DETECT_CONTENT_IS_SINGLE(cd2) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd1) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd2)) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest26(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"one\"; offset:10; http_client_body; pcre:/two/; "
+ "content:\"three\"; distance:10; http_client_body; within:10; "
+ "content:\"four\"; distance:10; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
+ cd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(cd2->content, "four", cd2->content_len) != 0 ||
+ hcbd1->flags != (DETECT_CONTENT_RELATIVE_NEXT | DETECT_CONTENT_OFFSET) ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
+ memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
+ printf ("failed: http_client_body incorrect flags");
+ goto end;
+ }
+
+ if (DETECT_CONTENT_IS_SINGLE(cd2) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd1) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd2)) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest27(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"one\"; offset:10; http_client_body; pcre:/two/; "
+ "content:\"three\"; distance:10; http_client_body; within:10; "
+ "content:\"four\"; distance:10; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest28(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; pcre:/two/; "
+ "content:\"three\"; http_client_body; depth:10; "
+ "content:\"four\"; distance:10; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->prev->ctx;
+ DetectContentData *cd2 =
+ (DetectContentData *)de_ctx->sig_list->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]
+ ->ctx;
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
+ cd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(cd2->content, "four", cd2->content_len) != 0 ||
+ hcbd1->flags != 0 ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != DETECT_CONTENT_DEPTH ||
+ memcmp(hcbd2->content, "three", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ if (DETECT_CONTENT_IS_SINGLE(cd2) ||
+ !DETECT_CONTENT_IS_SINGLE(hcbd1) ||
+ DETECT_CONTENT_IS_SINGLE(hcbd2)) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest29(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; "
+ "content:\"two\"; distance:0; http_client_body; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(hcbd2->content, "two", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest30(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; "
+ "content:\"two\"; within:5; http_client_body; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
+ memcmp(hcbd1->content, "one", hcbd1->content_len) != 0 ||
+ hcbd2->flags != DETECT_CONTENT_WITHIN ||
+ memcmp(hcbd2->content, "two", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest31(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; within:5; http_client_body; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest32(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; http_client_body; within:5; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest33(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"one\"; within:5; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest34(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(pcre:/one/P; "
+ "content:\"two\"; within:5; http_client_body; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id) == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->type != DETECT_CONTENT ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev->type !=
+ DETECT_PCRE) {
+
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
+ hcbd2->flags != DETECT_CONTENT_WITHIN ||
+ memcmp(hcbd2->content, "two", hcbd2->content_len) != 0) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest35(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(content:\"two\"; http_client_body; "
+ "pcre:/one/PR; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id) == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->type != DETECT_PCRE ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev->type !=
+ DETECT_CONTENT) {
+
+ goto end;
+ }
+
+ DetectContentData *hcbd1 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectPcreData *pd2 =
+ (DetectPcreData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd2->flags != (DETECT_PCRE_RELATIVE) ||
+ hcbd1->flags != DETECT_CONTENT_RELATIVE_NEXT ||
+ memcmp(hcbd1->content, "two", hcbd1->content_len) != 0) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyTest36(void)
+{
+ DetectEngineCtx *de_ctx = NULL;
+ int result = 0;
+
+ if ( (de_ctx = DetectEngineCtxInit()) == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ Signature *s =
+ DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
+ "(pcre:/one/P; "
+ "content:\"two\"; distance:5; http_client_body; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("de_ctx->sig_list == NULL\n");
+ goto end;
+ }
+
+ if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
+ printf("de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL) {
+ printf("DetectBufferGetFirstSigMatch(s, g_http_client_body_buffer_id) == NULL\n");
+ goto end;
+ }
+
+ if (DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id) == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->type != DETECT_CONTENT ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev == NULL ||
+ DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->prev->type !=
+ DETECT_PCRE) {
+
+ goto end;
+ }
+
+ DetectPcreData *pd1 =
+ (DetectPcreData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)
+ ->prev->ctx;
+ DetectContentData *hcbd2 =
+ (DetectContentData *)DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id)->ctx;
+ if (pd1->flags != (DETECT_PCRE_RELATIVE_NEXT) ||
+ hcbd2->flags != DETECT_CONTENT_DISTANCE ||
+ memcmp(hcbd2->content, "two", hcbd2->content_len) != 0) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+static int DetectHttpClientBodyIsdataatParseTest(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any ("
+ "content:\"one\"; http_client_body; "
+ "isdataat:!4,relative; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigMatch *sm = DetectBufferGetLastSigMatch(s, g_http_client_body_buffer_id);
+ FAIL_IF_NULL(sm);
+ FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
+
+ DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
+ FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
+ FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
+ FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHttpClientBodyRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpClientBodyParserTest01", DetectHttpClientBodyParserTest01);
+ UtRegisterTest("DetectHttpClientBodyParserTest02", DetectHttpClientBodyParserTest02);
+ UtRegisterTest("DetectHttpClientBodyTest01", DetectHttpClientBodyTest01);
+ UtRegisterTest("DetectHttpClientBodyTest02", DetectHttpClientBodyTest02);
+ UtRegisterTest("DetectHttpClientBodyTest03", DetectHttpClientBodyTest03);
+ UtRegisterTest("DetectHttpClientBodyTest05", DetectHttpClientBodyTest05);
+ UtRegisterTest("DetectHttpClientBodyTest06", DetectHttpClientBodyTest06);
+ UtRegisterTest("DetectHttpClientBodyTest07", DetectHttpClientBodyTest07);
+ UtRegisterTest("DetectHttpClientBodyTest08", DetectHttpClientBodyTest08);
+ UtRegisterTest("DetectHttpClientBodyTest09", DetectHttpClientBodyTest09);
+ UtRegisterTest("DetectHttpClientBodyTest10", DetectHttpClientBodyTest10);
+ UtRegisterTest("DetectHttpClientBodyTest11", DetectHttpClientBodyTest11);
+ UtRegisterTest("DetectHttpClientBodyTest12", DetectHttpClientBodyTest12);
+ UtRegisterTest("DetectHttpClientBodyTest13", DetectHttpClientBodyTest13);
+ UtRegisterTest("DetectHttpClientBodyTest14", DetectHttpClientBodyTest14);
+ UtRegisterTest("DetectHttpClientBodyTest15", DetectHttpClientBodyTest15);
+
+ UtRegisterTest("DetectHttpClientBodyTest22", DetectHttpClientBodyTest22);
+ UtRegisterTest("DetectHttpClientBodyTest23", DetectHttpClientBodyTest23);
+ UtRegisterTest("DetectHttpClientBodyTest24", DetectHttpClientBodyTest24);
+ UtRegisterTest("DetectHttpClientBodyTest25", DetectHttpClientBodyTest25);
+ UtRegisterTest("DetectHttpClientBodyTest26", DetectHttpClientBodyTest26);
+ UtRegisterTest("DetectHttpClientBodyTest27", DetectHttpClientBodyTest27);
+ UtRegisterTest("DetectHttpClientBodyTest28", DetectHttpClientBodyTest28);
+ UtRegisterTest("DetectHttpClientBodyTest29", DetectHttpClientBodyTest29);
+ UtRegisterTest("DetectHttpClientBodyTest30", DetectHttpClientBodyTest30);
+ UtRegisterTest("DetectHttpClientBodyTest31", DetectHttpClientBodyTest31);
+ UtRegisterTest("DetectHttpClientBodyTest32", DetectHttpClientBodyTest32);
+ UtRegisterTest("DetectHttpClientBodyTest33", DetectHttpClientBodyTest33);
+ UtRegisterTest("DetectHttpClientBodyTest34", DetectHttpClientBodyTest34);
+ UtRegisterTest("DetectHttpClientBodyTest35", DetectHttpClientBodyTest35);
+ UtRegisterTest("DetectHttpClientBodyTest36", DetectHttpClientBodyTest36);
+
+ UtRegisterTest("DetectHttpClientBodyIsdataatParseTest",
+ DetectHttpClientBodyIsdataatParseTest);
+
+ UtRegisterTest("DetectEngineHttpClientBodyTest01",
+ DetectEngineHttpClientBodyTest01);
+ UtRegisterTest("DetectEngineHttpClientBodyTest02",
+ DetectEngineHttpClientBodyTest02);
+ UtRegisterTest("DetectEngineHttpClientBodyTest03",
+ DetectEngineHttpClientBodyTest03);
+ UtRegisterTest("DetectEngineHttpClientBodyTest04",
+ DetectEngineHttpClientBodyTest04);
+ UtRegisterTest("DetectEngineHttpClientBodyTest05",
+ DetectEngineHttpClientBodyTest05);
+ UtRegisterTest("DetectEngineHttpClientBodyTest06",
+ DetectEngineHttpClientBodyTest06);
+ UtRegisterTest("DetectEngineHttpClientBodyTest07",
+ DetectEngineHttpClientBodyTest07);
+ UtRegisterTest("DetectEngineHttpClientBodyTest08",
+ DetectEngineHttpClientBodyTest08);
+ UtRegisterTest("DetectEngineHttpClientBodyTest09",
+ DetectEngineHttpClientBodyTest09);
+ UtRegisterTest("DetectEngineHttpClientBodyTest10",
+ DetectEngineHttpClientBodyTest10);
+ UtRegisterTest("DetectEngineHttpClientBodyTest11",
+ DetectEngineHttpClientBodyTest11);
+ UtRegisterTest("DetectEngineHttpClientBodyTest12",
+ DetectEngineHttpClientBodyTest12);
+ UtRegisterTest("DetectEngineHttpClientBodyTest13",
+ DetectEngineHttpClientBodyTest13);
+ UtRegisterTest("DetectEngineHttpClientBodyTest14",
+ DetectEngineHttpClientBodyTest14);
+ UtRegisterTest("DetectEngineHttpClientBodyTest15",
+ DetectEngineHttpClientBodyTest15);
+ UtRegisterTest("DetectEngineHttpClientBodyTest16",
+ DetectEngineHttpClientBodyTest16);
+ UtRegisterTest("DetectEngineHttpClientBodyTest17",
+ DetectEngineHttpClientBodyTest17);
+ UtRegisterTest("DetectEngineHttpClientBodyTest18",
+ DetectEngineHttpClientBodyTest18);
+ UtRegisterTest("DetectEngineHttpClientBodyTest19",
+ DetectEngineHttpClientBodyTest19);
+ UtRegisterTest("DetectEngineHttpClientBodyTest20",
+ DetectEngineHttpClientBodyTest20);
+ UtRegisterTest("DetectEngineHttpClientBodyTest21",
+ DetectEngineHttpClientBodyTest21);
+ UtRegisterTest("DetectEngineHttpClientBodyTest22",
+ DetectEngineHttpClientBodyTest22);
+ UtRegisterTest("DetectEngineHttpClientBodyTest23",
+ DetectEngineHttpClientBodyTest23);
+ UtRegisterTest("DetectEngineHttpClientBodyTest24",
+ DetectEngineHttpClientBodyTest24);
+ UtRegisterTest("DetectEngineHttpClientBodyTest25",
+ DetectEngineHttpClientBodyTest25);
+ UtRegisterTest("DetectEngineHttpClientBodyTest26",
+ DetectEngineHttpClientBodyTest26);
+ UtRegisterTest("DetectEngineHttpClientBodyTest27",
+ DetectEngineHttpClientBodyTest27);
+ UtRegisterTest("DetectEngineHttpClientBodyTest28",
+ DetectEngineHttpClientBodyTest28);
+ UtRegisterTest("DetectEngineHttpClientBodyTest29",
+ DetectEngineHttpClientBodyTest29);
+
+ UtRegisterTest("DetectEngineHttpClientBodyTest30",
+ DetectEngineHttpClientBodyTest30);
+ UtRegisterTest("DetectEngineHttpClientBodyTest31",
+ DetectEngineHttpClientBodyTest31);
+}
+
+#endif
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-cookie.c b/src/tests/detect-http-cookie.c
new file mode 100644
index 0000000..466722e
--- /dev/null
+++ b/src/tests/detect-http-cookie.c
@@ -0,0 +1,2623 @@
+/* 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * \brief Handle HTTP cookie match
+ *
+ */
+
+#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"
+#include "../detect-isdataat.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+/***********************************Unittests**********************************/
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CONNECT\"; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; depth:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"ECT\"; depth:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"ECT\"; depth:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"CON\"; depth:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"ECT\"; offset:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"CO\"; offset:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"ECT\"; offset:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CON\"; offset:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:\"EC\"; within:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:!\"EC\"; within:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:\"EC\"; within:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:!\"EC\"; within:4; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:\"EC\"; distance:2; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:!\"EC\"; distance:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:\"EC\"; distance:3; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_cookie content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpCookieTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Cookie: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_cookie; "
+ "content:!\"EC\"; distance:2; http_cookie; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Checks if a http_cookie is registered in a Signature, if content is not
+ * specified in the signature
+ */
+static int DetectHttpCookieTest01(void)
+{
+ 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_cookie\"; http_cookie;sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ result = 1;
+
+end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/**
+ * \test Checks if a http_cookie is registered in a Signature, if some parameter
+ * is specified with http_cookie in the signature
+ */
+static int DetectHttpCookieTest02(void)
+{
+ 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_cookie\"; content:\"me\"; "
+ "http_cookie:woo; sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ result = 1;
+
+end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check the signature working to alert when http_cookie is matched . */
+static int DetectHttpCookieSigTest01(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\nCookie:"
+ " hellocatchme\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:\"me\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+ "cookie\"; content:\"go\"; http_cookie; sid:2;)");
+ if (s->next == NULL) {
+ goto end;
+ }
+
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 matched but shouldn't: ");
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest02(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 */
+ 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(&p, 0, sizeof(p));
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:\"me\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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))) {
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest03(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
+ "Cookie: dummy\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:\"boo\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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))) {
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest04(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
+ "Cookie: dummy\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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(&p, 0, sizeof(p));
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:!\"boo\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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)) {
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest05(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
+ "Cookie: DuMmY\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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(&p, 0, sizeof(p));
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:\"dummy\"; nocase; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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)) {
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest06(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
+ "Cookie: DuMmY\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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(&p, 0, sizeof(p));
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:\"dummy\"; "
+ "http_cookie; nocase; sid:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ 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("sig 1 failed to match: ");
+ 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_cookie is not present */
+static int DetectHttpCookieSigTest07(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
+ "Cookie: dummy\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 cookie\"; content:!\"dummy\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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)) {
+ 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 against set-cookie
+ */
+static int DetectHttpCookieSigTest08(void)
+{
+ int result = 0;
+ Flow f;
+
+ uint8_t httpbuf_request[] =
+ "GET / HTTP/1.1\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "\r\n";
+ uint32_t httpbuf_request_len = sizeof(httpbuf_request) - 1; /* minus the \0 */
+
+ uint8_t httpbuf_response[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Set-Cookie: response_user_agent\r\n"
+ "\r\n";
+ uint32_t httpbuf_response_len = sizeof(httpbuf_response) - 1; /* minus the \0 */
+
+ TcpSession ssn;
+ Packet *p1 = NULL, *p2 = 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));
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ f.alproto = ALPROTO_HTTP1;
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+
+ 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 "
+ "(flow:to_client; content:\"response_user_agent\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ /* request */
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf_request,
+ httpbuf_request_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ goto end;
+ }
+
+ /* response */
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf_response,
+ httpbuf_response_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!PacketAlertCheck(p2, 1)) {
+ 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(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ * \test Check the signature working to alert against cookie/set-cookie
+ */
+static int DetectHttpCookieSigTest09(void)
+{
+ int result = 0;
+ Flow f;
+
+ uint8_t httpbuf_request[] =
+ "GET / HTTP/1.1\r\n"
+ "Cookie: request_user_agent\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "\r\n";
+ uint32_t httpbuf_request_len = sizeof(httpbuf_request) - 1; /* minus the \0 */
+
+ uint8_t httpbuf_response[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Set-Cookie: response_user_agent\r\n"
+ "\r\n";
+ uint32_t httpbuf_response_len = sizeof(httpbuf_response) - 1; /* minus the \0 */
+
+ TcpSession ssn;
+ Packet *p1 = NULL, *p2 = 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));
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ f.alproto = ALPROTO_HTTP1;
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+
+ 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 "
+ "(flow:to_server; content:\"request_user_agent\"; "
+ "http_cookie; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+ s = de_ctx->sig_list->next = SigInit(de_ctx,"alert http any any -> any any "
+ "(flow:to_client; content:\"response_user_agent\"; "
+ "http_cookie; sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ /* request */
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf_request,
+ httpbuf_request_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!PacketAlertCheck(p1, 1) || PacketAlertCheck(p1, 2)) {
+ goto end;
+ }
+
+ /* response */
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf_response,
+ httpbuf_response_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 1) || !PacketAlertCheck(p2, 2)) {
+ 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(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ * \brief Register the UNITTESTS for the http_cookie keyword
+ */
+void DetectHttpCookieRegisterTests (void)
+{
+ UtRegisterTest("DetectHttpCookieTest01", DetectHttpCookieTest01);
+ UtRegisterTest("DetectHttpCookieTest02", DetectHttpCookieTest02);
+ UtRegisterTest("DetectHttpCookieSigTest01", DetectHttpCookieSigTest01);
+ UtRegisterTest("DetectHttpCookieSigTest02", DetectHttpCookieSigTest02);
+ UtRegisterTest("DetectHttpCookieSigTest03", DetectHttpCookieSigTest03);
+ UtRegisterTest("DetectHttpCookieSigTest04", DetectHttpCookieSigTest04);
+ UtRegisterTest("DetectHttpCookieSigTest05", DetectHttpCookieSigTest05);
+ UtRegisterTest("DetectHttpCookieSigTest06", DetectHttpCookieSigTest06);
+ UtRegisterTest("DetectHttpCookieSigTest07", DetectHttpCookieSigTest07);
+ UtRegisterTest("DetectHttpCookieSigTest08", DetectHttpCookieSigTest08);
+ UtRegisterTest("DetectHttpCookieSigTest09", DetectHttpCookieSigTest09);
+ UtRegisterTest("DetectEngineHttpCookieTest01",
+ DetectEngineHttpCookieTest01);
+ UtRegisterTest("DetectEngineHttpCookieTest02",
+ DetectEngineHttpCookieTest02);
+ UtRegisterTest("DetectEngineHttpCookieTest03",
+ DetectEngineHttpCookieTest03);
+ UtRegisterTest("DetectEngineHttpCookieTest04",
+ DetectEngineHttpCookieTest04);
+ UtRegisterTest("DetectEngineHttpCookieTest05",
+ DetectEngineHttpCookieTest05);
+ UtRegisterTest("DetectEngineHttpCookieTest06",
+ DetectEngineHttpCookieTest06);
+ UtRegisterTest("DetectEngineHttpCookieTest07",
+ DetectEngineHttpCookieTest07);
+ UtRegisterTest("DetectEngineHttpCookieTest08",
+ DetectEngineHttpCookieTest08);
+ UtRegisterTest("DetectEngineHttpCookieTest09",
+ DetectEngineHttpCookieTest09);
+ UtRegisterTest("DetectEngineHttpCookieTest10",
+ DetectEngineHttpCookieTest10);
+ UtRegisterTest("DetectEngineHttpCookieTest11",
+ DetectEngineHttpCookieTest11);
+ UtRegisterTest("DetectEngineHttpCookieTest12",
+ DetectEngineHttpCookieTest12);
+ UtRegisterTest("DetectEngineHttpCookieTest13",
+ DetectEngineHttpCookieTest13);
+ UtRegisterTest("DetectEngineHttpCookieTest14",
+ DetectEngineHttpCookieTest14);
+ UtRegisterTest("DetectEngineHttpCookieTest15",
+ DetectEngineHttpCookieTest15);
+ UtRegisterTest("DetectEngineHttpCookieTest16",
+ DetectEngineHttpCookieTest16);
+ UtRegisterTest("DetectEngineHttpCookieTest17",
+ DetectEngineHttpCookieTest17);
+}
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-header.c b/src/tests/detect-http-header.c
new file mode 100644
index 0000000..776d891
--- /dev/null
+++ b/src/tests/detect-http-header.c
@@ -0,0 +1,4651 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ *
+ * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
+ *
+ * Implements support for http_header keyword.
+ */
+
+#include "../suricata-common.h"
+#include "../flow.h"
+#include "../flow-var.h"
+#include "../flow-util.h"
+
+#include "../app-layer.h"
+#include "../app-layer-parser.h"
+
+#include "../app-layer-htp.h"
+#include "../detect-http-header.h"
+#include "../detect-http-header-common.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+#include "../detect-isdataat.h"
+
+#include "../stream-tcp.h"
+
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpHeaderParserTest01(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; http_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; nocase; http_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; endswith; http_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; startswith; http_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; startswith; endswith; http_header; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (content:\"abc\"; rawbytes; http_header; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (http_header; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (content:\"abc\"; http_header; sid:1;)", false));
+ PASS;
+}
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpHeaderParserTest02(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; nocase; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; startswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; startswith; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; bsize:10; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (http.header; content:\"abc\"; rawbytes; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (http.header; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (http.header; content:\"abc\"; sid:1;)", false));
+ PASS;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHeaderTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Content-Type: text/html\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHeaderTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozi";
+ uint8_t http2_buf[] =
+ "lla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\nContent-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy message body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p1);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p2);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Mozilla\"; http_header; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF(r != 0);
+
+ HtpState *http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF( (PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHeaderTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n";
+ uint8_t http2_buf[] =
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Gecko/20091221 Firefox/3.5.7\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpHeaderTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
+ uint8_t http2_buf[] =
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy body\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+ de_ctx->mpm_matcher = mpm_default_matcher;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Firefox/3.5.7|0D 0A|Content\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpHeaderTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
+ uint8_t http2_buf[] =
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy body";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"firefox/3.5.7|0D 0A|content\"; nocase; http_header;"
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the negated http_header content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpHeaderTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"lalalalala\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Negative test that the negated http_header content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpHeaderTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"User-Agent: Mozilla/5.0 \"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHeaderTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 100\r\n"
+ "\r\n"
+ "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Host: www.openinfosecfoundation.org\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test app-layer-event:http.host_header_ambiguous should not be set
+ * \bug 640*/
+static int DetectHttpHeaderTest28(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "POST http://xxx.intranet.local:8000/xxx HTTP/1.1\r\n"
+ "User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_29\r\n"
+ "Host: xxx.intranet.local:8000\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(app-layer-event:http.host_header_ambiguous; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ if (PacketAlertCheck(p, 1)) {
+ printf("sid 1 matched but shouldnt have: ");
+ goto end;
+ }
+
+ result = 1;
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test app-layer-event:http.host_header_ambiguous should be set
+ * \bug 640*/
+static int DetectHttpHeaderTest29(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "POST http://xxx.intranet.local:8001/xxx HTTP/1.1\r\n"
+ "User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_29\r\n"
+ "Host: xxx.intranet.local:8000\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(app-layer-event:http.host_header_ambiguous; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ 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;
+ }
+
+ result = 1;
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test app-layer-event:http.host_header_ambiguous should be set
+ * \bug 640*/
+static int DetectHttpHeaderTest30(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "POST http://xxx.intranet.local:8000/xxx HTTP/1.1\r\n"
+ "User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_29\r\n"
+ "Host: xyz.intranet.local:8000\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(app-layer-event:http.host_header_ambiguous; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ 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;
+ }
+
+ result = 1;
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectHttpHeaderIsdataatParseTest(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any ("
+ "flow:to_server; "
+ "content:\"one\"; http_header; "
+ "isdataat:!4,relative; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigMatch *sm = DetectBufferGetLastSigMatch(s, g_http_header_buffer_id);
+ FAIL_IF_NULL(sm);
+ FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
+
+ DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
+ FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
+ FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
+ FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; depth:15; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"one\"; depth:5; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; depth:5; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"one\"; depth:15; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; offset:10; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"one\"; offset:15; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; offset:15; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"one\"; offset:10; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:\"three\"; http_header; within:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:!\"three\"; http_header; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:!\"three\"; http_header; within:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:\"three\"; http_header; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:\"five\"; http_header; distance:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:!\"five\"; http_header; distance:15; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:!\"five\"; http_header; distance:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHeaderTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"one\"; http_header; content:\"five\"; http_header; distance:15; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest20(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:!\"dummy\"; http_header; within:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest21(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:!\"dummy\"; within:7; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest22(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:!\"dummy\"; distance:3; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest23(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:!\"dummy\"; distance:13; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest24(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:\"dummy\"; within:15; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest25(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:\"dummy\"; within:10; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest26(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:\"dummy\"; distance:8; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest27(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "pcre:/body1/H; "
+ "content:\"dummy\"; distance:14; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest28(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Content-Length: 6\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!PacketAlertCheck(p2, 1));
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpHeaderTest29(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Content-Length: 7\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+#if 0
+
+static int DetectEngineHttpHeaderTest30(void)
+{
+ int result = 0;
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Content-Length: 6\"; http_header; "
+ "content:\"User-Agent: Mozilla\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list != NULL) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+#endif /* #if 0 */
+
+static int DetectEngineHttpHeaderTest30(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Set-Cookie: dummycookieset\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"dummycookieset\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/** \test reassembly bug where headers with names of length 6 were
+ * skipped
+ */
+static int DetectEngineHttpHeaderTest31(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Accept: blah\r\n"
+ "Cookie: blah\r\n"
+ "Crazy6: blah\r\n"
+ "SixZix: blah\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(content:\"Accept|3a|\"; http_header; "
+ "content:!\"Cookie|3a|\"; http_header; "
+ "content:\"Crazy6|3a|\"; http_header; "
+ "content:\"SixZix|3a|\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpHeaderTest32(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n"
+ "Dummy-Header: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(content:\"Dummy\"; http_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpHeaderTest33(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n";
+ uint8_t http2_buf[] =
+ "Dummy-Header: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF(de_ctx == NULL);
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(content:\"Dummy\"; http_header; "
+ "sid:1;)");
+ FAIL_IF(de_ctx->sig_list == NULL);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+
+ http_state = f.alstate;
+ FAIL_IF(http_state == NULL);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpHeaderTest34(void)
+{
+ TcpSession ssn;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Dummy-Header1: blah\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n";
+ uint8_t http2_buf[] =
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n";
+ uint8_t http3_buf[] =
+ "Dummy-Header2: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ uint32_t http3_len = sizeof(http3_buf) - 1;
+
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ Packet *p3 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p1->pcap_cnt = 1;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->pcap_cnt = 2;
+ p3->flow = &f;
+ p3->flowflags |= FLOW_PKT_TOSERVER;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p3->pcap_cnt = 3;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF(de_ctx == NULL);
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(content:\"Dummy\"; http_header; content:\"Header2\"; http_header; within:8; "
+ "sid:1;)");
+ FAIL_IF(de_ctx->sig_list == NULL);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+
+ http_state = f.alstate;
+ FAIL_IF(http_state == NULL);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http3_buf, http3_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
+ FAIL_IF(!PacketAlertCheck(p3, 1)); /* should match in trailer */
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ UTHFreePackets(&p3, 1);
+ PASS;
+}
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpHeaderTest35(void)
+{
+ TcpSession ssn;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Dummy-Header1: blah\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n";
+ uint8_t http2_buf[] =
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n";
+ uint8_t http3_buf[] =
+ "Dummy-Header2: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ uint32_t http3_len = sizeof(http3_buf) - 1;
+
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ Packet *p3 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p1->pcap_cnt = 1;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->pcap_cnt = 2;
+ p3->flow = &f;
+ p3->flowflags |= FLOW_PKT_TOSERVER;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p3->pcap_cnt = 3;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF(de_ctx == NULL);
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(content:\"Dummy\"; http_header; fast_pattern; content:\"Header2\"; http_header; within:8; "
+ "sid:1;)");
+ FAIL_IF(de_ctx->sig_list == NULL);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+
+ http_state = f.alstate;
+ FAIL_IF(http_state == NULL);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http3_buf, http3_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
+ FAIL_IF(!PacketAlertCheck(p3, 1)); /* should match in trailer */
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ UTHFreePackets(&p3, 1);
+ PASS;
+}
+
+void DetectHttpHeaderRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpHeaderParserTest01", DetectHttpHeaderParserTest01);
+ UtRegisterTest("DetectHttpHeaderParserTest02", DetectHttpHeaderParserTest02);
+
+ UtRegisterTest("DetectHttpHeaderTest06", DetectHttpHeaderTest06);
+ UtRegisterTest("DetectHttpHeaderTest07", DetectHttpHeaderTest07);
+ UtRegisterTest("DetectHttpHeaderTest08", DetectHttpHeaderTest08);
+ UtRegisterTest("DetectHttpHeaderTest09", DetectHttpHeaderTest09);
+ UtRegisterTest("DetectHttpHeaderTest10", DetectHttpHeaderTest10);
+ UtRegisterTest("DetectHttpHeaderTest11", DetectHttpHeaderTest11);
+ UtRegisterTest("DetectHttpHeaderTest12", DetectHttpHeaderTest12);
+ UtRegisterTest("DetectHttpHeaderTest13", DetectHttpHeaderTest13);
+ UtRegisterTest("DetectHttpHeaderTest28", DetectHttpHeaderTest28);
+ UtRegisterTest("DetectHttpHeaderTest29", DetectHttpHeaderTest29);
+ UtRegisterTest("DetectHttpHeaderTest30", DetectHttpHeaderTest30);
+
+ UtRegisterTest("DetectHttpHeaderIsdataatParseTest",
+ DetectHttpHeaderIsdataatParseTest);
+
+ UtRegisterTest("DetectEngineHttpHeaderTest01",
+ DetectEngineHttpHeaderTest01);
+ UtRegisterTest("DetectEngineHttpHeaderTest02",
+ DetectEngineHttpHeaderTest02);
+ UtRegisterTest("DetectEngineHttpHeaderTest03",
+ DetectEngineHttpHeaderTest03);
+ UtRegisterTest("DetectEngineHttpHeaderTest04",
+ DetectEngineHttpHeaderTest04);
+ UtRegisterTest("DetectEngineHttpHeaderTest05",
+ DetectEngineHttpHeaderTest05);
+ UtRegisterTest("DetectEngineHttpHeaderTest06",
+ DetectEngineHttpHeaderTest06);
+ UtRegisterTest("DetectEngineHttpHeaderTest07",
+ DetectEngineHttpHeaderTest07);
+ UtRegisterTest("DetectEngineHttpHeaderTest08",
+ DetectEngineHttpHeaderTest08);
+ UtRegisterTest("DetectEngineHttpHeaderTest09",
+ DetectEngineHttpHeaderTest09);
+ UtRegisterTest("DetectEngineHttpHeaderTest10",
+ DetectEngineHttpHeaderTest10);
+ UtRegisterTest("DetectEngineHttpHeaderTest11",
+ DetectEngineHttpHeaderTest11);
+ UtRegisterTest("DetectEngineHttpHeaderTest12",
+ DetectEngineHttpHeaderTest12);
+ UtRegisterTest("DetectEngineHttpHeaderTest13",
+ DetectEngineHttpHeaderTest13);
+ UtRegisterTest("DetectEngineHttpHeaderTest14",
+ DetectEngineHttpHeaderTest14);
+ UtRegisterTest("DetectEngineHttpHeaderTest15",
+ DetectEngineHttpHeaderTest15);
+ UtRegisterTest("DetectEngineHttpHeaderTest16",
+ DetectEngineHttpHeaderTest16);
+ UtRegisterTest("DetectEngineHttpHeaderTest17",
+ DetectEngineHttpHeaderTest17);
+ UtRegisterTest("DetectEngineHttpHeaderTest20",
+ DetectEngineHttpHeaderTest20);
+ UtRegisterTest("DetectEngineHttpHeaderTest21",
+ DetectEngineHttpHeaderTest21);
+ UtRegisterTest("DetectEngineHttpHeaderTest22",
+ DetectEngineHttpHeaderTest22);
+ UtRegisterTest("DetectEngineHttpHeaderTest23",
+ DetectEngineHttpHeaderTest23);
+ UtRegisterTest("DetectEngineHttpHeaderTest24",
+ DetectEngineHttpHeaderTest24);
+ UtRegisterTest("DetectEngineHttpHeaderTest25",
+ DetectEngineHttpHeaderTest25);
+ UtRegisterTest("DetectEngineHttpHeaderTest26",
+ DetectEngineHttpHeaderTest26);
+ UtRegisterTest("DetectEngineHttpHeaderTest27",
+ DetectEngineHttpHeaderTest27);
+ UtRegisterTest("DetectEngineHttpHeaderTest28",
+ DetectEngineHttpHeaderTest28);
+ UtRegisterTest("DetectEngineHttpHeaderTest29",
+ DetectEngineHttpHeaderTest29);
+ UtRegisterTest("DetectEngineHttpHeaderTest30",
+ DetectEngineHttpHeaderTest30);
+ UtRegisterTest("DetectEngineHttpHeaderTest31",
+ DetectEngineHttpHeaderTest31);
+#if 0
+ UtRegisterTest("DetectEngineHttpHeaderTest30",
+ DetectEngineHttpHeaderTest30, 1);
+#endif
+ UtRegisterTest("DetectEngineHttpHeaderTest32",
+ DetectEngineHttpHeaderTest32);
+ UtRegisterTest("DetectEngineHttpHeaderTest33 -- Trailer",
+ DetectEngineHttpHeaderTest33);
+ UtRegisterTest("DetectEngineHttpHeaderTest34 -- Trailer",
+ DetectEngineHttpHeaderTest34);
+ UtRegisterTest("DetectEngineHttpHeaderTest35 -- Trailer",
+ DetectEngineHttpHeaderTest35);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-host.c b/src/tests/detect-http-host.c
new file mode 100644
index 0000000..4fbdff9
--- /dev/null
+++ b/src/tests/detect-http-host.c
@@ -0,0 +1,7111 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * \brief Handle HTTP host header.
+ * HHHD - Http Host Header Data
+ *
+ */
+
+#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"
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"connect\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"co\"; depth:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:!\"ect\"; depth:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"ect\"; depth:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"con\"; depth:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"ect\"; offset:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"co\"; offset:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"ect\"; offset:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"con\"; offset:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:\"ec\"; within:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:!\"ec\"; within:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:\"ec\"; within:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:!\"ec\"; within:4; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:\"ec\"; distance:2; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:!\"ec\"; distance:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:\"ec\"; distance:3; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHHTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"co\"; http_host; "
+ "content:!\"ec\"; distance:2; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest18(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"kaboom\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest19(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com:8080\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"kaboom\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest20(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com:8080\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"8080\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest21(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"kaboom\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest22(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"kaboom\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest23(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"8080\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest24(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "Host: www.rabbit.com\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"kaboom\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHHTest25(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "Host: www.rabbit.com\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_host header test\"; "
+ "content:\"rabbit\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that a signature containing a http_host is correctly parsed
+ * and the keyword is registered.
+ */
+static int DetectHttpHHTest01(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:\"Testing http_host\"; "
+ "content:\"one\"; http_host; sid:1;)");
+ if (de_ctx->sig_list != NULL) {
+ result = 1;
+ } else {
+ goto end;
+ }
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+/**
+ * \test Test that a signature containing an valid http_host entry is
+ * parsed.
+ */
+static int DetectHttpHHTest02(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:\"Testing http_host\"; "
+ "content:\"one\"; http_host; sid:1;)");
+ if (de_ctx->sig_list != NULL)
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+/**
+ * \test Test that an invalid signature containing no content but a
+ * http_host is invalidated.
+ */
+static int DetectHttpHHTest03(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:\"Testing http_host\"; "
+ "http_host; sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+/**
+ * \test Test that an invalid signature containing a rawbytes along with a
+ * http_host is invalidated.
+ */
+static int DetectHttpHHTest04(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:\"Testing http_host\"; "
+ "content:\"one\"; rawbytes; http_host; sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+/**
+ * \test Test that a http_host with nocase is parsed.
+ */
+static int DetectHttpHHTest05(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:\"Testing http_host\"; "
+ "content:\"one\"; http_host; sid:1;)");
+ if (de_ctx->sig_list != NULL)
+ result = 1;
+
+ end:
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+/** \test invalid sig: uppercase content */
+static int DetectHttpHHTest05a(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"ABC\"; http_host; sid:1;)");
+ FAIL_IF_NOT_NULL(s);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ *\test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHHTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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\n");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHHTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message";
+ uint8_t http2_buf[] =
+ "body1\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched on p1 but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match on p2 but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHHTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "host: This is dummy mess";
+ uint8_t http2_buf[] =
+ "age body\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_host content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpHHTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy body1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"body1this\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_host content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpHHTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy bodY1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy bodY1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"body1this\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the negated http_host content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpHHTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:!\"message\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Negative test that the negated http_host content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpHHTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy body\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:!\"message\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHHTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test multiple http transactions and body chunks of request handling
+ */
+static int DetectHttpHHTest14(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
+ uint8_t httpbuf2[] = "Cookie: dummy1\r\n";
+ uint8_t httpbuf3[] = "Host: Body one!!\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "GET /?var=val HTTP/1.1\r\n";
+ uint8_t httpbuf5[] = "Cookie: dummy2\r\n";
+ uint8_t httpbuf6[] = "Host: Body two\r\n\r\n";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
+ uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy1\"; http_cookie; content:\"body one\"; http_host; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"dummy2\"; http_cookie; content:\"body two\"; http_host; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) || PacketAlertCheck(p, 2)) {
+ printf("sig 1 alerted (4): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
+ if (r != 0) {
+ printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
+ printf("sig 1 alerted (request 2, chunk 6): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ SCLogDebug("sending data chunk 7");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
+ if (r != 0) {
+ printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) || !(PacketAlertCheck(p, 2))) {
+ printf("signature 2 didn't match or sig 1 matched, but shouldn't have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHRHTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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\n");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHRHTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message";
+ uint8_t http2_buf[] = "body1\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched on p1 but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match on p2 but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHRHTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "host: This is dummy mess";
+ uint8_t http2_buf[] = "age body\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"message\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpHRHTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy body1";
+ uint8_t http2_buf[] = "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"body1This\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpHRHTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy bodY1";
+ uint8_t http2_buf[] = "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy bodY1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"bodY1This\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the negated http_raw_host content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpHRHTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:!\"message\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Negative test that the negated http_raw_host content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpHRHTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy body\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:!\"message\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpHRHTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list =
+ SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test multiple http transactions and body chunks of request handling
+ */
+static int DetectHttpHRHTest14(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
+ uint8_t httpbuf2[] = "Cookie: dummy1\r\n";
+ uint8_t httpbuf3[] = "Host: Body one!!\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "GET /?var=val HTTP/1.1\r\n";
+ uint8_t httpbuf5[] = "Cookie: dummy2\r\n";
+ uint8_t httpbuf6[] = "Host: Body two\r\n\r\n";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
+ uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy1\"; "
+ "http_cookie; content:\"Body one\"; http_raw_host; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"dummy2\"; "
+ "http_cookie; content:\"Body two\"; http_raw_host; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted (2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) || PacketAlertCheck(p, 2)) {
+ printf("sig 1 alerted (4): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
+ if (r != 0) {
+ printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
+ printf("sig 1 alerted (request 2, chunk 6): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ SCLogDebug("sending data chunk 7");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
+ if (r != 0) {
+ printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) || !(PacketAlertCheck(p, 2))) {
+ printf("signature 2 didn't match or sig 1 matched, but shouldn't have: ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+/**
+ *\test Test that the http_raw_host content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpHRHTest37(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: www.openinfosecfoundation.org\r\n"
+ "Host: This is dummy bodY1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy bodY1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host test\"; "
+ "content:\"body1this\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"CONNECT\"; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"CO\"; depth:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:!\"ECT\"; depth:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"ECT\"; depth:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"CON\"; depth:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"ECT\"; offset:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"CO\"; offset:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:!\"ECT\"; offset:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http host header test\"; "
+ "content:\"CON\"; offset:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:\"EC\"; within:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:!\"EC\"; within:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:\"EC\"; within:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:!\"EC\"; within:4; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:\"EC\"; distance:2; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:!\"EC\"; distance:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:\"EC\"; distance:3; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_raw_host header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpHRHTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: CONNECT\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"CO\"; http_raw_host; "
+ "content:!\"EC\"; distance:2; http_raw_host; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest18(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com:8080\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"kaboom\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest19(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com:8080\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"kaboom\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest20(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.kaboom.com:8080\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"8080\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest21(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"kaboom\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest22(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"kaboom\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest23(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"8080\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest24(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "Host: www.rabbit.com\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"kaboom\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpHRHTest25(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
+ "Host: www.rabbit.com\r\n"
+ "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http_raw_host header test\"; "
+ "content:\"rabbit\"; http_raw_host; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+void DetectHttpHHRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpHHTest01", DetectHttpHHTest01);
+ UtRegisterTest("DetectHttpHHTest02", DetectHttpHHTest02);
+ UtRegisterTest("DetectHttpHHTest03", DetectHttpHHTest03);
+ UtRegisterTest("DetectHttpHHTest04", DetectHttpHHTest04);
+ UtRegisterTest("DetectHttpHHTest05", DetectHttpHHTest05);
+ UtRegisterTest("DetectHttpHHTest05a", DetectHttpHHTest05a);
+ UtRegisterTest("DetectHttpHHTest06", DetectHttpHHTest06);
+ UtRegisterTest("DetectHttpHHTest07", DetectHttpHHTest07);
+ UtRegisterTest("DetectHttpHHTest08", DetectHttpHHTest08);
+ UtRegisterTest("DetectHttpHHTest09", DetectHttpHHTest09);
+ UtRegisterTest("DetectHttpHHTest10", DetectHttpHHTest10);
+ UtRegisterTest("DetectHttpHHTest11", DetectHttpHHTest11);
+ UtRegisterTest("DetectHttpHHTest12", DetectHttpHHTest12);
+ UtRegisterTest("DetectHttpHHTest13", DetectHttpHHTest13);
+ UtRegisterTest("DetectHttpHHTest14", DetectHttpHHTest14);
+
+ UtRegisterTest("DetectEngineHttpHHTest01", DetectEngineHttpHHTest01);
+ UtRegisterTest("DetectEngineHttpHHTest02", DetectEngineHttpHHTest02);
+ UtRegisterTest("DetectEngineHttpHHTest03", DetectEngineHttpHHTest03);
+ UtRegisterTest("DetectEngineHttpHHTest04", DetectEngineHttpHHTest04);
+ UtRegisterTest("DetectEngineHttpHHTest05", DetectEngineHttpHHTest05);
+ UtRegisterTest("DetectEngineHttpHHTest06", DetectEngineHttpHHTest06);
+ UtRegisterTest("DetectEngineHttpHHTest07", DetectEngineHttpHHTest07);
+ UtRegisterTest("DetectEngineHttpHHTest08", DetectEngineHttpHHTest08);
+ UtRegisterTest("DetectEngineHttpHHTest09", DetectEngineHttpHHTest09);
+ UtRegisterTest("DetectEngineHttpHHTest10", DetectEngineHttpHHTest10);
+ UtRegisterTest("DetectEngineHttpHHTest11", DetectEngineHttpHHTest11);
+ UtRegisterTest("DetectEngineHttpHHTest12", DetectEngineHttpHHTest12);
+ UtRegisterTest("DetectEngineHttpHHTest13", DetectEngineHttpHHTest13);
+ UtRegisterTest("DetectEngineHttpHHTest14", DetectEngineHttpHHTest14);
+ UtRegisterTest("DetectEngineHttpHHTest15", DetectEngineHttpHHTest15);
+ UtRegisterTest("DetectEngineHttpHHTest16", DetectEngineHttpHHTest16);
+ UtRegisterTest("DetectEngineHttpHHTest17", DetectEngineHttpHHTest17);
+ UtRegisterTest("DetectEngineHttpHHTest18", DetectEngineHttpHHTest18);
+ UtRegisterTest("DetectEngineHttpHHTest19", DetectEngineHttpHHTest19);
+ UtRegisterTest("DetectEngineHttpHHTest20", DetectEngineHttpHHTest20);
+ UtRegisterTest("DetectEngineHttpHHTest21", DetectEngineHttpHHTest21);
+ UtRegisterTest("DetectEngineHttpHHTest22", DetectEngineHttpHHTest22);
+ UtRegisterTest("DetectEngineHttpHHTest23", DetectEngineHttpHHTest23);
+ UtRegisterTest("DetectEngineHttpHHTest24", DetectEngineHttpHHTest24);
+ UtRegisterTest("DetectEngineHttpHHTest25", DetectEngineHttpHHTest25);
+
+ UtRegisterTest("DetectHttpHRHTest06", DetectHttpHRHTest06);
+ UtRegisterTest("DetectHttpHRHTest07", DetectHttpHRHTest07);
+ UtRegisterTest("DetectHttpHRHTest08", DetectHttpHRHTest08);
+ UtRegisterTest("DetectHttpHRHTest09", DetectHttpHRHTest09);
+ UtRegisterTest("DetectHttpHRHTest10", DetectHttpHRHTest10);
+ UtRegisterTest("DetectHttpHRHTest11", DetectHttpHRHTest11);
+ UtRegisterTest("DetectHttpHRHTest12", DetectHttpHRHTest12);
+ UtRegisterTest("DetectHttpHRHTest13", DetectHttpHRHTest13);
+ UtRegisterTest("DetectHttpHRHTest14", DetectHttpHRHTest14);
+
+ UtRegisterTest("DetectHttpHRHTest37", DetectHttpHRHTest37);
+
+ UtRegisterTest("DetectEngineHttpHRHTest01", DetectEngineHttpHRHTest01);
+ UtRegisterTest("DetectEngineHttpHRHTest02", DetectEngineHttpHRHTest02);
+ UtRegisterTest("DetectEngineHttpHRHTest03", DetectEngineHttpHRHTest03);
+ UtRegisterTest("DetectEngineHttpHRHTest04", DetectEngineHttpHRHTest04);
+ UtRegisterTest("DetectEngineHttpHRHTest05", DetectEngineHttpHRHTest05);
+ UtRegisterTest("DetectEngineHttpHRHTest06", DetectEngineHttpHRHTest06);
+ UtRegisterTest("DetectEngineHttpHRHTest07", DetectEngineHttpHRHTest07);
+ UtRegisterTest("DetectEngineHttpHRHTest08", DetectEngineHttpHRHTest08);
+ UtRegisterTest("DetectEngineHttpHRHTest09", DetectEngineHttpHRHTest09);
+ UtRegisterTest("DetectEngineHttpHRHTest10", DetectEngineHttpHRHTest10);
+ UtRegisterTest("DetectEngineHttpHRHTest11", DetectEngineHttpHRHTest11);
+ UtRegisterTest("DetectEngineHttpHRHTest12", DetectEngineHttpHRHTest12);
+ UtRegisterTest("DetectEngineHttpHRHTest13", DetectEngineHttpHRHTest13);
+ UtRegisterTest("DetectEngineHttpHRHTest14", DetectEngineHttpHRHTest14);
+ UtRegisterTest("DetectEngineHttpHRHTest15", DetectEngineHttpHRHTest15);
+ UtRegisterTest("DetectEngineHttpHRHTest16", DetectEngineHttpHRHTest16);
+ UtRegisterTest("DetectEngineHttpHRHTest17", DetectEngineHttpHRHTest17);
+ UtRegisterTest("DetectEngineHttpHRHTest18", DetectEngineHttpHRHTest18);
+ UtRegisterTest("DetectEngineHttpHRHTest19", DetectEngineHttpHRHTest19);
+ UtRegisterTest("DetectEngineHttpHRHTest20", DetectEngineHttpHRHTest20);
+ UtRegisterTest("DetectEngineHttpHRHTest21", DetectEngineHttpHRHTest21);
+ UtRegisterTest("DetectEngineHttpHRHTest22", DetectEngineHttpHRHTest22);
+ UtRegisterTest("DetectEngineHttpHRHTest23", DetectEngineHttpHRHTest23);
+ UtRegisterTest("DetectEngineHttpHRHTest24", DetectEngineHttpHRHTest24);
+ UtRegisterTest("DetectEngineHttpHRHTest25", DetectEngineHttpHRHTest25);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-method.c b/src/tests/detect-http-method.c
new file mode 100644
index 0000000..1da5c18
--- /dev/null
+++ b/src/tests/detect-http-method.c
@@ -0,0 +1,2207 @@
+/* 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ *
+ * \brief Handle HTTP method match
+ *
+ */
+
+#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"
+#include "../detect-isdataat.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"GET\"; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; depth:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"ECT\"; depth:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"ECT\"; depth:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"CON\"; depth:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"ECT\"; offset:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"CO\"; offset:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:!\"ECT\"; offset:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CON\"; offset:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:\"EC\"; within:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:!\"EC\"; within:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:\"EC\"; within:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:!\"EC\"; within:4; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:\"EC\"; distance:2; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:!\"EC\"; distance:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:\"EC\"; distance:3; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ * \test Test that the http_method content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpMethodTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "CONNECT /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"CO\"; http_method; "
+ "content:!\"EC\"; distance:2; http_method; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test Check a signature with content */
+static int DetectHttpMethodTest01(void)
+{
+ 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_method\"; "
+ "content:\"GET\"; "
+ "http_method; sid:1;)");
+
+ if (de_ctx->sig_list != NULL) {
+ result = 1;
+ } else {
+ printf("sig parse failed: ");
+ }
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check a signature without content (fail) */
+static int DetectHttpMethodTest02(void)
+{
+ 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_method\"; "
+ "http_method; sid:1;)");
+
+ if (de_ctx->sig_list == NULL) {
+ result = 1;
+ }
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check a signature with parameter (fail) */
+static int DetectHttpMethodTest03(void)
+{
+ 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_method\"; "
+ "content:\"foobar\"; "
+ "http_method:\"GET\"; sid:1;)");
+
+ if (de_ctx->sig_list == NULL) {
+ result = 1;
+ }
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check a signature with fast_pattern (should work) */
+static int DetectHttpMethodTest04(void)
+{
+ 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_method\"; "
+ "content:\"GET\"; "
+ "fast_pattern; "
+ "http_method; sid:1;)");
+
+ if (de_ctx->sig_list != NULL) {
+ result = 1;
+ }
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check a signature with rawbytes (fail) */
+static int DetectHttpMethodTest05(void)
+{
+ 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_method\"; "
+ "content:\"GET\"; "
+ "rawbytes; "
+ "http_method; sid:1;)");
+
+ if (de_ctx->sig_list == NULL) {
+ result = 1;
+ }
+
+ end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+/** \test Check a signature with an known request method */
+static int DetectHttpMethodSigTest01(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "GET / HTTP/1.0\r\n"
+ "Host: foo.bar.tld\r\n"
+ "\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Testing http_method\"; "
+ "content:\"GET\"; "
+ "http_method; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s = s->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(msg:\"Testing http_method\"; "
+ "content:\"POST\"; "
+ "http_method; sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ SCLogDebug("no http state: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ if (!(PacketAlertCheck(p, 1))) {
+ goto end;
+ }
+ if (PacketAlertCheck(p, 2)) {
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test Check a signature with an unknown request method */
+static int DetectHttpMethodSigTest02(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "FOO / HTTP/1.0\r\n"
+ "Host: foo.bar.tld\r\n"
+ "\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Testing http_method\"; "
+ "content:\"FOO\"; "
+ "http_method; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s = s->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(msg:\"Testing http_method\"; "
+ "content:\"BAR\"; "
+ "http_method; sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ SCLogDebug("no http state: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ if (!(PacketAlertCheck(p, 1))) {
+ goto end;
+ }
+ if (PacketAlertCheck(p, 2)) {
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test Check a signature against an unparsable request */
+static int DetectHttpMethodSigTest03(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = " ";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Testing http_method\"; "
+ "content:\"GET\"; "
+ "http_method; sid:1;)");
+ if (s == NULL) {
+ SCLogDebug("Bad signature");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ SCLogDebug("no http state: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ if (PacketAlertCheck(p, 1)) {
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test Check a signature with an request method and negation of the same */
+static int DetectHttpMethodSigTest04(void)
+{
+ int result = 0;
+ Flow f;
+ uint8_t httpbuf1[] = "GET / HTTP/1.0\r\n"
+ "Host: foo.bar.tld\r\n"
+ "\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any (msg:\"Testing http_method\"; "
+ "content:\"GET\"; http_method; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s = s->next = SigInit(de_ctx,
+ "alert tcp any any -> any any (msg:\"Testing http_method\"; "
+ "content:!\"GET\"; http_method; sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ SCLogDebug("no http state: ");
+ goto end;
+ }
+
+ 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 matched 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);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectHttpMethodIsdataatParseTest(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any ("
+ "content:\"one\"; http_method; "
+ "isdataat:!4,relative; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigMatch *sm = DetectBufferGetLastSigMatch(s, g_http_method_buffer_id);
+ FAIL_IF_NULL(sm);
+ FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
+
+ DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
+ FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
+ FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
+ FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectHttpMethod
+ */
+void DetectHttpMethodRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpMethodTest01", DetectHttpMethodTest01);
+ UtRegisterTest("DetectHttpMethodTest02", DetectHttpMethodTest02);
+ UtRegisterTest("DetectHttpMethodTest03", DetectHttpMethodTest03);
+ UtRegisterTest("DetectHttpMethodTest04", DetectHttpMethodTest04);
+ UtRegisterTest("DetectHttpMethodTest05", DetectHttpMethodTest05);
+ UtRegisterTest("DetectHttpMethodSigTest01", DetectHttpMethodSigTest01);
+ UtRegisterTest("DetectHttpMethodSigTest02", DetectHttpMethodSigTest02);
+ UtRegisterTest("DetectHttpMethodSigTest03", DetectHttpMethodSigTest03);
+ UtRegisterTest("DetectHttpMethodSigTest04", DetectHttpMethodSigTest04);
+
+ UtRegisterTest("DetectHttpMethodIsdataatParseTest",
+ DetectHttpMethodIsdataatParseTest);
+ UtRegisterTest("DetectEngineHttpMethodTest01",
+ DetectEngineHttpMethodTest01);
+ UtRegisterTest("DetectEngineHttpMethodTest02",
+ DetectEngineHttpMethodTest02);
+ UtRegisterTest("DetectEngineHttpMethodTest03",
+ DetectEngineHttpMethodTest03);
+ UtRegisterTest("DetectEngineHttpMethodTest04",
+ DetectEngineHttpMethodTest04);
+ UtRegisterTest("DetectEngineHttpMethodTest05",
+ DetectEngineHttpMethodTest05);
+ UtRegisterTest("DetectEngineHttpMethodTest06",
+ DetectEngineHttpMethodTest06);
+ UtRegisterTest("DetectEngineHttpMethodTest07",
+ DetectEngineHttpMethodTest07);
+ UtRegisterTest("DetectEngineHttpMethodTest08",
+ DetectEngineHttpMethodTest08);
+ UtRegisterTest("DetectEngineHttpMethodTest09",
+ DetectEngineHttpMethodTest09);
+ UtRegisterTest("DetectEngineHttpMethodTest10",
+ DetectEngineHttpMethodTest10);
+ UtRegisterTest("DetectEngineHttpMethodTest11",
+ DetectEngineHttpMethodTest11);
+ UtRegisterTest("DetectEngineHttpMethodTest12",
+ DetectEngineHttpMethodTest12);
+ UtRegisterTest("DetectEngineHttpMethodTest13",
+ DetectEngineHttpMethodTest13);
+ UtRegisterTest("DetectEngineHttpMethodTest14",
+ DetectEngineHttpMethodTest14);
+ UtRegisterTest("DetectEngineHttpMethodTest15",
+ DetectEngineHttpMethodTest15);
+ UtRegisterTest("DetectEngineHttpMethodTest16",
+ DetectEngineHttpMethodTest16);
+ UtRegisterTest("DetectEngineHttpMethodTest17",
+ DetectEngineHttpMethodTest17);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-raw-header.c b/src/tests/detect-http-raw-header.c
new file mode 100644
index 0000000..de716cb
--- /dev/null
+++ b/src/tests/detect-http-raw-header.c
@@ -0,0 +1,3960 @@
+/* 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * \brief Handle HTTP raw header match.
+ *
+ */
+
+#include "../suricata-common.h"
+#include "../suricata.h"
+#include "../decode.h"
+
+#include "../detect.h"
+#include "../detect-engine.h"
+#include "../detect-isdataat.h"
+#include "../detect-pcre.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+#include "../stream-tcp.h"
+#include "../app-layer.h"
+#include "../app-layer-htp.h"
+#include "../app-layer-protos.h"
+#include "../app-layer-parser.h"
+
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+#include "../util-validate.h"
+
+/***********************************Unittests**********************************/
+
+#ifdef UNITTESTS
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpRawHeaderParserTest01(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; http_raw_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; nocase; http_raw_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; endswith; http_raw_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; http_raw_header; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; endswith; http_raw_header; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; rawbytes; http_raw_header; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http_raw_header; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; content:\"abc\"; http_raw_header; sid:1;)", false));
+ PASS;
+}
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpRawHeaderParserTest02(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; nocase; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; startswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; startswith; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; bsize:10; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; rawbytes; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http.header.raw; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; sid:1;)", false));
+ PASS;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest02(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; depth:15; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest03(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"one\"; depth:5; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest04(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; depth:5; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest05(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"one\"; depth:15; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; offset:10; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest07(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"one\"; offset:15; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; offset:15; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest09(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"one\"; offset:10; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest10(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:\"three\"; http_raw_header; within:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:!\"three\"; http_raw_header; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:!\"three\"; http_raw_header; within:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:\"three\"; http_raw_header; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest14(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:\"five\"; http_raw_header; distance:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest15(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:!\"five\"; http_raw_header; distance:15; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest16(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:!\"five\"; http_raw_header; distance:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectEngineHttpRawHeaderTest17(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"one\"; http_raw_header; content:\"five\"; http_raw_header; distance:15; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest20(void)
+{
+ TcpSession ssn;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p1);
+ Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p2);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(flow:to_server; pcre:/body1/D; "
+ "content:!\"dummy\"; http_raw_header; within:7; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+
+ HtpState *http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+
+ PASS;
+}
+
+static int DetectEngineHttpRawHeaderTest21(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:!\"dummy\"; within:7; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest22(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:!\"dummy\"; distance:3; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest23(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:!\"dummy\"; distance:13; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest24(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:\"dummy\"; within:15; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest25(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:\"dummy\"; within:10; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest26(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:\"dummy\"; distance:8; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest27(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: This_is_dummy_body1";
+ uint8_t http2_buf[] =
+ "This_is_dummy_message_body2\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; flow:to_server; "
+ "pcre:/body1/D; "
+ "content:\"dummy\"; distance:14; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest28(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_client; "
+ "content:\"Content-Length: 6\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawHeaderTest29(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_client; "
+ "content:\"Content-Length: 7\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+#if 0
+
+static int DetectEngineHttpRawHeaderTest30(void)
+{
+ int result = 0;
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"http header test\"; "
+ "content:\"Content-Length: 6\"; http_raw_header; "
+ "content:\"User-Agent: Mozilla\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list != NULL) {
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
+#endif /* #if 0 */
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpRawHeaderTest31(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n"
+ "Dummy-Header: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(flow:to_server; "
+ "content:\"Dummy\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+/**
+ * \test Trailing headers.
+ */
+static int DetectEngineHttpRawHeaderTest32(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "host: boom\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "13\r\n"
+ "This is dummy body1\r\n"
+ "0\r\n";
+ uint8_t http2_buf[] =
+ "Dummy-Header: kaboom\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(flow:to_server; "
+ "content:\"Dummy\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpRawHeaderTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"Content-Type: text/html\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpRawHeaderTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozi";
+ uint8_t http2_buf[] =
+ "lla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\nContent-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy message body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"Mozilla\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ( (PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpRawHeaderTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n";
+ uint8_t http2_buf[] =
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"Gecko/20091221 Firefox/3.5.7\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpRawHeaderTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
+ uint8_t http2_buf[] =
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy body\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"Firefox/3.5.7|0D 0A|Content\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpRawHeaderTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
+ uint8_t http2_buf[] =
+ "Content-Type: text/html\r\n"
+ "Content-Length: 67\r\n"
+ "\r\n"
+ "This is dummy body";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"firefox/3.5.7|0D 0A|content\"; nocase; http_raw_header;"
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the negated http_header content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpRawHeaderTest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"lalalalala\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Negative test that the negated http_header content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpRawHeaderTest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 26\r\n"
+ "\r\n"
+ "This is dummy message body\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:!\"User-Agent: Mozilla/5.0 \"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_header content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpRawHeaderTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 100\r\n"
+ "\r\n"
+ "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ int result = 0;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http header test\"; flow:to_server; "
+ "content:\"Host: www.openinfosecfoundation.org\"; http_raw_header; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ result = 1;
+end:
+
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+void DetectHttpRawHeaderRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpRawHeaderParserTest01",
+ DetectHttpRawHeaderParserTest01);
+ UtRegisterTest("DetectHttpRawHeaderParserTest02",
+ DetectHttpRawHeaderParserTest02);
+
+ UtRegisterTest("DetectEngineHttpRawHeaderTest01",
+ DetectEngineHttpRawHeaderTest01);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest02",
+ DetectEngineHttpRawHeaderTest02);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest03",
+ DetectEngineHttpRawHeaderTest03);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest04",
+ DetectEngineHttpRawHeaderTest04);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest05",
+ DetectEngineHttpRawHeaderTest05);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest06",
+ DetectEngineHttpRawHeaderTest06);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest07",
+ DetectEngineHttpRawHeaderTest07);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest08",
+ DetectEngineHttpRawHeaderTest08);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest09",
+ DetectEngineHttpRawHeaderTest09);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest10",
+ DetectEngineHttpRawHeaderTest10);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest11",
+ DetectEngineHttpRawHeaderTest11);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest12",
+ DetectEngineHttpRawHeaderTest12);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest13",
+ DetectEngineHttpRawHeaderTest13);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest14",
+ DetectEngineHttpRawHeaderTest14);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest15",
+ DetectEngineHttpRawHeaderTest15);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest16",
+ DetectEngineHttpRawHeaderTest16);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest17",
+ DetectEngineHttpRawHeaderTest17);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest20",
+ DetectEngineHttpRawHeaderTest20);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest21",
+ DetectEngineHttpRawHeaderTest21);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest22",
+ DetectEngineHttpRawHeaderTest22);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest23",
+ DetectEngineHttpRawHeaderTest23);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest24",
+ DetectEngineHttpRawHeaderTest24);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest25",
+ DetectEngineHttpRawHeaderTest25);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest26",
+ DetectEngineHttpRawHeaderTest26);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest27",
+ DetectEngineHttpRawHeaderTest27);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest28",
+ DetectEngineHttpRawHeaderTest28);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest29",
+ DetectEngineHttpRawHeaderTest29);
+#if 0
+ UtRegisterTest("DetectEngineHttpRawHeaderTest30",
+ DetectEngineHttpRawHeaderTest30, 1);
+#endif
+ UtRegisterTest("DetectEngineHttpRawHeaderTest31",
+ DetectEngineHttpRawHeaderTest31);
+ UtRegisterTest("DetectEngineHttpRawHeaderTest32",
+ DetectEngineHttpRawHeaderTest32);
+
+ UtRegisterTest("DetectHttpRawHeaderTest06", DetectHttpRawHeaderTest06);
+ UtRegisterTest("DetectHttpRawHeaderTest07", DetectHttpRawHeaderTest07);
+ UtRegisterTest("DetectHttpRawHeaderTest08", DetectHttpRawHeaderTest08);
+ UtRegisterTest("DetectHttpRawHeaderTest09", DetectHttpRawHeaderTest09);
+ UtRegisterTest("DetectHttpRawHeaderTest10", DetectHttpRawHeaderTest10);
+ UtRegisterTest("DetectHttpRawHeaderTest11", DetectHttpRawHeaderTest11);
+ UtRegisterTest("DetectHttpRawHeaderTest12", DetectHttpRawHeaderTest12);
+ UtRegisterTest("DetectHttpRawHeaderTest13", DetectHttpRawHeaderTest13);
+}
+
+#endif /* UNITTESTS */
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-server-body.c b/src/tests/detect-http-server-body.c
new file mode 100644
index 0000000..29340fb
--- /dev/null
+++ b/src/tests/detect-http-server-body.c
@@ -0,0 +1,8044 @@
+/* Copyright (C) 2017 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 Giuseppe Longo <giuseppe@glongo.it>
+ *
+ * Tests for the hsbd with swf files
+ */
+
+#include "../suricata-common.h"
+#include "../conf-yaml-loader.h"
+#include "../decode.h"
+#include "../flow.h"
+#include "../detect.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpServerBodyParserTest01(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; http_server_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; nocase; http_server_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; endswith; http_server_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; startswith; http_server_body; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; startswith; endswith; http_server_body; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; content:\"abc\"; rawbytes; http_server_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_client; http_server_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_client; content:\"abc\"; http_server_body; sid:1;)", false));
+ PASS;
+}
+
+/**
+ * \test Test parser accepting valid rules and rejecting invalid rules
+ */
+static int DetectHttpServerBodyParserTest02(void)
+{
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; nocase; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; startswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; startswith; endswith; sid:1;)", true));
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; bsize:10; sid:1;)", true));
+
+ FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_client; http.response_body; content:\"abc\"; rawbytes; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_client; http.response_body; sid:1;)", false));
+ FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_client; http.response_body; content:\"abc\"; sid:1;)", false));
+ PASS;
+}
+struct TestSteps {
+ const uint8_t *input;
+ size_t input_size; /**< if 0 strlen will be used */
+ int direction; /**< STREAM_TOSERVER, STREAM_TOCLIENT */
+ int expect;
+};
+
+static int RunTest(struct TestSteps *steps, const char *sig, const char *yaml)
+{
+ TcpSession ssn;
+ Flow f;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ if (yaml) {
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(yaml, strlen(yaml));
+ HTPConfigure();
+ EngineModeSetIPS();
+ }
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ f.alproto = ALPROTO_HTTP1;
+
+ SCLogDebug("sig %s", sig);
+ Signature *s = DetectEngineAppendSig(de_ctx, (char *)sig);
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ struct TestSteps *b = steps;
+ int i = 0;
+ while (b->input != NULL) {
+ SCLogDebug("chunk %p %d", b, i);
+ Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+ p->flow = &f;
+ p->flowflags = (b->direction == STREAM_TOSERVER) ? FLOW_PKT_TOSERVER : FLOW_PKT_TOCLIENT;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, b->direction,
+ (uint8_t *)b->input,
+ b->input_size ? b->input_size : strlen((const char *)b->input));
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ int match = PacketAlertCheck(p, 1);
+ FAIL_IF_NOT(b->expect == match);
+
+ UTHFreePackets(&p, 1);
+ b++;
+ i++;
+ }
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+
+ if (yaml) {
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+ EngineModeSetIDS();
+ }
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyTest01(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "message";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"message\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "xxxxABC";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"ABC\"; http_server_body; offset:4; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ int result = 0;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 17\r\n"
+ "\r\n"
+ "1234567";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "8901234ABC";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"ABC\"; http_server_body; offset:14; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest04(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:!\"abc\"; http_server_body; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest05(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"abc\"; http_server_body; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest06(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:!\"def\"; http_server_body; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:!\"def\"; http_server_body; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:!\"abc\"; http_server_body; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"abc\"; http_server_body; depth:3; "
+ "content:\"def\"; http_server_body; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"abc\"; http_server_body; depth:3; "
+ "content:!\"xyz\"; http_server_body; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest11(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"abc\"; http_server_body; depth:3; "
+ "content:\"xyz\"; http_server_body; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did match but should not have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest12(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"ab\"; http_server_body; depth:2; "
+ "content:\"ef\"; http_server_body; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest13(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"ab\"; http_server_body; depth:3; "
+ "content:!\"yz\"; http_server_body; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest14(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "pcre:/ab/Q; "
+ "content:\"ef\"; http_server_body; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest15(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "pcre:/abc/Q; "
+ "content:!\"xyz\"; http_server_body; distance:0; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest16(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+ personality: IDS\n\
+ request-body-limit: 0\n\
+ response-body-limit: 0\n\
+\n\
+ request-body-inspect-window: 0\n\
+ response-body-inspect-window: 0\n\
+ request-body-minimal-inspect-size: 0\n\
+ response-body-minimal-inspect-size: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ int result = 0;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 17\r\n"
+ "\r\n"
+ "1234567";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "8901234ABC";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"890\"; within:3; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyTest17(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+ personality: IDS\n\
+ request-body-limit: 0\n\
+ response-body-limit: 0\n\
+\n\
+ request-body-inspect-window: 0\n\
+ response-body-inspect-window: 0\n\
+ request-body-minimal-inspect-size: 0\n\
+ response-body-minimal-inspect-size: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 17\r\n"
+ "\r\n"
+ "1234567";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "8901234ABC";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any ("
+ "content:\"890\"; depth:3; http_server_body; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF_NOT(r == 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ SCLogDebug("chunk http_buf2");
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ SCLogDebug("chunk http_buf3");
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/*
+ * gzip stream
+ */
+static int DetectEngineHttpServerBodyTest18(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '5', '1', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'g', 'z', 'i', 'p', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x1f, 0x8b, 0x08, 0x08, 0x27, 0x1e, 0xe5, 0x51,
+ 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
+ 0x78, 0x74, 0x00, 0x2b, 0xc9, 0xc8, 0x2c, 0x56,
+ 0x00, 0xa2, 0x44, 0x85, 0xb4, 0xcc, 0x9c, 0x54,
+ 0x85, 0xcc, 0x3c, 0x20, 0x2b, 0x29, 0xbf, 0x42,
+ 0x8f, 0x0b, 0x00, 0xb2, 0x7d, 0xac, 0x9b, 0x19,
+ 0x00, 0x00, 0x00,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"file\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/*
+ * deflate stream
+ */
+static int DetectEngineHttpServerBodyTest19(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '2', '4', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'd', 'e', 'f', 'l', 'a', 't', 'e', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x2b, 0xc9, 0xc8, 0x2c, 0x56,
+ 0x00, 0xa2, 0x44, 0x85, 0xb4, 0xcc, 0x9c, 0x54,
+ 0x85, 0xcc, 0x3c, 0x20, 0x2b, 0x29, 0xbf, 0x42,
+ 0x8f, 0x0b, 0x00,
+ };
+ // 0xb2, 0x7d, 0xac, 0x9b, 0x19, 0x00, 0x00, 0x00,
+ uint32_t http_len2 = sizeof(http_buf2);
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"file\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/*
+ * deflate stream with gzip set as content-encoding
+ */
+static int DetectEngineHttpServerBodyTest20(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '2', '4', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'g', 'z', 'i', 'p', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x2b, 0xc9, 0xc8, 0x2c, 0x56,
+ 0x00, 0xa2, 0x44, 0x85, 0xb4, 0xcc, 0x9c, 0x54,
+ 0x85, 0xcc, 0x3c, 0x20, 0x2b, 0x29, 0xbf, 0x42,
+ 0x8f, 0x0b, 0x00,
+ };
+ // 0xb2, 0x7d, 0xac, 0x9b, 0x19, 0x00, 0x00, 0x00,
+ uint32_t http_len2 = sizeof(http_buf2);
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"file\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+#ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+#endif
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/*
+ * gzip stream with deflate set as content-encoding.
+ */
+static int DetectEngineHttpServerBodyTest21(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '5', '1', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'd', 'e', 'f', 'l', 'a', 't', 'e', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x1f, 0x8b, 0x08, 0x08, 0x27, 0x1e, 0xe5, 0x51,
+ 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
+ 0x78, 0x74, 0x00, 0x2b, 0xc9, 0xc8, 0x2c, 0x56,
+ 0x00, 0xa2, 0x44, 0x85, 0xb4, 0xcc, 0x9c, 0x54,
+ 0x85, 0xcc, 0x3c, 0x20, 0x2b, 0x29, 0xbf, 0x42,
+ 0x8f, 0x0b, 0x00, 0xb2, 0x7d, 0xac, 0x9b, 0x19,
+ 0x00, 0x00, 0x00,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"file\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+#ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+#endif
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/*
+ * gzip stream.
+ * We have 2 content-encoding headers. First gzip and second deflate.
+ */
+static int DetectEngineHttpServerBodyTest22(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '5', '1', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'g', 'z', 'i', 'p', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', ':', ' ', 'd', 'e', 'f', 'l', 'a', 't', 'e', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x1f, 0x8b, 0x08, 0x08, 0x27, 0x1e, 0xe5, 0x51,
+ 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
+ 0x78, 0x74, 0x00, 0x2b, 0xc9, 0xc8, 0x2c, 0x56,
+ 0x00, 0xa2, 0x44, 0x85, 0xb4, 0xcc, 0x9c, 0x54,
+ 0x85, 0xcc, 0x3c, 0x20, 0x2b, 0x29, 0xbf, 0x42,
+ 0x8f, 0x0b, 0x00, 0xb2, 0x7d, 0xac, 0x9b, 0x19,
+ 0x00, 0x00, 0x00,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"file\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+#ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+#endif
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest01(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "file_data; pcre:/ab/; "
+ "content:\"ef\"; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "file_data; pcre:/abc/; "
+ "content:!\"xyz\"; distance:0; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/* \test recursive relative byte test */
+static int DetectEngineHttpServerBodyFileDataTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 33\r\n"
+ "\r\n"
+ "XYZ_klm_1234abcd_XYZ_klm_5678abcd";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"match on 1st\"; "
+ "file_data; content:\"XYZ\"; content:\"_klm_\"; distance:0; content:\"abcd\"; distance:4; byte_test:4,=,1234,-8,relative,string;"
+ "sid:1;)")))
+ goto end;
+ if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"match on 2nd\"; "
+ "file_data; content:\"XYZ\"; content:\"_klm_\"; distance:0; content:\"abcd\"; distance:4; byte_test:4,=,5678,-8,relative,string;"
+ "sid:2;)")))
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+ if (!PacketAlertCheck(p2, 2)) {
+ printf("sid 2 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest04(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 1 },
+ { (const uint8_t *)"ef",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abcd\"; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest05(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"ef",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abcdef\"; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest06(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"ef",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"bcdef\"; offset:1; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest07(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 1 },
+ { (const uint8_t *)"123456789",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"bc\"; offset:1; depth:2; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest08(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"1234567890",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"d123456789\"; offset:3; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest09(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"cd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"123456789",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abcd12\"; depth:6; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest10(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 5\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"c",
+ 0, STREAM_TOCLIENT, 1 },
+ { (const uint8_t *)"de",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abc\"; depth:3; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest11(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 5\r\n"
+ "\r\n"
+ "ab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"c",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"de",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"bcde\"; offset:1; depth:4; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest12(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 6\n\
+ response-body-inspect-window: 3\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "a",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"b",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"c",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"d",
+ 0, STREAM_TOCLIENT, 1 },
+ { (const uint8_t *)"efghijklm",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abcd\"; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest13(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 9\n\
+ response-body-inspect-window: 12\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "a",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"b",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"c",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"d",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"efghijklm",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"abcdefghijklm\"; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest14(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 9\n\
+ response-body-inspect-window: 12\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 20\r\n"
+ "\r\n"
+ "1234567890",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"abcdefghi",
+ 0, STREAM_TOCLIENT, 1 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"890abcdefghi\"; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest15(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 9\n\
+ response-body-inspect-window: 12\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 20\r\n"
+ "\r\n"
+ "1234567890",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"abcdefghi",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"7890ab\"; depth:6; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest16(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 9\n\
+ response-body-inspect-window: 12\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 20\r\n"
+ "\r\n"
+ "aaaab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"bbbbc",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"ccccd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"dddde",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"aabb\"; depth:4; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest17(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 8\n\
+ response-body-inspect-window: 4\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 20\r\n"
+ "\r\n"
+ "aaaab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"bbbbc",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"ccccd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"dddde",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"bbbc\"; depth:4; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+
+static int DetectEngineHttpServerBodyFileDataTest18(void)
+{
+
+ const char yaml[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ http-body-inline: yes\n\
+ response-body-minimal-inspect-size: 8\n\
+ response-body-inspect-window: 4\n\
+";
+
+ struct TestSteps steps[] = {
+ { (const uint8_t *)"GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n",
+ 0, STREAM_TOSERVER, 0 },
+ { (const uint8_t *)"HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 20\r\n"
+ "\r\n"
+ "aaaab",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"bbbbc",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"ccccd",
+ 0, STREAM_TOCLIENT, 0 },
+ { (const uint8_t *)"dddde",
+ 0, STREAM_TOCLIENT, 0 },
+ { NULL, 0, 0, 0 },
+ };
+
+ const char *sig = "alert http any any -> any any (file_data; content:\"bccd\"; depth:4; sid:1;)";
+ return RunTest(steps, sig, yaml);
+}
+static int DetectEngineHttpServerBodyFileDataTest19(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x0a, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"FWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest20(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: no\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x0a, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"CWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest21(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: deflate\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x0a, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"FWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest22(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: lzma\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x0a, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"CWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest23(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x01, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"CWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest24(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '1', '0', '3', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x5a, 0x57, 0x53, 0x17, 0x5c, 0x24, 0x00, 0x00, 0xb7, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x3b, 0xff, 0xfc, 0x8e, 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85,
+ 0xf5, 0x75, 0x6f, 0xd0, 0x7e, 0x61, 0x35, 0x1b, 0x1a, 0x8b, 0x16, 0x4d, 0xdf, 0x05, 0x32, 0xfe,
+ 0xa4, 0x4c, 0x46, 0x49, 0xb7, 0x7b, 0x6b, 0x75, 0xf9, 0x2b, 0x5c, 0x37, 0x29, 0x0b, 0x91, 0x37,
+ 0x01, 0x37, 0x0e, 0xe9, 0xf2, 0xe1, 0xfc, 0x9e, 0x64, 0xda, 0x6c, 0x11, 0x21, 0x33, 0xed, 0xa0,
+ 0x0e, 0x76, 0x70, 0xa0, 0xcd, 0x98, 0x2e, 0x76, 0x80, 0xf0, 0xe0, 0x59, 0x56, 0x06, 0x08, 0xe9,
+ 0xca, 0xeb, 0xa2, 0xc6, 0xdb, 0x5a, 0x86
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"FWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest25(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: no\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '1', '0', '3', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x5a, 0x57, 0x53, 0x17, 0x5c, 0x24, 0x00, 0x00, 0xb7, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3b, 0xff, 0xfc, 0x8e, 0x19,
+ 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85, 0xf5, 0x75, 0x6f, 0xd0, 0x7e, 0x61, 0x35, 0x1b, 0x1a, 0x8b, 0x16, 0x4d, 0xdf, 0x05,
+ 0x32, 0xfe, 0xa4, 0x4c, 0x46, 0x49, 0xb7, 0x7b, 0x6b, 0x75, 0xf9, 0x2b, 0x5c, 0x37, 0x29, 0x0b, 0x91, 0x37, 0x01, 0x37, 0x0e, 0xe9, 0xf2,
+ 0xe1, 0xfc, 0x9e, 0x64, 0xda, 0x6c, 0x11, 0x21, 0x33, 0xed, 0xa0, 0x0e, 0x76, 0x70, 0xa0, 0xcd, 0x98, 0x2e, 0x76, 0x80, 0xf0, 0xe0, 0x59,
+ 0x56, 0x06, 0x08, 0xe9, 0xca, 0xeb, 0xa2, 0xc6, 0xdb, 0x5a, 0x86
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"ZWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest26(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: lzma\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '1', '0', '3', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x5a, 0x57, 0x53, 0x17, 0x5c, 0x24, 0x00, 0x00, 0xb7, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x3b, 0xff, 0xfc, 0x8e, 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85,
+ 0xf5, 0x75, 0x6f, 0xd0, 0x7e, 0x61, 0x35, 0x1b, 0x1a, 0x8b, 0x16, 0x4d, 0xdf, 0x05, 0x32, 0xfe,
+ 0xa4, 0x4c, 0x46, 0x49, 0xb7, 0x7b, 0x6b, 0x75, 0xf9, 0x2b, 0x5c, 0x37, 0x29, 0x0b, 0x91, 0x37,
+ 0x01, 0x37, 0x0e, 0xe9, 0xf2, 0xe1, 0xfc, 0x9e, 0x64, 0xda, 0x6c, 0x11, 0x21, 0x33, 0xed, 0xa0,
+ 0x0e, 0x76, 0x70, 0xa0, 0xcd, 0x98, 0x2e, 0x76, 0x80, 0xf0, 0xe0, 0x59, 0x56, 0x06, 0x08, 0xe9,
+ 0xca, 0xeb, 0xa2, 0xc6, 0xdb, 0x5a, 0x86
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"FWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest27(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: deflate\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x5a, 0x57, 0x53, 0x17, 0x5c, 0x24, 0x00, 0x00, 0xb7, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x3b, 0xff, 0xfc, 0x8e, 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85,
+ 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85, 0xf5, 0x75, 0x6f, 0xd0, 0x7e, 0x61,
+ 0x35, 0x1b, 0x1a, 0x8b, 0x16, 0x4d, 0xdf, 0x05, 0x32, 0xfe, 0xa4, 0x4c, 0x46, 0x49, 0xb7, 0x7b,
+ 0x6b, 0x75, 0xf9, 0x2b, 0x5c, 0x37, 0x29, 0x0b, 0x91, 0x37, 0x01, 0x37, 0x0e, 0xe9, 0xf2, 0xe1,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"ZWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest28(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: both\n\
+ compress-depth: 0\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x5a, 0x57, 0x53, 0x01, 0x5c, 0x24, 0x00, 0x00, 0xb7, 0x21, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x3b, 0xff, 0xfc, 0x8e, 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85,
+ 0x19, 0xfa, 0xdf, 0xe7, 0x66, 0x08, 0xa0, 0x3d, 0x3e, 0x85, 0xf5, 0x75, 0x6f, 0xd0, 0x7e, 0x61,
+ 0x35, 0x1b, 0x1a, 0x8b, 0x16, 0x4d, 0xdf, 0x05, 0x32, 0xfe, 0xa4, 0x4c, 0x46, 0x49, 0xb7, 0x7b,
+ 0x6b, 0x75, 0xf9, 0x2b, 0x5c, 0x37, 0x29, 0x0b, 0x91, 0x37, 0x01, 0x37, 0x0e, 0xe9, 0xf2, 0xe1,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"ZWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+static int DetectEngineHttpServerBodyFileDataTest29(void)
+{
+ char input[] = "\
+%YAML 1.1\n\
+---\n\
+libhtp:\n\
+\n\
+ default-config:\n\
+\n\
+ swf-decompression:\n\
+ enabled: yes\n\
+ type: both\n\
+ compress-depth: 1000\n\
+ decompress-depth: 0\n\
+";
+
+ ConfCreateContextBackup();
+ ConfInit();
+ HtpConfigCreateBackup();
+ ConfYamlLoadString(input, strlen(input));
+ HTPConfigure();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /file.swf HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = {
+ 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ', '2', '0', '0', 'o', 'k', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'L', 'e', 'n', 'g', 't', 'h', ':', ' ', '8', '0', 0x0d, 0x0a,
+ 'C', 'o', 'n', 't', 'e', 'n', 't', '-', 'T', 'y', 'p', 'e', ':', ' ',
+ 'a','p','p','l','i','c','a','t','i','o','n','/','x','-','s','h','o','c','k','w','a','v','e','-','f','l','a','s','h', 0x0d, 0x0a,
+ 0x0d, 0x0a,
+ 0x43, 0x57, 0x53, 0x0a, 0xcb, 0x6c, 0x00, 0x00, 0x78, 0xda, 0xad, 0xbd, 0x07, 0x98, 0x55, 0x55,
+ 0x9e, 0xee, 0xbd, 0x4f, 0xd8, 0xb5, 0x4e, 0x15, 0xc1, 0xc2, 0x80, 0x28, 0x86, 0xd2, 0x2e, 0x5a,
+ 0xdb, 0x46, 0xd9, 0x39, 0x38, 0xdd, 0x4e, 0x1b, 0xa8, 0x56, 0x5b, 0xc5, 0x6b, 0xe8, 0x76, 0xfa,
+ 0x0e, 0xc2, 0x8e, 0x50, 0x76, 0x51, 0xc5, 0x54, 0x15, 0x88, 0x73, 0xc3, 0xd0, 0x88, 0x39, 0x81,
+ 0x98, 0x63, 0x91, 0x93, 0x8a, 0x82, 0x89, 0x60, 0x00, 0xcc, 0xb1, 0x00, 0x01, 0x73, 0xce, 0x39,
+ };
+ uint32_t http_len2 = sizeof(http_buf2);
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any "
+ "(flow:established,from_server; "
+ "file_data; content:\"FWS\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ FAIL_IF(r != 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF((PacketAlertCheck(p1, 1)));
+
+ r = AppLayerParserParse(
+ &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF(!(PacketAlertCheck(p2, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ HTPFreeConfig();
+ HtpConfigRestoreBackup();
+ ConfRestoreContextBackup();
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyTest06(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "message";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"message\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOSERVER | STREAM_START | STREAM_EOF, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOCLIENT | STREAM_START | STREAM_EOF, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "message";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"message\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched on chunk2 but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match on p2 (chunk3) but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"message\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sag";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ uint8_t http_buf4[] =
+ "e4u!!";
+ uint32_t http_len4 = sizeof(http_buf4) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"message\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf4, http_len4);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Case insensitive.
+ */
+static int DetectHttpServerBodyTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sag";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ uint8_t http_buf4[] =
+ "e4u!!";
+ uint32_t http_len4 = sizeof(http_buf4) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:\"MeSSaGE\"; http_server_body; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf4, http_len4);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Negated match.
+ */
+static int DetectHttpServerBodyTest11(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "bigmessage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:!\"MaSSaGE\"; http_server_body; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have (p1): ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have (p2): ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Negated match.
+ */
+static int DetectHttpServerBodyTest12(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "bigmessage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "content:!\"MeSSaGE\"; http_server_body; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have (p1): ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have (p2): ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectHttpServerBodyTest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 55\r\n"
+ "\r\n"
+ "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "content:\"longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\"; http_server_body; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOSERVER | STREAM_START | STREAM_EOF, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOCLIENT | STREAM_START | STREAM_EOF, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test multiple http transactions and body chunks of request handling */
+static int DetectHttpServerBodyTest14(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "GET /index1.html HTTP/1.1\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy1\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint8_t httpbuf2[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "one";
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint8_t httpbuf3[] = "GET /index2.html HTTP/1.1\r\n"
+ "User-Agent: Firefox/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy2\r\n\r\n";
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "two";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; content:\"one\"; http_server_body; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; content:\"two\"; http_server_body; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SCLogDebug("add chunk 1");
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ SCLogDebug("add chunk 2");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ SCLogDebug("inspect chunk 1");
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert (tx 1): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ SCLogDebug("add chunk 3");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ SCLogDebug("add chunk 4");
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ SCLogDebug("inspect chunk 4");
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1))) {
+ printf("sig 1 alerted (tx 2): ");
+ goto end;
+ }
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("sig 2 didn't alert (tx 2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+static int DetectHttpServerBodyTest15(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "GET /index1.html HTTP/1.1\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy1\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint8_t httpbuf2[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "one";
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint8_t httpbuf3[] = "GET /index2.html HTTP/1.1\r\n"
+ "User-Agent: Firefox/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy2\r\n\r\n";
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "two";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; content:\"one\"; http_server_body; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; content:\"two\"; http_server_body; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert (tx 1): ");
+ goto end;
+ }
+ if (PacketAlertCheck(p, 2)) {
+ printf("sig 2 alerted (tx 1): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1))) {
+ printf("sig 1 alerted (tx 2): ");
+ goto end;
+ }
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("sig 2 didn't alert (tx 2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyFileDataTest01(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "message";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "file_data; content:\"message\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOSERVER | STREAM_START | STREAM_EOF, http_buf, http_len);
+ FAIL_IF(r != 0);
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOCLIENT | STREAM_START | STREAM_EOF, http_buf2, http_len2);
+ FAIL_IF(r != 0);
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ FAIL_IF(!(PacketAlertCheck(p, 1)));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyFileDataTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "message";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "file_data; content:\"message\"; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched on p1 but should have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match on p2 but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyFileDataTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "file_data; content:\"message\"; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpServerBodyFileDataTest04(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sag";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ uint8_t http_buf4[] =
+ "e4u!!";
+ uint32_t http_len4 = sizeof(http_buf4) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "file_data; content:\"message\"; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf4, http_len4);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Case insensitive.
+ */
+static int DetectHttpServerBodyFileDataTest05(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n"
+ "bigmes";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "sag";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ uint8_t http_buf4[] =
+ "e4u!!";
+ uint32_t http_len4 = sizeof(http_buf4) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http client body test\"; "
+ "file_data; content:\"MeSSaGE\"; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf4, http_len4);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Negated match.
+ */
+static int DetectHttpServerBodyFileDataTest06(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "bigmessage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http file_data test\"; "
+ "file_data; content:!\"MaSSaGE\"; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have (p1): ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have (p2): ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ *\test Test that the http_server_body content matches against a http request
+ * which holds the content. Negated match.
+ */
+static int DetectHttpServerBodyFileDataTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 14\r\n"
+ "\r\n";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "bigmessage4u!!";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http file_data test\"; "
+ "file_data; content:!\"MeSSaGE\"; nocase; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
+ http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
+ http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have (p1): ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have (p2): ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectHttpServerBodyFileDataTest08(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 55\r\n"
+ "\r\n"
+ "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http server body test\"; "
+ "file_data; content:\"longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\"; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOSERVER | STREAM_START | STREAM_EOF, http_buf, http_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1,
+ STREAM_TOCLIENT | STREAM_START | STREAM_EOF, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ 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;
+ }
+
+ result = 1;
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test multiple http transactions and body chunks of request handling */
+static int DetectHttpServerBodyFileDataTest09(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "GET /index1.html HTTP/1.1\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy1\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint8_t httpbuf2[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "one";
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint8_t httpbuf3[] = "GET /index2.html HTTP/1.1\r\n"
+ "User-Agent: Firefox/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy2\r\n\r\n";
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "two";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; file_data; content:\"one\"; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; file_data; content:\"two\"; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert (tx 1): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1))) {
+ printf("sig 1 alerted (tx 2): ");
+ goto end;
+ }
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("sig 2 didn't alert (tx 2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+static int DetectHttpServerBodyFileDataTest10(void)
+{
+ int result = 0;
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "GET /index1.html HTTP/1.1\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy1\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint8_t httpbuf2[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "one";
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint8_t httpbuf3[] = "GET /index2.html HTTP/1.1\r\n"
+ "User-Agent: Firefox/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Connection: keep-alive\r\n"
+ "Cookie: dummy2\r\n\r\n";
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "HTTP/1.1 200 ok\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 3\r\n"
+ "\r\n"
+ "two";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ 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_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; file_data; content:\"one\"; sid:1; rev:1;)");
+ if (s == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:established,to_client; file_data; content:\"two\"; sid:2; rev:1;)");
+ if (s == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!(PacketAlertCheck(p, 1))) {
+ printf("sig 1 didn't alert (tx 1): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ if (r != 0) {
+ printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, httpbuf4, httplen4);
+ if (r != 0) {
+ printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if ((PacketAlertCheck(p, 1))) {
+ printf("sig 1 alerted (tx 2): ");
+ goto end;
+ }
+ if (!(PacketAlertCheck(p, 2))) {
+ printf("sig 2 didn't alert (tx 2): ");
+ goto end;
+ }
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ if (htp_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ if (AppLayerParserGetTxCnt(&f, htp_state) != 2) {
+ printf("The http app layer doesn't have 2 transactions, but it should: ");
+ 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);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ return result;
+}
+
+void DetectHttpServerBodyRegisterTests(void)
+{
+ UtRegisterTest("DetectHttpServerBodyParserTest01", DetectHttpServerBodyParserTest01);
+ UtRegisterTest("DetectHttpServerBodyParserTest02", DetectHttpServerBodyParserTest02);
+
+ UtRegisterTest("DetectHttpServerBodyTest06", DetectHttpServerBodyTest06);
+ UtRegisterTest("DetectHttpServerBodyTest07", DetectHttpServerBodyTest07);
+ UtRegisterTest("DetectHttpServerBodyTest08", DetectHttpServerBodyTest08);
+ UtRegisterTest("DetectHttpServerBodyTest09", DetectHttpServerBodyTest09);
+ UtRegisterTest("DetectHttpServerBodyTest10", DetectHttpServerBodyTest10);
+ UtRegisterTest("DetectHttpServerBodyTest11", DetectHttpServerBodyTest11);
+ UtRegisterTest("DetectHttpServerBodyTest12", DetectHttpServerBodyTest12);
+ UtRegisterTest("DetectHttpServerBodyTest13", DetectHttpServerBodyTest13);
+ UtRegisterTest("DetectHttpServerBodyTest14", DetectHttpServerBodyTest14);
+ UtRegisterTest("DetectHttpServerBodyTest15", DetectHttpServerBodyTest15);
+
+ UtRegisterTest("DetectHttpServerBodyFileDataTest01",
+ DetectHttpServerBodyFileDataTest01);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest02",
+ DetectHttpServerBodyFileDataTest02);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest03",
+ DetectHttpServerBodyFileDataTest03);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest04",
+ DetectHttpServerBodyFileDataTest04);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest05",
+ DetectHttpServerBodyFileDataTest05);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest06",
+ DetectHttpServerBodyFileDataTest06);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest07",
+ DetectHttpServerBodyFileDataTest07);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest08",
+ DetectHttpServerBodyFileDataTest08);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest09",
+ DetectHttpServerBodyFileDataTest09);
+ UtRegisterTest("DetectHttpServerBodyFileDataTest10",
+ DetectHttpServerBodyFileDataTest10);
+
+ UtRegisterTest("DetectEngineHttpServerBodyTest01",
+ DetectEngineHttpServerBodyTest01);
+ UtRegisterTest("DetectEngineHttpServerBodyTest02",
+ DetectEngineHttpServerBodyTest02);
+ UtRegisterTest("DetectEngineHttpServerBodyTest03",
+ DetectEngineHttpServerBodyTest03);
+ UtRegisterTest("DetectEngineHttpServerBodyTest04",
+ DetectEngineHttpServerBodyTest04);
+ UtRegisterTest("DetectEngineHttpServerBodyTest05",
+ DetectEngineHttpServerBodyTest05);
+ UtRegisterTest("DetectEngineHttpServerBodyTest06",
+ DetectEngineHttpServerBodyTest06);
+ UtRegisterTest("DetectEngineHttpServerBodyTest07",
+ DetectEngineHttpServerBodyTest07);
+ UtRegisterTest("DetectEngineHttpServerBodyTest08",
+ DetectEngineHttpServerBodyTest08);
+ UtRegisterTest("DetectEngineHttpServerBodyTest09",
+ DetectEngineHttpServerBodyTest09);
+ UtRegisterTest("DetectEngineHttpServerBodyTest10",
+ DetectEngineHttpServerBodyTest10);
+ UtRegisterTest("DetectEngineHttpServerBodyTest11",
+ DetectEngineHttpServerBodyTest11);
+ UtRegisterTest("DetectEngineHttpServerBodyTest12",
+ DetectEngineHttpServerBodyTest12);
+ UtRegisterTest("DetectEngineHttpServerBodyTest13",
+ DetectEngineHttpServerBodyTest13);
+ UtRegisterTest("DetectEngineHttpServerBodyTest14",
+ DetectEngineHttpServerBodyTest14);
+ UtRegisterTest("DetectEngineHttpServerBodyTest15",
+ DetectEngineHttpServerBodyTest15);
+ UtRegisterTest("DetectEngineHttpServerBodyTest16",
+ DetectEngineHttpServerBodyTest16);
+ UtRegisterTest("DetectEngineHttpServerBodyTest17",
+ DetectEngineHttpServerBodyTest17);
+ UtRegisterTest("DetectEngineHttpServerBodyTest18",
+ DetectEngineHttpServerBodyTest18);
+ UtRegisterTest("DetectEngineHttpServerBodyTest19",
+ DetectEngineHttpServerBodyTest19);
+ UtRegisterTest("DetectEngineHttpServerBodyTest20",
+ DetectEngineHttpServerBodyTest20);
+ UtRegisterTest("DetectEngineHttpServerBodyTest21",
+ DetectEngineHttpServerBodyTest21);
+ UtRegisterTest("DetectEngineHttpServerBodyTest22",
+ DetectEngineHttpServerBodyTest22);
+
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest01",
+ DetectEngineHttpServerBodyFileDataTest01);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest02",
+ DetectEngineHttpServerBodyFileDataTest02);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest03",
+ DetectEngineHttpServerBodyFileDataTest03);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest04",
+ DetectEngineHttpServerBodyFileDataTest04);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest05",
+ DetectEngineHttpServerBodyFileDataTest05);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest06",
+ DetectEngineHttpServerBodyFileDataTest06);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest07",
+ DetectEngineHttpServerBodyFileDataTest07);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest08",
+ DetectEngineHttpServerBodyFileDataTest08);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest09",
+ DetectEngineHttpServerBodyFileDataTest09);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest10",
+ DetectEngineHttpServerBodyFileDataTest10);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest11",
+ DetectEngineHttpServerBodyFileDataTest11);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest12",
+ DetectEngineHttpServerBodyFileDataTest12);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest13",
+ DetectEngineHttpServerBodyFileDataTest13);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest14",
+ DetectEngineHttpServerBodyFileDataTest14);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest15",
+ DetectEngineHttpServerBodyFileDataTest15);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest16",
+ DetectEngineHttpServerBodyFileDataTest16);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest17",
+ DetectEngineHttpServerBodyFileDataTest17);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest18",
+ DetectEngineHttpServerBodyFileDataTest18);
+
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest19",
+ DetectEngineHttpServerBodyFileDataTest19);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest20",
+ DetectEngineHttpServerBodyFileDataTest20);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest21",
+ DetectEngineHttpServerBodyFileDataTest21);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest22",
+ DetectEngineHttpServerBodyFileDataTest22);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest23",
+ DetectEngineHttpServerBodyFileDataTest23);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest24",
+ DetectEngineHttpServerBodyFileDataTest24);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest25",
+ DetectEngineHttpServerBodyFileDataTest25);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest26",
+ DetectEngineHttpServerBodyFileDataTest26);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest27",
+ DetectEngineHttpServerBodyFileDataTest27);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest28",
+ DetectEngineHttpServerBodyFileDataTest28);
+ UtRegisterTest("DetectEngineHttpServerBodyFileDataTest29",
+ DetectEngineHttpServerBodyFileDataTest29);
+}
diff --git a/src/tests/detect-http-stat-code.c b/src/tests/detect-http-stat-code.c
new file mode 100644
index 0000000..25a7115
--- /dev/null
+++ b/src/tests/detect-http-stat-code.c
@@ -0,0 +1,2324 @@
+/* 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+/**
+ * \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#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"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+static int DetectEngineHttpStatCodeTest01(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 message\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "message";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"200\"; http_stat_code; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 2000123 xxxxABC\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "xxxxABC";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"123\"; http_stat_code; offset:4; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ int result = 0;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 123";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "456789\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 17\r\n"
+ "\r\n"
+ "12345678901234ABC";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"789\"; http_stat_code; offset:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest04(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:!\"200\"; http_stat_code; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest05(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"200\"; http_stat_code; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest06(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:!\"123\"; http_stat_code; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:!\"123\"; http_stat_code; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:!\"200\"; http_stat_code; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"200\"; http_stat_code; depth:3; "
+ "content:\"123\"; http_stat_code; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"200\"; http_stat_code; depth:3; "
+ "content:!\"124\"; http_stat_code; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest11(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"200\"; http_stat_code; depth:3; "
+ "content:\"124\"; http_stat_code; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did match but should not have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest12(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"20\"; http_stat_code; depth:2; "
+ "content:\"23\"; http_stat_code; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest13(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "content:\"20\"; http_stat_code; depth:3; "
+ "content:!\"25\"; http_stat_code; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest14(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "pcre:/20/S; "
+ "content:\"23\"; http_stat_code; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatCodeTest15(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200123 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat code test\"; "
+ "pcre:/200/S; "
+ "content:!\"124\"; http_stat_code; distance:0; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ 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_HTTP1;
+
+ 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);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ 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_HTTP1;
+
+ 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);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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_HTTP1;
+
+ 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);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 negation 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_HTTP1;
+
+ 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);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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",
+ DetectEngineHttpStatCodeTest02);
+ UtRegisterTest("DetectEngineHttpStatCodeTest03",
+ DetectEngineHttpStatCodeTest03);
+ UtRegisterTest("DetectEngineHttpStatCodeTest04",
+ DetectEngineHttpStatCodeTest04);
+ UtRegisterTest("DetectEngineHttpStatCodeTest05",
+ DetectEngineHttpStatCodeTest05);
+ UtRegisterTest("DetectEngineHttpStatCodeTest06",
+ DetectEngineHttpStatCodeTest06);
+ UtRegisterTest("DetectEngineHttpStatCodeTest07",
+ DetectEngineHttpStatCodeTest07);
+ UtRegisterTest("DetectEngineHttpStatCodeTest08",
+ DetectEngineHttpStatCodeTest08);
+ UtRegisterTest("DetectEngineHttpStatCodeTest09",
+ DetectEngineHttpStatCodeTest09);
+ UtRegisterTest("DetectEngineHttpStatCodeTest10",
+ DetectEngineHttpStatCodeTest10);
+ UtRegisterTest("DetectEngineHttpStatCodeTest11",
+ DetectEngineHttpStatCodeTest11);
+ UtRegisterTest("DetectEngineHttpStatCodeTest12",
+ DetectEngineHttpStatCodeTest12);
+ UtRegisterTest("DetectEngineHttpStatCodeTest13",
+ DetectEngineHttpStatCodeTest13);
+ UtRegisterTest("DetectEngineHttpStatCodeTest14",
+ DetectEngineHttpStatCodeTest14);
+ UtRegisterTest("DetectEngineHttpStatCodeTest15",
+ DetectEngineHttpStatCodeTest15);
+
+ UtRegisterTest("DetectHttpStatCodeSigTest01", DetectHttpStatCodeSigTest01);
+ UtRegisterTest("DetectHttpStatCodeSigTest02", DetectHttpStatCodeSigTest02);
+ UtRegisterTest("DetectHttpStatCodeSigTest03", DetectHttpStatCodeSigTest03);
+ UtRegisterTest("DetectHttpStatCodeSigTest04", DetectHttpStatCodeSigTest04);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-stat-msg.c b/src/tests/detect-http-stat-msg.c
new file mode 100644
index 0000000..60251ec
--- /dev/null
+++ b/src/tests/detect-http-stat-msg.c
@@ -0,0 +1,2213 @@
+/* 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+/**
+ * \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#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"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+static int DetectEngineHttpStatMsgTest01(void)
+ {
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 message\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "message";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"message\"; http_stat_msg; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 xxxxABC\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 7\r\n"
+ "\r\n"
+ "xxxxABC";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOCLIENT;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"ABC\"; http_stat_msg; offset:4; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ int result = 0;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 1234567";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ uint8_t http_buf3[] =
+ "8901234ABC\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 17\r\n"
+ "\r\n"
+ "12345678901234ABC";
+ uint32_t http_len3 = sizeof(http_buf3) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"ABC\"; http_stat_msg; offset:14; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf3, http_len3);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest04(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:!\"abc\"; http_stat_msg; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest05(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"abc\"; http_stat_msg; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest06(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:!\"def\"; http_stat_msg; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:!\"def\"; http_stat_msg; offset:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:!\"abc\"; http_stat_msg; depth:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"abc\"; http_stat_msg; depth:3; "
+ "content:\"def\"; http_stat_msg; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"abc\"; http_stat_msg; depth:3; "
+ "content:!\"xyz\"; http_stat_msg; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest11(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"abc\"; http_stat_msg; depth:3; "
+ "content:\"xyz\"; http_stat_msg; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did match but should not have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest12(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"ab\"; http_stat_msg; depth:2; "
+ "content:\"ef\"; http_stat_msg; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest13(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "content:\"ab\"; http_stat_msg; depth:3; "
+ "content:!\"yz\"; http_stat_msg; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest14(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "pcre:/ab/Y; "
+ "content:\"ef\"; http_stat_msg; distance:2; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpStatMsgTest15(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http_buf1[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "\r\n";
+ uint32_t http_len1 = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] =
+ "HTTP/1.0 200 abcdef\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 6\r\n"
+ "\r\n"
+ "abcdef";
+ uint32_t http_len2 = sizeof(http_buf2) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http stat msg test\"; "
+ "pcre:/abc/Y; "
+ "content:!\"xyz\"; http_stat_msg; distance:0; within:3; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, http_buf2, http_len2);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 did not match but should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/** \test Check the signature working to alert when http_stat_msg is matched . */
+static int DetectHttpStatMsgSigTest01(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_HTTP1;
+
+ 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 message\"; content:\"OK\"; "
+ "http_stat_msg; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+ "Status message nocase\"; content:\"ok\"; nocase; "
+ "http_stat_msg; sid:2;)");
+ if (s->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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_msg is not matched . */
+static int DetectHttpStatMsgSigTest02(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_HTTP1;
+
+ 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 message\"; content:\"no\"; "
+ "http_stat_msg; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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;
+ }
+
+ 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_msg is used with
+ * negated content . */
+static int DetectHttpStatMsgSigTest03(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_HTTP1;
+
+ 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 message\"; content:\"ok\"; "
+ "nocase; http_stat_msg; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
+ "Status message nocase\"; content:!\"Not\"; "
+ "http_stat_msg; sid:2;)");
+ if (s->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
+ if (r != 0) {
+ printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ 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 matched but should have: ");
+ goto end;
+ }
+ if (! PacketAlertCheck(p, 2)) {
+ printf("sid 2 didn't matched 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_msg keyword
+ */
+void DetectHttpStatMsgRegisterTests (void)
+{
+ UtRegisterTest("DetectHttpStatMsgSigTest01", DetectHttpStatMsgSigTest01);
+ UtRegisterTest("DetectHttpStatMsgSigTest02", DetectHttpStatMsgSigTest02);
+ UtRegisterTest("DetectHttpStatMsgSigTest03", DetectHttpStatMsgSigTest03);
+
+ UtRegisterTest("DetectEngineHttpStatMsgTest01",
+ DetectEngineHttpStatMsgTest01);
+ UtRegisterTest("DetectEngineHttpStatMsgTest02",
+ DetectEngineHttpStatMsgTest02);
+ UtRegisterTest("DetectEngineHttpStatMsgTest03",
+ DetectEngineHttpStatMsgTest03);
+ UtRegisterTest("DetectEngineHttpStatMsgTest04",
+ DetectEngineHttpStatMsgTest04);
+ UtRegisterTest("DetectEngineHttpStatMsgTest05",
+ DetectEngineHttpStatMsgTest05);
+ UtRegisterTest("DetectEngineHttpStatMsgTest06",
+ DetectEngineHttpStatMsgTest06);
+ UtRegisterTest("DetectEngineHttpStatMsgTest07",
+ DetectEngineHttpStatMsgTest07);
+ UtRegisterTest("DetectEngineHttpStatMsgTest08",
+ DetectEngineHttpStatMsgTest08);
+ UtRegisterTest("DetectEngineHttpStatMsgTest09",
+ DetectEngineHttpStatMsgTest09);
+ UtRegisterTest("DetectEngineHttpStatMsgTest10",
+ DetectEngineHttpStatMsgTest10);
+ UtRegisterTest("DetectEngineHttpStatMsgTest11",
+ DetectEngineHttpStatMsgTest11);
+ UtRegisterTest("DetectEngineHttpStatMsgTest12",
+ DetectEngineHttpStatMsgTest12);
+ UtRegisterTest("DetectEngineHttpStatMsgTest13",
+ DetectEngineHttpStatMsgTest13);
+ UtRegisterTest("DetectEngineHttpStatMsgTest14",
+ DetectEngineHttpStatMsgTest14);
+ UtRegisterTest("DetectEngineHttpStatMsgTest15",
+ DetectEngineHttpStatMsgTest15);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http-uri.c b/src/tests/detect-http-uri.c
new file mode 100644
index 0000000..f167be4
--- /dev/null
+++ b/src/tests/detect-http-uri.c
@@ -0,0 +1,6920 @@
+/* Copyright (C) 2007-2018 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 Victor Julien <victor@inliniac.net>
+ * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
+ */
+
+#include "../suricata-common.h"
+#include "../app-layer.h"
+#include "../app-layer-parser.h"
+#include "../app-layer-htp.h"
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+
+#include "../flow.h"
+#include "../flow-util.h"
+
+#include "../detect-isdataat.h"
+#include "../detect-engine-build.h"
+#include "../detect-engine-alert.h"
+
+/** \test Test a simple uricontent option */
+static int UriTestSig01(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test uricontent option\"; "
+ "uricontent:\"one\"; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ if (!PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted, but it should not: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option */
+static int UriTestSig02(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /on HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option\"; "
+ "pcre:/one/U; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted with payload2, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option */
+static int UriTestSig03(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option\"; "
+ "pcre:/blah/U; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the urilen option */
+static int UriTestSig04(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test urilen option\"; "
+ "urilen:>20; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the urilen option */
+static int UriTestSig05(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test urilen option\"; "
+ "urilen:>4; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option */
+static int UriTestSig06(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option\"; "
+ "pcre:/(oneself)+/U; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert on payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option in combination with urilen */
+static int UriTestSig07(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option with urilen \"; "
+ "pcre:/(one){2,}(self)?/U; urilen:3<>20; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert, but it should: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option in combination with urilen */
+static int UriTestSig08(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option with urilen\"; "
+ "pcre:/(blabla){2,}(self)?/U; urilen:3<>20; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test the pcre /U option in combination with urilen */
+static int UriTestSig09(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U option with urilen \"; "
+ "pcre:/(one){2,}(self)?/U; urilen:<2; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test uricontent, urilen, pcre /U options */
+static int UriTestSig12(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /oneoneoneone HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneoneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test pcre /U, uricontent and urilen option\"; "
+ "uricontent:\"one\"; "
+ "pcre:/(one)+self/U; urilen:>2; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test uricontent, urilen */
+static int UriTestSig13(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test urilen option\"; "
+ "urilen:>2; uricontent:\"one\"; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with pkt, but it should: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test uricontent, pcre /U */
+static int UriTestSig14(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test uricontent option\"; "
+ "uricontent:\"one\"; pcre:/one(self)?/U;sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with pkt, but it should: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test pcre /U with anchored regex (bug 155) */
+static int UriTestSig15(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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 tcp any any -> any any "
+ "(msg:\"Test uricontent option\"; "
+ "uricontent:\"one\"; pcre:/^\\/one(self)?$/U;sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with pkt, but it should: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 didnt alert with payload2, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/** \test Test pcre /U with anchored regex (bug 155) */
+static int UriTestSig16(void)
+{
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /search?q=123&aq=7123abcee HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0/\r\n"
+ "Host: 1.2.3.4\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ uint8_t http_buf2[] = "POST /search?q=123&aq=7123abcee HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf2) - 1;
+ TcpSession ssn;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+ StreamTcpInitConfig(true);
+
+ Packet *p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+ p->tcph->th_seq = htonl(1000);
+ Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1", 41424, 80);
+ FAIL_IF_NULL(f);
+ f->proto = IPPROTO_TCP;
+
+ UTHAddSessionToFlow(f, 1000, 1000);
+ UTHAddStreamToFlow(f, 0, http_buf1, http_buf1_len);
+
+ p->flow = f;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST | PKT_DETECT_HAS_STREAMDATA;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f->alproto = ALPROTO_HTTP1;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any any (flow:to_server,established; uricontent:\"/search?q=\"; pcre:\"/^\\/search\\?q=[0-9]{1,3}(&aq=7(\\?[0-9a-f]{8})?)?/U\"; pcre:\"/\\x0d\\x0aHost\\: \\d+\\.\\d+\\.\\d+\\.\\d+\\x0d\\x0a/\"; sid:2009024; rev:9;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ UTHAddStreamToFlow(f, 0, http_buf2, http_buf2_len);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ FAIL_IF(r != 0);
+
+ http_state = f->alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+ FAIL_IF(!PacketAlertCheck(p, 2009024));
+ p->alerts.cnt = 0;
+
+ p->payload = http_buf2;
+ p->payload_len = http_buf2_len;
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ FAIL_IF(r != 0);
+
+ http_state = f->alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 2009024));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ UTHRemoveSessionFromFlow(f);
+ UTHFreeFlow(f);
+
+ StreamTcpFreeConfig(true);
+ UTHFreePacket(p);
+ PASS;
+}
+
+/**
+ * \test Test multiple relative contents
+ */
+static int UriTestSig17(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /now_this_is_is_big_big_string_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"this\"; uricontent:\"is\"; within:6; "
+ "uricontent:\"big\"; within:8; "
+ "uricontent:\"string\"; within:8; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents
+ */
+static int UriTestSig18(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /now_this_is_is_is_big_big_big_string_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"this\"; uricontent:\"is\"; within:9; "
+ "uricontent:\"big\"; within:12; "
+ "uricontent:\"string\"; within:8; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents
+ */
+static int UriTestSig19(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /this_this_now_is_is_____big_string_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"now\"; uricontent:\"this\"; "
+ "uricontent:\"is\"; within:12; "
+ "uricontent:\"big\"; within:8; "
+ "uricontent:\"string\"; within:8; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with offset
+ */
+static int UriTestSig20(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /_________thus_thus_is_a_big 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"thus\"; offset:8; "
+ "uricontent:\"is\"; within:6; "
+ "uricontent:\"big\"; within:8; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int UriTestSig21(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"fix\"; uricontent:\"this\"; within:6; "
+ "uricontent:!\"and\"; distance:0; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test relative pcre.
+ */
+static int UriTestSig22(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /this_is_a_super_duper_"
+ "nova_in_super_nova_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "pcre:/super/U; uricontent:\"nova\"; within:7; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int UriTestSig23(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:!\"fix_this_now\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int UriTestSig24(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"we_need_to\"; uricontent:!\"fix_this_now\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it should not: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test normalized uricontents.
+ */
+static int UriTestSig25(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "pcre:/normalized/U; uricontent:\"normalized uri\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int UriTestSig26(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"fix_this\"; isdataat:4,relative; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int UriTestSig27(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "uricontent:\"fix_this\"; isdataat:!10,relative; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any (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 = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any (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 = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any (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 = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any (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 = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any (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 = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig33(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:15; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig34(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:15, norm; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig35(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:16; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig36(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:16, norm; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig37(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:17, raw; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 UriTestSig38(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /normalized%20uri "
+ "HTTP/1.0\r\nUser-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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative uricontents\"; "
+ "urilen:18, raw; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 alerted, but it shouldn't have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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 DetectHttpUriIsdataatParseTest(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any ("
+ "content:\"one\"; http_uri; "
+ "isdataat:!4,relative; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigMatch *sm = DetectBufferGetLastSigMatch(s, g_http_uri_buffer_id);
+ FAIL_IF_NULL(sm);
+ FAIL_IF_NOT(sm->type == DETECT_ISDATAAT);
+
+ DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
+ FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
+ FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
+ FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+static int DetectEngineHttpRawUriTest01(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/../c";
+ uint8_t http2_buf[] =
+ "/./d.html HTTP/1.1\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"../c/./d\"; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if ((PacketAlertCheck(p1, 1))) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!(PacketAlertCheck(p2, 1))) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest02(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 19\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"/c/./d\"; http_raw_uri; offset:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match but should have\n");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest03(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/../";
+ uint8_t http2_buf[] =
+ "c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"/a/b\"; http_raw_uri; offset:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest04(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/../";
+ uint8_t http2_buf[] =
+ "c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:!\"/a/b\"; http_raw_uri; offset:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest05(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/";
+ uint8_t http2_buf[] =
+ "../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"a/b\"; http_raw_uri; depth:10; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest06(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/";
+ uint8_t http2_buf[] =
+ "../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:!\"/a/b\"; http_raw_uri; depth:25; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/b/";
+ uint8_t http2_buf[] =
+ "../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:!\"/c/./d\"; http_raw_uri; depth:12; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a/";
+ uint8_t http2_buf[] =
+ "b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:!\"/c/./d\"; http_raw_uri; depth:18; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"/a\"; http_raw_uri; "
+ "content:\"./c/.\"; http_raw_uri; within:9; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"/a\"; http_raw_uri; "
+ "content:!\"boom\"; http_raw_uri; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest11(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:\"boom\"; http_raw_uri; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest12(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:!\"/b/..\"; http_raw_uri; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest13(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:\"/c/.\"; http_raw_uri; distance:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest14(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:!\"b/..\"; http_raw_uri; distance:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest15(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:\"/c/\"; http_raw_uri; distance:7; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest16(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "content:\"./a\"; http_raw_uri; "
+ "content:!\"/c/\"; http_raw_uri; distance:4; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest21(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:!\"/c/\"; http_raw_uri; within:5; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest22(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:!\"/c/\"; within:5; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest23(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:!\"/c/\"; distance:3; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest24(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:!\"/c/\"; distance:10; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest25(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:\"/c/\"; within:10; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest26(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:\"/c/\"; within:5; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest27(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:\"/c/\"; distance:5; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (!PacketAlertCheck(p2, 1)) {
+ printf("sid 1 didn't match but should have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+static int DetectEngineHttpRawUriTest28(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineCtx *de_ctx = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ HtpState *http_state = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /../a";
+ uint8_t http2_buf[] =
+ "/b/../c/./d.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1"
+ "This is dummy message body2";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL)
+ goto end;
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
+ "(msg:\"http raw uri test\"; "
+ "pcre:/\\.\\/a/I; "
+ "content:\"/c/\"; distance:10; http_raw_uri; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL)
+ goto end;
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: \n");
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 matched but shouldn't have\n");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
+ result = 0;
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sid 1 matched but shouldn't have");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ SigCleanSignatures(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ return result;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int DetectEngineHttpRawUriTest29(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /../a/b/../c/./d.html 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative raw uri contents\"; "
+ "content:\"/c/\"; http_raw_uri; "
+ "isdataat:4,relative; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \test Test multiple relative contents with a negated content.
+ */
+static int DetectEngineHttpRawUriTest30(void)
+{
+ int result = 0;
+ uint8_t *http_buf = (uint8_t *)"POST /../a/b/../c/./d.html 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;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ 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.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
+ "(msg:\"test multiple relative raw uri contents\"; "
+ "uricontent:\"/c/\"; isdataat:!10,relative; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_buf_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should have: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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;
+}
+
+/**
+ * \brief Register the UNITTESTS for the http_uri keyword
+ */
+static void DetectHttpUriRegisterTests (void)
+{
+ UtRegisterTest("UriTestSig01", UriTestSig01);
+ UtRegisterTest("UriTestSig02", UriTestSig02);
+ UtRegisterTest("UriTestSig03", UriTestSig03);
+ UtRegisterTest("UriTestSig04", UriTestSig04);
+ UtRegisterTest("UriTestSig05", UriTestSig05);
+ UtRegisterTest("UriTestSig06", UriTestSig06);
+ UtRegisterTest("UriTestSig07", UriTestSig07);
+ UtRegisterTest("UriTestSig08", UriTestSig08);
+ UtRegisterTest("UriTestSig09", UriTestSig09);
+ UtRegisterTest("UriTestSig12", UriTestSig12);
+ UtRegisterTest("UriTestSig13", UriTestSig13);
+ UtRegisterTest("UriTestSig14", UriTestSig14);
+ UtRegisterTest("UriTestSig15", UriTestSig15);
+ UtRegisterTest("UriTestSig16", UriTestSig16);
+ UtRegisterTest("UriTestSig17", UriTestSig17);
+ UtRegisterTest("UriTestSig18", UriTestSig18);
+ UtRegisterTest("UriTestSig19", UriTestSig19);
+ UtRegisterTest("UriTestSig20", UriTestSig20);
+ UtRegisterTest("UriTestSig21", UriTestSig21);
+ UtRegisterTest("UriTestSig22", UriTestSig22);
+ UtRegisterTest("UriTestSig23", UriTestSig23);
+ UtRegisterTest("UriTestSig24", UriTestSig24);
+ UtRegisterTest("UriTestSig25", UriTestSig25);
+ UtRegisterTest("UriTestSig26", UriTestSig26);
+ UtRegisterTest("UriTestSig27", UriTestSig27);
+
+ UtRegisterTest("UriTestSig28", UriTestSig28);
+ UtRegisterTest("UriTestSig29", UriTestSig29);
+ UtRegisterTest("UriTestSig30", UriTestSig30);
+ UtRegisterTest("UriTestSig31", UriTestSig31);
+ UtRegisterTest("UriTestSig32", UriTestSig32);
+ UtRegisterTest("UriTestSig33", UriTestSig33);
+ UtRegisterTest("UriTestSig34", UriTestSig34);
+ UtRegisterTest("UriTestSig35", UriTestSig35);
+ UtRegisterTest("UriTestSig36", UriTestSig36);
+ UtRegisterTest("UriTestSig37", UriTestSig37);
+ UtRegisterTest("UriTestSig38", UriTestSig38);
+
+ UtRegisterTest("DetectHttpUriIsdataatParseTest",
+ DetectHttpUriIsdataatParseTest);
+
+ UtRegisterTest("DetectEngineHttpRawUriTest01",
+ DetectEngineHttpRawUriTest01);
+ UtRegisterTest("DetectEngineHttpRawUriTest02",
+ DetectEngineHttpRawUriTest02);
+ UtRegisterTest("DetectEngineHttpRawUriTest03",
+ DetectEngineHttpRawUriTest03);
+ UtRegisterTest("DetectEngineHttpRawUriTest04",
+ DetectEngineHttpRawUriTest04);
+ UtRegisterTest("DetectEngineHttpRawUriTest05",
+ DetectEngineHttpRawUriTest05);
+ UtRegisterTest("DetectEngineHttpRawUriTest06",
+ DetectEngineHttpRawUriTest06);
+ UtRegisterTest("DetectEngineHttpRawUriTest07",
+ DetectEngineHttpRawUriTest07);
+ UtRegisterTest("DetectEngineHttpRawUriTest08",
+ DetectEngineHttpRawUriTest08);
+ UtRegisterTest("DetectEngineHttpRawUriTest09",
+ DetectEngineHttpRawUriTest09);
+ UtRegisterTest("DetectEngineHttpRawUriTest10",
+ DetectEngineHttpRawUriTest10);
+ UtRegisterTest("DetectEngineHttpRawUriTest11",
+ DetectEngineHttpRawUriTest11);
+ UtRegisterTest("DetectEngineHttpRawUriTest12",
+ DetectEngineHttpRawUriTest12);
+ UtRegisterTest("DetectEngineHttpRawUriTest13",
+ DetectEngineHttpRawUriTest13);
+ UtRegisterTest("DetectEngineHttpRawUriTest14",
+ DetectEngineHttpRawUriTest14);
+ UtRegisterTest("DetectEngineHttpRawUriTest15",
+ DetectEngineHttpRawUriTest15);
+ UtRegisterTest("DetectEngineHttpRawUriTest16",
+ DetectEngineHttpRawUriTest16);
+ UtRegisterTest("DetectEngineHttpRawUriTest21",
+ DetectEngineHttpRawUriTest21);
+ UtRegisterTest("DetectEngineHttpRawUriTest22",
+ DetectEngineHttpRawUriTest22);
+ UtRegisterTest("DetectEngineHttpRawUriTest23",
+ DetectEngineHttpRawUriTest23);
+ UtRegisterTest("DetectEngineHttpRawUriTest24",
+ DetectEngineHttpRawUriTest24);
+ UtRegisterTest("DetectEngineHttpRawUriTest25",
+ DetectEngineHttpRawUriTest25);
+ UtRegisterTest("DetectEngineHttpRawUriTest26",
+ DetectEngineHttpRawUriTest26);
+ UtRegisterTest("DetectEngineHttpRawUriTest27",
+ DetectEngineHttpRawUriTest27);
+ UtRegisterTest("DetectEngineHttpRawUriTest28",
+ DetectEngineHttpRawUriTest28);
+ UtRegisterTest("DetectEngineHttpRawUriTest29",
+ DetectEngineHttpRawUriTest29);
+ UtRegisterTest("DetectEngineHttpRawUriTest30",
+ DetectEngineHttpRawUriTest30);
+}
diff --git a/src/tests/detect-http-user-agent.c b/src/tests/detect-http-user-agent.c
new file mode 100644
index 0000000..df9c9c1
--- /dev/null
+++ b/src/tests/detect-http-user-agent.c
@@ -0,0 +1,1221 @@
+/* Copyright (C) 2007-2021 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.
+ */
+
+/**
+ * \ingroup httplayer
+ *
+ * @{
+ */
+
+
+/** \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ * \brief Handle HTTP user agent match
+ *
+ */
+
+#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"
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+
+static int DetectEngineHttpUATest(
+ const uint8_t *buf, const uint32_t buf_len, const char *sig, const bool expect)
+{
+ TcpSession ssn;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, sig);
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buf_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ bool match = PacketAlertCheck(p, 1);
+ FAIL_IF_NOT(match == expect);
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+static int DetectEngineHttpUATest01(void)
+{
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CONNECT\"; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest02(void)
+{
+ uint8_t http_buf[] = "GET /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CO\"; depth:4; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest03(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http_user_agent test\"; "
+ "content:!\"ECT\"; depth:4; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest04(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"ECT\"; depth:4; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest05(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:!\"CON\"; depth:4; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest06(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"ECT\"; offset:3; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest07(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:!\"CO\"; offset:3; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest08(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:!\"ECT\"; offset:3; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest09(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CON\"; offset:3; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest10(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http_user_agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:\"EC\"; within:4; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest11(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:!\"EC\"; within:3; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest12(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http_user_agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:\"EC\"; within:3; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest13(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:!\"EC\"; within:4; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest14(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http_user_agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:\"EC\"; distance:2; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest15(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:!\"EC\"; distance:3; http_user_agent; "
+ "sid:1;)",
+ true);
+}
+
+static int DetectEngineHttpUATest16(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:\"EC\"; distance:3; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectEngineHttpUATest17(void)
+{
+ uint8_t http_buf[] = "CONNECT /index.html HTTP/1.0\r\n"
+ "User-Agent: CONNECT\r\n"
+ "Host: www.onetwothreefourfivesixseven.org\r\n\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ return DetectEngineHttpUATest(http_buf, http_len,
+ "alert http any any -> any any "
+ "(msg:\"http_user_agent test\"; "
+ "content:\"CO\"; http_user_agent; "
+ "content:!\"EC\"; distance:2; http_user_agent; "
+ "sid:1;)",
+ false);
+}
+
+static int DetectHttpUATestSigParse(const char *sig, const bool expect)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, sig);
+ bool parsed = (s != NULL);
+ FAIL_IF_NOT(parsed == expect);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test that a signature containing a http_user_agent is correctly parsed
+ * and the keyword is registered.
+ */
+static int DetectHttpUATest01(void)
+{
+ return DetectHttpUATestSigParse("alert tcp any any -> any any "
+ "(msg:\"Testing http_user_agent\"; "
+ "content:\"one\"; http_user_agent; sid:1;)",
+ true);
+}
+
+/**
+ * \test Test that a signature containing an valid http_user_agent entry is
+ * parsed.
+ */
+static int DetectHttpUATest02(void)
+{
+ return DetectHttpUATestSigParse("alert tcp any any -> any any "
+ "(msg:\"Testing http_user_agent\"; "
+ "content:\"one\"; http_user_agent:; sid:1;)",
+ true);
+}
+
+/**
+ * \test Test that an invalid signature containing no content but a
+ * http_user_agent is invalidated.
+ */
+static int DetectHttpUATest03(void)
+{
+ return DetectHttpUATestSigParse("alert tcp any any -> any any "
+ "(msg:\"Testing http_user_agent\"; "
+ "http_user_agent; sid:1;)",
+ false);
+}
+
+/**
+ * \test Test that an invalid signature containing a rawbytes along with a
+ * http_user_agent is invalidated.
+ */
+static int DetectHttpUATest04(void)
+{
+ return DetectHttpUATestSigParse("alert tcp any any -> any any "
+ "(msg:\"Testing http_user_agent\"; "
+ "content:\"one\"; rawbytes; http_user_agent; sid:1;)",
+ false);
+}
+
+/**
+ * \test Test that a http_user_agent with nocase is parsed.
+ */
+static int DetectHttpUATest05(void)
+{
+ return DetectHttpUATestSigParse("alert tcp any any -> any any "
+ "(msg:\"Testing http_user_agent\"; "
+ "content:\"one\"; http_user_agent; nocase; sid:1;)",
+ true);
+}
+
+/**
+ *\test Test that the http_user_agent content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpUATest06(void)
+{
+ TcpSession ssn;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"message\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_user_agent content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpUATest07(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy message";
+ uint8_t http2_buf[] =
+ "body1\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"message\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF_NOT(PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_user_agent content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpUATest08(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy mess";
+ uint8_t http2_buf[] =
+ "age body\r\n\r\n";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"message\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF_NOT(PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_user_agent content matches against a http request
+ * which holds the content, against a cross boundary present pattern.
+ */
+static int DetectHttpUATest09(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy body1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy body1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"body1This\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+
+ FAIL_IF_NOT(PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the http_user_agent content matches against a http request
+ * against a case insensitive pattern.
+ */
+static int DetectHttpUATest10(void)
+{
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http1_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy bodY1";
+ uint8_t http2_buf[] =
+ "This is dummy message body2\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 46\r\n"
+ "\r\n"
+ "This is dummy bodY1";
+ uint32_t http1_len = sizeof(http1_buf) - 1;
+ uint32_t http2_len = sizeof(http2_buf) - 1;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"body1this\"; http_user_agent; nocase;"
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http1_buf, http1_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http2_buf, http2_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF_NOT(PacketAlertCheck(p2, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ PASS;
+}
+
+/**
+ *\test Test that the negated http_user_agent content matches against a
+ * http request which doesn't hold the content.
+ */
+static int DetectHttpUATest11(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy message body\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:!\"message\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ FAIL_IF(PacketAlertCheck(p, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ *\test Negative test that the negated http_user_agent content matches against a
+ * http request which holds hold the content.
+ */
+static int DetectHttpUATest12(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: This is dummy body\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:!\"message\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ * \test Test that the http_user_agent content matches against a http request
+ * which holds the content.
+ */
+static int DetectHttpUATest13(void)
+{
+ TcpSession ssn;
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ uint8_t http_buf[] =
+ "GET /index.html HTTP/1.0\r\n"
+ "Host: www.openinfosecfoundation.org\r\n"
+ "User-Agent: longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n";
+ uint32_t http_len = sizeof(http_buf) - 1;
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any "
+ "(msg:\"http user agent test\"; "
+ "content:\"abcdefghijklmnopqrstuvwxyz0123456789\"; http_user_agent; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf, http_len);
+ FAIL_IF_NOT(r == 0);
+ FAIL_IF_NULL(f.alstate);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/**
+ * \test multiple http transactions and body chunks of request handling
+ */
+static int DetectHttpUATest14(void)
+{
+ Signature *s = NULL;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ ThreadVars th_v;
+ Flow f;
+ TcpSession ssn;
+ Packet *p = NULL;
+ uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
+ uint8_t httpbuf2[] = "Cookie: dummy1\r\n";
+ uint8_t httpbuf3[] = "User-Agent: Body one!!\r\n\r\n";
+ uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+ uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+ uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
+ uint8_t httpbuf4[] = "GET /?var=val HTTP/1.1\r\n";
+ uint8_t httpbuf5[] = "Cookie: dummy2\r\n";
+ uint8_t httpbuf6[] = "User-Agent: Body two\r\n\r\n";
+ uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
+ uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
+ uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy1\"; http_cookie; content:\"Body one\"; http_user_agent; sid:1; rev:1;)");
+ FAIL_IF_NULL(s);
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"dummy2\"; http_cookie; content:\"Body two\"; http_user_agent; sid:2; rev:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+ p->alerts.cnt = 0;
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+ FAIL_IF(PacketAlertCheck(p, 2));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+ FAIL_IF(PacketAlertCheck(p, 2));
+
+ SCLogDebug("sending data chunk 7");
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
+ FAIL_IF_NOT(r == 0);
+
+ /* do detect */
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+ FAIL_IF_NOT(PacketAlertCheck(p, 2));
+ p->alerts.cnt = 0;
+
+ HtpState *htp_state = f.alstate;
+ FAIL_IF_NULL(htp_state);
+ FAIL_IF_NOT(AppLayerParserGetTxCnt(&f, htp_state) == 2);
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+ PASS;
+}
+
+static void DetectHttpUARegisterTests(void)
+{
+ UtRegisterTest("DetectEngineHttpUATest01", DetectEngineHttpUATest01);
+ UtRegisterTest("DetectEngineHttpUATest02", DetectEngineHttpUATest02);
+ UtRegisterTest("DetectEngineHttpUATest03", DetectEngineHttpUATest03);
+ UtRegisterTest("DetectEngineHttpUATest04", DetectEngineHttpUATest04);
+ UtRegisterTest("DetectEngineHttpUATest05", DetectEngineHttpUATest05);
+ UtRegisterTest("DetectEngineHttpUATest06", DetectEngineHttpUATest06);
+ UtRegisterTest("DetectEngineHttpUATest07", DetectEngineHttpUATest07);
+ UtRegisterTest("DetectEngineHttpUATest08", DetectEngineHttpUATest08);
+ UtRegisterTest("DetectEngineHttpUATest09", DetectEngineHttpUATest09);
+ UtRegisterTest("DetectEngineHttpUATest10", DetectEngineHttpUATest10);
+ UtRegisterTest("DetectEngineHttpUATest11", DetectEngineHttpUATest11);
+ UtRegisterTest("DetectEngineHttpUATest12", DetectEngineHttpUATest12);
+ UtRegisterTest("DetectEngineHttpUATest13", DetectEngineHttpUATest13);
+ UtRegisterTest("DetectEngineHttpUATest14", DetectEngineHttpUATest14);
+ UtRegisterTest("DetectEngineHttpUATest15", DetectEngineHttpUATest15);
+ UtRegisterTest("DetectEngineHttpUATest16", DetectEngineHttpUATest16);
+ UtRegisterTest("DetectEngineHttpUATest17", DetectEngineHttpUATest17);
+
+ UtRegisterTest("DetectHttpUATest01", DetectHttpUATest01);
+ UtRegisterTest("DetectHttpUATest02", DetectHttpUATest02);
+ UtRegisterTest("DetectHttpUATest03", DetectHttpUATest03);
+ UtRegisterTest("DetectHttpUATest04", DetectHttpUATest04);
+ UtRegisterTest("DetectHttpUATest05", DetectHttpUATest05);
+ UtRegisterTest("DetectHttpUATest06", DetectHttpUATest06);
+ UtRegisterTest("DetectHttpUATest07", DetectHttpUATest07);
+ UtRegisterTest("DetectHttpUATest08", DetectHttpUATest08);
+ UtRegisterTest("DetectHttpUATest09", DetectHttpUATest09);
+ UtRegisterTest("DetectHttpUATest10", DetectHttpUATest10);
+ UtRegisterTest("DetectHttpUATest11", DetectHttpUATest11);
+ UtRegisterTest("DetectHttpUATest12", DetectHttpUATest12);
+ UtRegisterTest("DetectHttpUATest13", DetectHttpUATest13);
+ UtRegisterTest("DetectHttpUATest14", DetectHttpUATest14);
+}
+
+/**
+ * @}
+ */
diff --git a/src/tests/detect-http2.c b/src/tests/detect-http2.c
new file mode 100644
index 0000000..2ce1bd4
--- /dev/null
+++ b/src/tests/detect-http2.c
@@ -0,0 +1,161 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect-engine.h"
+
+#include "../detect-http2.h"
+
+#include "../util-unittest.h"
+
+/**
+ * \test signature with a valid http2.frametype value.
+ */
+
+static int DetectHTTP2frameTypeParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.frametype:GOAWAY; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectHTTP2frameType
+ */
+void DetectHTTP2frameTypeRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2frameTypeParseTest01", DetectHTTP2frameTypeParseTest01);
+}
+
+/**
+ * \test signature with a valid http2.errorcode value.
+ */
+
+static int DetectHTTP2errorCodeParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.errorcode:NO_ERROR; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHTTP2errorCodeRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2errorCodeParseTest01", DetectHTTP2errorCodeParseTest01);
+}
+
+/**
+ * \test signature with a valid http2.priority value.
+ */
+
+static int DetectHTTP2priorityParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.priority:>100; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHTTP2priorityRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2priorityParseTest01", DetectHTTP2priorityParseTest01);
+}
+
+/**
+ * \test signature with a valid http2.window value.
+ */
+
+static int DetectHTTP2windowParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.window:<42; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHTTP2windowRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2windowParseTest01", DetectHTTP2windowParseTest01);
+}
+
+
+/**
+ * \test signature with a valid http2.settings value.
+ */
+
+static int DetectHTTP2settingsParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.settings:SETTINGS_MAX_HEADER_LIST_SIZE >1024; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHTTP2settingsRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2settingsParseTest01", DetectHTTP2settingsParseTest01);
+}
+
+
+/**
+* \test signature with a valid http2.size_update value.
+*/
+
+static int DetectHTTP2sizeUpdateParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http2 any any -> any any (http2.size_update:>4096; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+void DetectHTTP2sizeUpdateRegisterTests(void)
+{
+ UtRegisterTest("DetectHTTP2sizeUpdateParseTest01", DetectHTTP2sizeUpdateParseTest01);
+}
diff --git a/src/tests/detect-icmpv4hdr.c b/src/tests/detect-icmpv4hdr.c
new file mode 100644
index 0000000..7617d80
--- /dev/null
+++ b/src/tests/detect-icmpv4hdr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+
+#include "../detect-icmpv4hdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectIcmpv4HdrParseTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ FAIL_IF_NULL(DetectEngineAppendSig(
+ de_ctx, "alert icmp any any -> any any (icmpv4.hdr; content:\"A\"; sid:1; rev:1;)"));
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectIcmpv4Hdr
+ */
+void DetectIcmpv4HdrRegisterTests(void)
+{
+ UtRegisterTest("DetectIcmpv4HdrParseTest01", DetectIcmpv4HdrParseTest01);
+}
diff --git a/src/tests/detect-icmpv6-mtu.c b/src/tests/detect-icmpv6-mtu.c
new file mode 100644
index 0000000..241a221
--- /dev/null
+++ b/src/tests/detect-icmpv6-mtu.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect-engine.h"
+
+#include "../detect-icmpv6-mtu.h"
+
+#include "../util-unittest.h"
+
+/**
+ * \test signature with a valid icmpv6.mtu value.
+ */
+
+static int DetectICMPv6mtuParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert ip any any -> any any (icmpv6.mtu:<1280; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+
+}
+
+/**
+ * \brief this function registers unit tests for DetectICMPv6mtu
+ */
+void DetectICMPv6mtuRegisterTests(void)
+{
+ UtRegisterTest("DetectICMPv6mtuParseTest01", DetectICMPv6mtuParseTest01);
+}
diff --git a/src/tests/detect-icmpv6hdr.c b/src/tests/detect-icmpv6hdr.c
new file mode 100644
index 0000000..84292a4
--- /dev/null
+++ b/src/tests/detect-icmpv6hdr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-icmpv6hdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectICMPv6hdrParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert ip any any -> any any (icmpv6.hdr; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectICMPv6hdr
+ */
+void DetectICMPv6hdrRegisterTests(void)
+{
+ UtRegisterTest("DetectICMPv6hdrParseTest01", DetectICMPv6hdrParseTest01);
+}
diff --git a/src/tests/detect-ipaddr.c b/src/tests/detect-ipaddr.c
new file mode 100644
index 0000000..712aac7
--- /dev/null
+++ b/src/tests/detect-ipaddr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2022 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-ipaddr.h"
+
+#include "../util-unittest.h"
+
+static int DetectIPAddrParseTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(
+ de_ctx, "alert ip any any -> any any (ip.src; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectIpv4hdr
+ */
+void DetectIPAddrRegisterTests(void)
+{
+ UtRegisterTest("DetectIPAddrParseTest01", DetectIPAddrParseTest01);
+}
diff --git a/src/tests/detect-ipv4hdr.c b/src/tests/detect-ipv4hdr.c
new file mode 100644
index 0000000..f86047e
--- /dev/null
+++ b/src/tests/detect-ipv4hdr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-ipv4hdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectIpv4hdrParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert ip any any -> any any (ipv4.hdr; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectIpv4hdr
+ */
+void DetectIpv4hdrRegisterTests(void)
+{
+ UtRegisterTest("DetectIpv4hdrParseTest01", DetectIpv4hdrParseTest01);
+}
diff --git a/src/tests/detect-ipv6hdr.c b/src/tests/detect-ipv6hdr.c
new file mode 100644
index 0000000..1373ad7
--- /dev/null
+++ b/src/tests/detect-ipv6hdr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-ipv6hdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectIpv6hdrParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert ip any any -> any any (ipv6.hdr; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectIpv6hdr
+ */
+void DetectIpv6hdrRegisterTests(void)
+{
+ UtRegisterTest("DetectIpv6hdrParseTest01", DetectIpv6hdrParseTest01);
+}
diff --git a/src/tests/detect-parse.c b/src/tests/detect-parse.c
new file mode 100644
index 0000000..694e2ae
--- /dev/null
+++ b/src/tests/detect-parse.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 2007-2022 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.
+ */
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-port.h"
+#include "../util-unittest.h"
+#include "util-debug.h"
+#include "util-error.h"
+
+/**
+ * \test DetectParseTest01 is a regression test against a memory leak
+ * in the case of multiple signatures with different revisions
+ * Leak happened in function DetectEngineSignatureIsDuplicate
+ */
+
+static int DetectParseTest01 (void)
+{
+ DetectEngineCtx * de_ctx = DetectEngineCtxInit();
+ FAIL_IF(DetectEngineAppendSig(de_ctx, "alert http any any -> any any (msg:\"sid 1 version 0\"; content:\"dummy1\"; sid:1;)") == NULL);
+ DetectEngineAppendSig(de_ctx, "alert http any any -> any any (msg:\"sid 2 version 0\"; content:\"dummy2\"; sid:2;)");
+ DetectEngineAppendSig(de_ctx, "alert http any any -> any any (msg:\"sid 1 version 1\"; content:\"dummy1.1\"; sid:1; rev:1;)");
+ DetectEngineAppendSig(de_ctx, "alert http any any -> any any (msg:\"sid 2 version 2\"; content:\"dummy2.1\"; sid:2; rev:1;)");
+ FAIL_IF(de_ctx->sig_list->next == NULL);
+ DetectEngineCtxFree(de_ctx);
+
+ PASS;
+}
+
+/**
+ * \test DetectParseTestNoOpt is a regression test to make sure that we reject
+ * any signature where a NOOPT rule option is given a value. This can hide rule
+ * errors which make other options disappear, eg: foo: bar: baz; where "foo" is
+ * the NOOPT option, we will end up with a signature which is missing "bar".
+ */
+
+static int DetectParseTestNoOpt(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF(DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any (msg:\"sid 1 version 0\"; "
+ "content:\"dummy1\"; endswith: reference: ref; sid:1;)") != NULL);
+ DetectEngineCtxFree(de_ctx);
+
+ PASS;
+}
+
+static int SigParseTestNegationNoWhitespace(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any [30:50,!45] -> any [30:50,!45] (msg:\"sid 2 version 0\"; "
+ "content:\"dummy2\"; sid:2;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->sp);
+ FAIL_IF_NULL(s->dp);
+ FAIL_IF_NOT(s->sp->port == 30);
+ FAIL_IF_NOT(s->sp->port2 == 44);
+ FAIL_IF_NULL(s->sp->next);
+ FAIL_IF_NOT(s->sp->next->port == 46);
+ FAIL_IF_NOT(s->sp->next->port2 == 50);
+ FAIL_IF_NOT_NULL(s->sp->next->next);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+// // Tests proper Signature is parsed from portstring length < 16 ie [30:50, !45]
+static int SigParseTestWhitespaceLessThan14(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any [30:50, !45] -> any [30:50,!45] (msg:\"sid 2 version 0\"; "
+ "content:\"dummy2\"; sid:2;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->sp);
+ FAIL_IF_NULL(s->dp);
+ FAIL_IF_NOT(s->sp->port == 30);
+ FAIL_IF_NOT(s->sp->port2 == 44);
+ FAIL_IF_NULL(s->sp->next);
+ FAIL_IF_NOT(s->sp->next->port == 46);
+ FAIL_IF_NOT(s->sp->next->port2 == 50);
+ FAIL_IF_NOT_NULL(s->sp->next->next);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+static int SigParseTestWhitespace14Spaces(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any [30:50, !45] -> any [30:50,!45] (msg:\"sid 2 "
+ "version 0\"; content:\"dummy2\"; sid:2;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->sp);
+ FAIL_IF_NULL(s->dp);
+ FAIL_IF_NOT(s->sp->port == 30);
+ FAIL_IF_NOT(s->sp->port2 == 44);
+ FAIL_IF_NULL(s->sp->next);
+ FAIL_IF_NOT(s->sp->next->port == 46);
+ FAIL_IF_NOT(s->sp->next->port2 == 50);
+ FAIL_IF_NOT_NULL(s->sp->next->next);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+static int SigParseTestWhitespaceMoreThan14(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert http any [30:50, !45] -> any [30:50,!45] "
+ "(msg:\"sid 2 version 0\"; content:\"dummy2\"; sid:2;)");
+ FAIL_IF_NULL(s);
+ FAIL_IF_NULL(s->sp);
+ FAIL_IF_NULL(s->dp);
+ FAIL_IF_NOT(s->sp->port == 30);
+ FAIL_IF_NOT(s->sp->port2 == 44);
+ FAIL_IF_NULL(s->sp->next);
+ FAIL_IF_NOT(s->sp->next->port == 46);
+ FAIL_IF_NOT(s->sp->next->port2 == 50);
+ FAIL_IF_NOT_NULL(s->sp->next->next);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectParse
+ */
+void DetectParseRegisterTests(void)
+{
+ UtRegisterTest("DetectParseTest01", DetectParseTest01);
+ UtRegisterTest("DetectParseTestNoOpt", DetectParseTestNoOpt);
+ UtRegisterTest("SigParseTestNegationNoWhitespace", SigParseTestNegationNoWhitespace);
+ UtRegisterTest("SigParseTestWhitespaceLessThan14", SigParseTestWhitespaceLessThan14);
+ UtRegisterTest("SigParseTestWhitespace14Spaces", SigParseTestWhitespace14Spaces);
+ UtRegisterTest("SigParseTestWhitespaceMoreThan14", SigParseTestWhitespaceMoreThan14);
+}
diff --git a/src/tests/detect-snmp-community.c b/src/tests/detect-snmp-community.c
new file mode 100644
index 0000000..1eda883
--- /dev/null
+++ b/src/tests/detect-snmp-community.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2019 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.
+ */
+
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+#include "app-layer-parser.h"
+#include "detect-engine.h"
+#include "detect-parse.h"
+#include "flow-util.h"
+#include "stream-tcp.h"
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+
+static int DetectSNMPCommunityTest(void)
+{
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ Flow f;
+ Packet *p;
+ TcpSession tcp;
+ ThreadVars tv;
+ Signature *s;
+
+ uint8_t request[] = {
+ 0x30, 0x27, 0x02, 0x01, 0x01, 0x04, 0x0b, 0x5b,
+ 0x52, 0x30, 0x5f, 0x43, 0x40, 0x63, 0x74, 0x69,
+ 0x21, 0x5d, 0xa1, 0x15, 0x02, 0x04, 0x2b, 0x13,
+ 0x3f, 0x85, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00,
+ 0x30, 0x07, 0x30, 0x05, 0x06, 0x01, 0x01, 0x05,
+ 0x00
+ };
+
+ /* Setup flow. */
+ memset(&f, 0, sizeof(Flow));
+ memset(&tcp, 0, sizeof(TcpSession));
+ memset(&tv, 0, sizeof(ThreadVars));
+ p = UTHBuildPacket(request, sizeof(request), IPPROTO_UDP);
+ FLOW_INITIALIZE(&f);
+ f.alproto = ALPROTO_SNMP;
+ f.protoctx = (void *)&tcp;
+ f.proto = IPPROTO_UDP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.flags |= FLOW_IPV4;
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
+ StreamTcpInitConfig(true);
+
+ de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ /* This rule should match. */
+ s = DetectEngineAppendSig(de_ctx,
+ "alert snmp any any -> any any ("
+ "msg:\"SNMP Test Rule\"; "
+ "snmp.community; content:\"[R0_C@cti!]\"; "
+ "sid:1; rev:1;)");
+ FAIL_IF_NULL(s);
+
+ /* This rule should not match. */
+ s = DetectEngineAppendSig(de_ctx,
+ "alert snmp any any -> any any ("
+ "msg:\"SNMP Test Rule\"; "
+ "snmp.community; content:\"private\"; "
+ "sid:2; rev:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SNMP,
+ STREAM_TOSERVER, request, sizeof(request));
+ FAIL_IF(r != 0);
+
+ /* Check that we have app-layer state. */
+ FAIL_IF_NULL(f.alstate);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+ FAIL_IF(!PacketAlertCheck(p, 1));
+ FAIL_IF(PacketAlertCheck(p, 2));
+
+ /* Cleanup. */
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+
+ PASS;
+}
+
+static void DetectSNMPCommunityRegisterTests(void)
+{
+ UtRegisterTest("DetectSNMPCommunityTest",
+ DetectSNMPCommunityTest);
+}
diff --git a/src/tests/detect-snmp-pdu_type.c b/src/tests/detect-snmp-pdu_type.c
new file mode 100644
index 0000000..0e7693b
--- /dev/null
+++ b/src/tests/detect-snmp-pdu_type.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2019 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.
+ */
+
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+
+/**
+ * \test This is a test for a valid value 2.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int SNMPValidityTestParse01 (void)
+{
+ DetectSNMPPduTypeData *dd = NULL;
+ dd = DetectSNMPPduTypeParse("2");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->pdu_type == 2);
+ DetectSNMPPduTypeFree(NULL, dd);
+ PASS;
+}
+
+static void DetectSNMPPduTypeRegisterTests(void)
+{
+ UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01);
+}
diff --git a/src/tests/detect-snmp-version.c b/src/tests/detect-snmp-version.c
new file mode 100644
index 0000000..5da24b1
--- /dev/null
+++ b/src/tests/detect-snmp-version.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2019 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.
+ */
+
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+
+/**
+ * \test This is a test for a valid value 2.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int SNMPValidityTestParse01 (void)
+{
+ DetectU32Data *dd = NULL;
+ dd = DetectSNMPVersionParse("2");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_EQ);
+ DetectSNMPVersionFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value >2.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int SNMPValidityTestParse02 (void)
+{
+ DetectU32Data *dd = NULL;
+ dd = DetectSNMPVersionParse(">2");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_GT);
+ DetectSNMPVersionFree(NULL, dd);
+ PASS;
+}
+
+static void DetectSNMPVersionRegisterTests(void)
+{
+ UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01);
+ UtRegisterTest("SNMPValidityTestParse02", SNMPValidityTestParse02);
+}
diff --git a/src/tests/detect-ssl-state.c b/src/tests/detect-ssl-state.c
new file mode 100644
index 0000000..6be8ea8
--- /dev/null
+++ b/src/tests/detect-ssl-state.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2007-2019 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>
+ *
+ */
+
+#include "detect-engine-build.h"
+
+static int DetectSslStateTest01(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("client_hello");
+ FAIL_IF_NULL(ssd);
+ FAIL_IF_NOT(ssd->flags == DETECT_SSL_STATE_CLIENT_HELLO);
+ SCFree(ssd);
+ PASS;
+}
+
+static int DetectSslStateTest02(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("server_hello , client_hello");
+ FAIL_IF_NULL(ssd);
+ FAIL_IF_NOT(ssd->flags == (DETECT_SSL_STATE_SERVER_HELLO |
+ DETECT_SSL_STATE_CLIENT_HELLO));
+ SCFree(ssd);
+ PASS;
+}
+
+static int DetectSslStateTest03(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("server_hello , client_keyx , "
+ "client_hello");
+ FAIL_IF_NULL(ssd);
+ FAIL_IF_NOT(ssd->flags == (DETECT_SSL_STATE_SERVER_HELLO |
+ DETECT_SSL_STATE_CLIENT_KEYX |
+ DETECT_SSL_STATE_CLIENT_HELLO));
+ SCFree(ssd);
+ PASS;
+}
+
+static int DetectSslStateTest04(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("server_hello , client_keyx , "
+ "client_hello , server_keyx , "
+ "unknown");
+ FAIL_IF_NULL(ssd);
+ FAIL_IF_NOT(ssd->flags == (DETECT_SSL_STATE_SERVER_HELLO |
+ DETECT_SSL_STATE_CLIENT_KEYX |
+ DETECT_SSL_STATE_CLIENT_HELLO |
+ DETECT_SSL_STATE_SERVER_KEYX |
+ DETECT_SSL_STATE_UNKNOWN));
+ SCFree(ssd);
+ PASS;
+}
+
+static int DetectSslStateTest05(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse(", server_hello , client_keyx , "
+ "client_hello , server_keyx , "
+ "unknown");
+
+ FAIL_IF_NOT_NULL(ssd);
+ PASS;
+}
+
+static int DetectSslStateTest06(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("server_hello , client_keyx , "
+ "client_hello , server_keyx , "
+ "unknown , ");
+ FAIL_IF_NOT_NULL(ssd);
+ PASS;
+}
+
+/**
+ * \brief Test that the "|" character still works as a separate for
+ * compatibility with older Suricata rules.
+ */
+static int DetectSslStateTest08(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("server_hello|client_hello");
+ FAIL_IF_NULL(ssd);
+ FAIL_IF_NOT(ssd->flags == (DETECT_SSL_STATE_SERVER_HELLO |
+ DETECT_SSL_STATE_CLIENT_HELLO));
+ SCFree(ssd);
+ PASS;
+}
+
+/**
+ * \test Test parsing of negated states.
+ */
+static int DetectSslStateTestParseNegate(void)
+{
+ DetectSslStateData *ssd = DetectSslStateParse("!client_hello");
+ FAIL_IF_NULL(ssd);
+ uint32_t expected = DETECT_SSL_STATE_CLIENT_HELLO;
+ FAIL_IF(ssd->flags != expected || ssd->mask != expected);
+ SCFree(ssd);
+
+ ssd = DetectSslStateParse("!client_hello,!server_hello");
+ FAIL_IF_NULL(ssd);
+ expected = DETECT_SSL_STATE_CLIENT_HELLO | DETECT_SSL_STATE_SERVER_HELLO;
+ FAIL_IF(ssd->flags != expected || ssd->mask != expected);
+ SCFree(ssd);
+
+ PASS;
+}
+
+static void DetectSslStateRegisterTests(void)
+{
+ UtRegisterTest("DetectSslStateTest01", DetectSslStateTest01);
+ UtRegisterTest("DetectSslStateTest02", DetectSslStateTest02);
+ UtRegisterTest("DetectSslStateTest03", DetectSslStateTest03);
+ UtRegisterTest("DetectSslStateTest04", DetectSslStateTest04);
+ UtRegisterTest("DetectSslStateTest05", DetectSslStateTest05);
+ UtRegisterTest("DetectSslStateTest06", DetectSslStateTest06);
+ UtRegisterTest("DetectSslStateTest08", DetectSslStateTest08);
+ UtRegisterTest("DetectSslStateTestParseNegate",
+ DetectSslStateTestParseNegate);
+}
diff --git a/src/tests/detect-ssl-version.c b/src/tests/detect-ssl-version.c
new file mode 100644
index 0000000..d4a5297
--- /dev/null
+++ b/src/tests/detect-ssl-version.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 2007-2019 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 detect-ssl-version.c
+ *
+ * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+
+/**
+ * \test DetectSslVersionTestParse01 is a test to make sure that we parse the
+ * "ssl_version" option correctly when given valid ssl_version option
+ */
+static int DetectSslVersionTestParse01(void)
+{
+ DetectSslVersionData *ssl = NULL;
+ ssl = DetectSslVersionParse(NULL, "SSlv3");
+ FAIL_IF_NULL(ssl);
+ FAIL_IF_NOT(ssl->data[SSLv3].ver == SSL_VERSION_3);
+ DetectSslVersionFree(NULL, ssl);
+ PASS;
+}
+
+/**
+ * \test DetectSslVersionTestParse02 is a test to make sure that we parse the
+ * "ssl_version" option correctly when given an invalid ssl_version option
+ * it should return ssl = NULL
+ */
+static int DetectSslVersionTestParse02(void)
+{
+ DetectSslVersionData *ssl = NULL;
+ ssl = DetectSslVersionParse(NULL, "2.5");
+ FAIL_IF_NOT_NULL(ssl);
+ DetectSslVersionFree(NULL, ssl);
+ ssl = DetectSslVersionParse(NULL, "tls1.0, !");
+ FAIL_IF_NOT_NULL(ssl);
+ DetectSslVersionFree(NULL, ssl);
+ ssl = DetectSslVersionParse(NULL, "tls1.0, !tls1.0");
+ FAIL_IF_NOT_NULL(ssl);
+ DetectSslVersionFree(NULL, ssl);
+ ssl = DetectSslVersionParse(NULL, "tls1.1, tls1.1");
+ FAIL_IF_NOT_NULL(ssl);
+ DetectSslVersionFree(NULL, ssl);
+ ssl = DetectSslVersionParse(NULL, "tls1.1, !tls1.2");
+ FAIL_IF_NOT_NULL(ssl);
+ DetectSslVersionFree(NULL, ssl);
+ PASS;
+}
+
+/**
+ * \test DetectSslVersionTestParse03 is a test to make sure that we parse the
+ * "ssl_version" options correctly when given valid ssl_version options
+ */
+static int DetectSslVersionTestParse03(void)
+{
+ DetectSslVersionData *ssl = NULL;
+ ssl = DetectSslVersionParse(NULL, "SSlv3 , tls1.0");
+ FAIL_IF_NULL(ssl);
+ FAIL_IF_NOT(ssl->data[SSLv3].ver == SSL_VERSION_3);
+ FAIL_IF_NOT(ssl->data[TLS10].ver == TLS_VERSION_10);
+ DetectSslVersionFree(NULL, ssl);
+ ssl = DetectSslVersionParse(NULL, " !tls1.2");
+ FAIL_IF_NULL(ssl);
+ FAIL_IF_NOT(ssl->data[TLS12].ver == TLS_VERSION_12);
+ FAIL_IF_NOT(ssl->data[TLS12].flags & DETECT_SSL_VERSION_NEGATED);
+ DetectSslVersionFree(NULL, ssl);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectSslVersion
+ */
+static void DetectSslVersionRegisterTests(void)
+{
+ UtRegisterTest("DetectSslVersionTestParse01", DetectSslVersionTestParse01);
+ UtRegisterTest("DetectSslVersionTestParse02", DetectSslVersionTestParse02);
+ UtRegisterTest("DetectSslVersionTestParse03", DetectSslVersionTestParse03);
+}
diff --git a/src/tests/detect-tcphdr.c b/src/tests/detect-tcphdr.c
new file mode 100644
index 0000000..6faa0d7
--- /dev/null
+++ b/src/tests/detect-tcphdr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-tcphdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectTcphdrParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any (tcp.hdr; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTcphdr
+ */
+void DetectTcphdrRegisterTests(void)
+{
+ UtRegisterTest("DetectTcphdrParseTest01", DetectTcphdrParseTest01);
+}
diff --git a/src/tests/detect-template-buffer.c b/src/tests/detect-template-buffer.c
new file mode 100644
index 0000000..7e04025
--- /dev/null
+++ b/src/tests/detect-template-buffer.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2015-2018 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.
+ */
+
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+#include "../app-layer-parser.h"
+#include "../detect-engine.h"
+#include "../detect-parse.h"
+#include "../flow-util.h"
+#include "../stream-tcp.h"
+#include "../detect-engine-build.h"
+
+static int DetectTemplateBufferTest(void)
+{
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ Flow f;
+ Packet *p;
+ TcpSession tcp;
+ ThreadVars tv;
+ Signature *s;
+
+ uint8_t request[] = "Hello World!";
+
+ /* Setup flow. */
+ memset(&f, 0, sizeof(Flow));
+ memset(&tcp, 0, sizeof(TcpSession));
+ memset(&tv, 0, sizeof(ThreadVars));
+ p = UTHBuildPacket(request, sizeof(request), IPPROTO_TCP);
+ FLOW_INITIALIZE(&f);
+ f.alproto = ALPROTO_TEMPLATE;
+ f.protoctx = (void *)&tcp;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ /* This rule should match. */
+ s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any ("
+ "msg:\"TEMPLATE Test Rule\"; "
+ "template_buffer; content:\"World!\"; "
+ "sid:1; rev:1;)");
+ FAIL_IF_NULL(s);
+
+ /* This rule should not match. */
+ s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any ("
+ "msg:\"TEMPLATE Test Rule\"; "
+ "template_buffer; content:\"W0rld!\"; "
+ "sid:2; rev:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TEMPLATE,
+ STREAM_TOSERVER, request, sizeof(request));
+
+ /* Check that we have app-layer state. */
+ FAIL_IF_NULL(f.alstate);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+ FAIL_IF(!PacketAlertCheck(p, 1));
+ FAIL_IF(PacketAlertCheck(p, 2));
+
+ /* Cleanup. */
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p);
+
+ PASS;
+}
+
+static void DetectTemplateBufferRegisterTests(void)
+{
+ UtRegisterTest("DetectTemplateBufferTest", DetectTemplateBufferTest);
+}
diff --git a/src/tests/detect-template.c b/src/tests/detect-template.c
new file mode 100644
index 0000000..c91a463
--- /dev/null
+++ b/src/tests/detect-template.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2015-2018 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.
+ */
+
+#include "../suricata-common.h"
+#include "../util-unittest.h"
+
+#include "../detect-parse.h"
+#include "../detect-engine.h"
+
+#include "../detect-template.h"
+
+/**
+ * \test test keyword parsing
+ */
+
+static int DetectTemplateParseTest01 (void)
+{
+ DetectTemplateData *templated = DetectTemplateParse("1,10");
+ FAIL_IF_NULL(templated);
+ FAIL_IF(!(templated->arg1 == 1 && templated->arg2 == 10));
+ DetectTemplateFree(NULL, templated);
+ PASS;
+}
+
+/**
+ * \test test signature parsing
+ */
+
+static int DetectTemplateSignatureTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (template:1,10; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTemplate
+ */
+void DetectTemplateRegisterTests(void)
+{
+ UtRegisterTest("DetectTemplateParseTest01", DetectTemplateParseTest01);
+ UtRegisterTest("DetectTemplateSignatureTest01",
+ DetectTemplateSignatureTest01);
+}
diff --git a/src/tests/detect-tls-cert-fingerprint.c b/src/tests/detect-tls-cert-fingerprint.c
new file mode 100644
index 0000000..e2ec3d5
--- /dev/null
+++ b/src/tests/detect-tls-cert-fingerprint.c
@@ -0,0 +1,372 @@
+/* Copyright (C) 2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "app-layer-parser.h"
+/**
+ * \test Test that a signature containing tls_cert_fingerprint is correctly parsed
+ * and that the keyword is registered.
+ */
+static int DetectTlsFingerprintTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tls any any -> any any "
+ "(msg:\"Testing tls.cert_fingerprint\"; "
+ "tls.cert_fingerprint; "
+ "content:\"11:22:33:44:55:66:77:88:99:00:11:22:33:44:55:66:77:88:99:00\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ /* sm should not be in the MATCH list */
+ SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ sm = DetectBufferGetFirstSigMatch(s, g_tls_cert_fingerprint_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ FAIL_IF(sm->type != DETECT_CONTENT);
+ FAIL_IF_NOT_NULL(sm->next);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ PASS;
+}
+
+/**
+ * \test Test matching for fingerprint of a certificate.
+ */
+static int DetectTlsFingerprintTest02(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->mpm_matcher = mpm_default_matcher;
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls.cert_fingerprint\"; "
+ "tls.cert_fingerprint; "
+ "content:\"4a:a3:66:76:82:cb:6b:23:bb:c3:58:47:23:a4:63:a7:78:a4:a1:18\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+static void DetectTlsFingerprintRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsFingerprintTest01", DetectTlsFingerprintTest01);
+ UtRegisterTest("DetectTlsFingerprintTest02", DetectTlsFingerprintTest02);
+}
diff --git a/src/tests/detect-tls-cert-issuer.c b/src/tests/detect-tls-cert-issuer.c
new file mode 100644
index 0000000..feaa70b
--- /dev/null
+++ b/src/tests/detect-tls-cert-issuer.c
@@ -0,0 +1,376 @@
+/* Copyright (C) 2007-2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "app-layer-parser.h"
+#include "detect-engine-alert.h"
+
+/**
+ * \test Test that a signature containing a tls_cert_issuer is correctly parsed
+ * and that the keyword is registered.
+ */
+static int DetectTlsIssuerTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Testing tls.cert_issuer\"; "
+ "tls.cert_issuer; content:\"test\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ /* sm should not be in the MATCH list */
+ SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ sm = DetectBufferGetFirstSigMatch(s, g_tls_cert_issuer_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ FAIL_IF(sm->type != DETECT_CONTENT);
+ FAIL_IF_NOT_NULL(sm->next);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ PASS;
+}
+
+/**
+ * \test Test matching for google in the issuer of a certificate
+ *
+ */
+static int DetectTlsIssuerTest02(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->mpm_matcher = mpm_default_matcher;
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls.cert_issuer\"; "
+ "tls.cert_issuer; content:\"google\"; nocase; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+static void DetectTlsIssuerRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsIssuerTest01", DetectTlsIssuerTest01);
+ UtRegisterTest("DetectTlsIssuerTest02", DetectTlsIssuerTest02);
+}
diff --git a/src/tests/detect-tls-cert-serial.c b/src/tests/detect-tls-cert-serial.c
new file mode 100644
index 0000000..119d94a
--- /dev/null
+++ b/src/tests/detect-tls-cert-serial.c
@@ -0,0 +1,374 @@
+/* Copyright (C) 2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+#include "app-layer-parser.h"
+
+/**
+ * \test Test that a signature containing tls.cert_serial is correctly parsed
+ * and that the keyword is registered.
+ */
+static int DetectTlsSerialTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Testing tls.cert_serial\"; "
+ "tls.cert_serial; content:\"XX:XX:XX\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ /* sm should not be in the MATCH list */
+ SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ sm = DetectBufferGetFirstSigMatch(s, g_tls_cert_serial_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ FAIL_IF(sm->type != DETECT_CONTENT);
+ FAIL_IF_NOT_NULL(sm->next);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test matching for serial in a certificate.
+ */
+static int DetectTlsSerialTest02(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->mpm_matcher = mpm_default_matcher;
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls.cert_serial\"; "
+ "tls.cert_serial; "
+ "content:\"5C:19:B7:B1:32:3B:1C:A1\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+static void DetectTlsSerialRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsSerialTest01", DetectTlsSerialTest01);
+ UtRegisterTest("DetectTlsSerialTest02", DetectTlsSerialTest02);
+}
diff --git a/src/tests/detect-tls-cert-subject.c b/src/tests/detect-tls-cert-subject.c
new file mode 100644
index 0000000..2df23eb
--- /dev/null
+++ b/src/tests/detect-tls-cert-subject.c
@@ -0,0 +1,376 @@
+/* Copyright (C) 2007-2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+#include "app-layer-parser.h"
+
+/**
+ * \test Test that a signature containing a tls.cert_subject is correctly parsed
+ * and that the keyword is registered.
+ */
+static int DetectTlsSubjectTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Testing tls.cert_subject\"; "
+ "tls.cert_subject; content:\"test\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ /* sm should not be in the MATCH list */
+ SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ sm = DetectBufferGetFirstSigMatch(s, g_tls_cert_subject_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ FAIL_IF(sm->type != DETECT_CONTENT);
+ FAIL_IF_NOT_NULL(sm->next);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ PASS;
+}
+
+/**
+ * \test Test matching for google in the subject of a certificate
+ *
+ */
+static int DetectTlsSubjectTest02(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->mpm_matcher = mpm_default_matcher;
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls.cert_subject\"; "
+ "tls.cert_subject; content:\"google\"; nocase; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+static void DetectTlsSubjectRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsSubjectTest01", DetectTlsSubjectTest01);
+ UtRegisterTest("DetectTlsSubjectTest02", DetectTlsSubjectTest02);
+}
diff --git a/src/tests/detect-tls-cert-validity.c b/src/tests/detect-tls-cert-validity.c
new file mode 100644
index 0000000..6383e2b
--- /dev/null
+++ b/src/tests/detect-tls-cert-validity.c
@@ -0,0 +1,1422 @@
+/* Copyright (C) 2015-2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+#include "app-layer-parser.h"
+
+/**
+ * \test This is a test for a valid value 1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse01 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1430000000");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value >1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse02 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse(">1430000000");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->mode == DETECT_TLS_VALIDITY_GT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value <1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse03 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("<1430000000");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->mode == DETECT_TLS_VALIDITY_LT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 1430000000<>1470000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse04 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1430000000<>1470000000");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->epoch2 == 1470000000 &&
+ dd->mode == DETECT_TLS_VALIDITY_RA);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value A.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse05 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("A");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value >1430000000<>1470000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse06 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse(">1430000000<>1470000000");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value 1430000000<>.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse07 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1430000000<>");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value <>1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse08 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("<>1430000000");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value "".
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse09 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value " ".
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse10 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse(" ");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a invalid value 1490000000<>1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse11 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1490000000<>1430000000");
+ FAIL_IF_NOT_NULL(dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 1430000000 <> 1490000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse12 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1430000000 <> 1490000000");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->epoch2 == 1490000000 &&
+ dd->mode == DETECT_TLS_VALIDITY_RA);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value > 1430000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse13 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("> 1430000000 ");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1430000000 && dd->mode == DETECT_TLS_VALIDITY_GT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value < 1490000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse14 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("< 1490000000 ");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1490000000 && dd->mode == DETECT_TLS_VALIDITY_LT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 1490000000.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse15 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse(" 1490000000 ");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1490000000 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse16 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1443657600 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value >2015-10-22.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse17 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse(">2015-10-22");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445472000 && dd->mode == DETECT_TLS_VALIDITY_GT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value <2015-10-22 23.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse18 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("<2015-10-22 23");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445554800 && dd->mode == DETECT_TLS_VALIDITY_LT);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10-22 23:59.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse19 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10-22 23:59");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445558340 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10-22 23:59:59.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse20 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10-22 23:59:59");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445558399 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10-22T23.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse21 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10-22T23");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445554800 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10-22T23:59.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse22 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10-22T23:59");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445558340 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value 2015-10-22T23:59:59.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse23 (void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("2015-10-22T23:59:59");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 1445558399 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value of 1970-01-01T00:00:00
+ * that is at epoch 0, within the range of acceptable
+ * values (1950-2049) as per RFC 5280. (https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1)
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse24(void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1970-01-01T00:00:00");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == 0 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test This is a test for a valid value of 1965-10-22T23:59:59
+ * that is lower than epoch 0, but within the range of
+ * acceptable values (1950-2049) as per RFC 5280.
+ * (https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1)
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestParse25(void)
+{
+ DetectTlsValidityData *dd = NULL;
+ dd = DetectTlsValidityParse("1969-12-31T23:59:59");
+ FAIL_IF_NULL(dd);
+ FAIL_IF_NOT(dd->epoch == -1 && dd->mode == DETECT_TLS_VALIDITY_EQ);
+ DetectTlsValidityFree(NULL, dd);
+ PASS;
+}
+
+/**
+ * \test Test matching on validity dates in a certificate.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidityTestDetect01(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls_cert_notbefore\"; "
+ "tls_cert_notbefore:<2016-07-20; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls_cert_notafter\"; "
+ "tls_cert_notafter:>2016-09-01; sid:2;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+ FAIL_IF(PacketAlertCheck(p1, 2));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+ FAIL_IF(PacketAlertCheck(p2, 2));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+ FAIL_IF_NOT(PacketAlertCheck(p3, 2));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+/**
+ * \test Test matching on an expired certificate.
+ *
+ * Traffic from expired.badssl.com
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ExpiredTestDetect01(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x5a, 0x01, 0x00, 0x00,
+ 0x56, 0x03, 0x03, 0x62, 0x87, 0xa4, 0x11, 0x3e,
+ 0x11, 0x32, 0x7d, 0xbc, 0x5b, 0x63, 0xb7, 0xaf,
+ 0x55, 0x8d, 0x46, 0x5b, 0x8f, 0xac, 0x50, 0x02,
+ 0x90, 0xe3, 0x55, 0x03, 0xfe, 0xad, 0xa6, 0x92,
+ 0x56, 0x75, 0xf9, 0x00, 0x00, 0x08, 0x00, 0x35,
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00,
+ 0x00, 0x25, 0x00, 0x00, 0x00, 0x17, 0x00, 0x15,
+ 0x00, 0x00, 0x12, 0x65, 0x78, 0x70, 0x69, 0x72,
+ 0x65, 0x64, 0x2e, 0x62, 0x61, 0x64, 0x73, 0x73,
+ 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x0d, 0x00,
+ 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x55, 0x02, 0x00, 0x00,
+ 0x51, 0x03, 0x03, 0x22, 0xa1, 0xd8, 0xd0, 0x3c,
+ 0x8d, 0x32, 0x7e, 0x4f, 0x60, 0x27, 0xf6, 0x0c,
+ 0x99, 0x7a, 0x8e, 0x6e, 0x52, 0xa5, 0xf4, 0x20,
+ 0x2e, 0xa1, 0xa4, 0x0b, 0xd5, 0x80, 0x9b, 0xec,
+ 0xbd, 0x2c, 0x6c, 0x20, 0x7a, 0x9b, 0xcc, 0x6b,
+ 0xbf, 0x3d, 0xfc, 0x7c, 0x31, 0x78, 0x65, 0x1e,
+ 0xcc, 0x41, 0x0b, 0x8b, 0x3d, 0x4e, 0xde, 0x45,
+ 0xe5, 0x20, 0xf5, 0xbd, 0x8e, 0x99, 0xce, 0xc2,
+ 0xad, 0x88, 0x08, 0x27, 0x00, 0x2f, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00,
+ 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x05, 0x59, 0x0b, 0x00, 0x05,
+ 0x55, 0x00, 0x05, 0x52, 0x00, 0x05, 0x4f, 0x30,
+ 0x82, 0x05, 0x4b, 0x30, 0x82, 0x04, 0x33, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4a, 0xe7,
+ 0x95, 0x49, 0xfa, 0x9a, 0xbe, 0x3f, 0x10, 0x0f,
+ 0x17, 0xa4, 0x78, 0xe1, 0x69, 0x09, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x90,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30,
+ 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12,
+ 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20,
+ 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74,
+ 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c,
+ 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43,
+ 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41,
+ 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64,
+ 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x2d, 0x43, 0x4f, 0x4d, 0x4f, 0x44,
+ 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x61, 0x6c,
+ 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34,
+ 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x31,
+ 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a,
+ 0x30, 0x59, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+ 0x72, 0x6f, 0x6c, 0x20, 0x56, 0x61, 0x6c, 0x69,
+ 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x1d, 0x30,
+ 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x14,
+ 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
+ 0x53, 0x53, 0x4c, 0x20, 0x57, 0x69, 0x6c, 0x64,
+ 0x63, 0x61, 0x72, 0x64, 0x31, 0x15, 0x30, 0x13,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0c, 0x2a,
+ 0x2e, 0x62, 0x61, 0x64, 0x73, 0x73, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
+ 0x82, 0x01, 0x01, 0x00, 0xc2, 0x04, 0xec, 0xf8,
+ 0x8c, 0xee, 0x04, 0xc2, 0xb3, 0xd8, 0x50, 0xd5,
+ 0x70, 0x58, 0xcc, 0x93, 0x18, 0xeb, 0x5c, 0xa8,
+ 0x68, 0x49, 0xb0, 0x22, 0xb5, 0xf9, 0x95, 0x9e,
+ 0xb1, 0x2b, 0x2c, 0x76, 0x3e, 0x6c, 0xc0, 0x4b,
+ 0x60, 0x4c, 0x4c, 0xea, 0xb2, 0xb4, 0xc0, 0x0f,
+ 0x80, 0xb6, 0xb0, 0xf9, 0x72, 0xc9, 0x86, 0x02,
+ 0xf9, 0x5c, 0x41, 0x5d, 0x13, 0x2b, 0x7f, 0x71,
+ 0xc4, 0x4b, 0xbc, 0xe9, 0x94, 0x2e, 0x50, 0x37,
+ 0xa6, 0x67, 0x1c, 0x61, 0x8c, 0xf6, 0x41, 0x42,
+ 0xc5, 0x46, 0xd3, 0x16, 0x87, 0x27, 0x9f, 0x74,
+ 0xeb, 0x0a, 0x9d, 0x11, 0x52, 0x26, 0x21, 0x73,
+ 0x6c, 0x84, 0x4c, 0x79, 0x55, 0xe4, 0xd1, 0x6b,
+ 0xe8, 0x06, 0x3d, 0x48, 0x15, 0x52, 0xad, 0xb3,
+ 0x28, 0xdb, 0xaa, 0xff, 0x6e, 0xff, 0x60, 0x95,
+ 0x4a, 0x77, 0x6b, 0x39, 0xf1, 0x24, 0xd1, 0x31,
+ 0xb6, 0xdd, 0x4d, 0xc0, 0xc4, 0xfc, 0x53, 0xb9,
+ 0x6d, 0x42, 0xad, 0xb5, 0x7c, 0xfe, 0xae, 0xf5,
+ 0x15, 0xd2, 0x33, 0x48, 0xe7, 0x22, 0x71, 0xc7,
+ 0xc2, 0x14, 0x7a, 0x6c, 0x28, 0xea, 0x37, 0x4a,
+ 0xdf, 0xea, 0x6c, 0xb5, 0x72, 0xb4, 0x7e, 0x5a,
+ 0xa2, 0x16, 0xdc, 0x69, 0xb1, 0x57, 0x44, 0xdb,
+ 0x0a, 0x12, 0xab, 0xde, 0xc3, 0x0f, 0x47, 0x74,
+ 0x5c, 0x41, 0x22, 0xe1, 0x9a, 0xf9, 0x1b, 0x93,
+ 0xe6, 0xad, 0x22, 0x06, 0x29, 0x2e, 0xb1, 0xba,
+ 0x49, 0x1c, 0x0c, 0x27, 0x9e, 0xa3, 0xfb, 0x8b,
+ 0xf7, 0x40, 0x72, 0x00, 0xac, 0x92, 0x08, 0xd9,
+ 0x8c, 0x57, 0x84, 0x53, 0x81, 0x05, 0xcb, 0xe6,
+ 0xfe, 0x6b, 0x54, 0x98, 0x40, 0x27, 0x85, 0xc7,
+ 0x10, 0xbb, 0x73, 0x70, 0xef, 0x69, 0x18, 0x41,
+ 0x07, 0x45, 0x55, 0x7c, 0xf9, 0x64, 0x3f, 0x3d,
+ 0x2c, 0xc3, 0xa9, 0x7c, 0xeb, 0x93, 0x1a, 0x4c,
+ 0x86, 0xd1, 0xca, 0x85, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x82, 0x01, 0xd5, 0x30, 0x82, 0x01,
+ 0xd1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x90, 0xaf,
+ 0x6a, 0x3a, 0x94, 0x5a, 0x0b, 0xd8, 0x90, 0xea,
+ 0x12, 0x56, 0x73, 0xdf, 0x43, 0xb4, 0x3a, 0x28,
+ 0xda, 0xe7, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
+ 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, 0xee, 0xc1,
+ 0x7b, 0x81, 0x0b, 0x3a, 0x47, 0x69, 0x71, 0x18,
+ 0x7d, 0x11, 0x37, 0x93, 0xbc, 0xa5, 0x1b, 0x3f,
+ 0xfb, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
+ 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05,
+ 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16,
+ 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x4f,
+ 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x48, 0x30,
+ 0x46, 0x30, 0x3a, 0x06, 0x0b, 0x2b, 0x06, 0x01,
+ 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x02, 0x07,
+ 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1d,
+ 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
+ 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x08, 0x06,
+ 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x01, 0x30,
+ 0x54, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x4d,
+ 0x30, 0x4b, 0x30, 0x49, 0xa0, 0x47, 0xa0, 0x45,
+ 0x86, 0x43, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f,
+ 0x52, 0x53, 0x41, 0x44, 0x6f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72,
+ 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43,
+ 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x81, 0x85,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x79, 0x30, 0x77, 0x30, 0x4f,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x02, 0x86, 0x43, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f,
+ 0x44, 0x4f, 0x52, 0x53, 0x41, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63,
+ 0x75, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30,
+ 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63,
+ 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x23, 0x06,
+ 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1c, 0x30, 0x1a,
+ 0x82, 0x0c, 0x2a, 0x2e, 0x62, 0x61, 0x64, 0x73,
+ 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x0a,
+ 0x62, 0x61, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x6a, 0x7a,
+ 0xf1, 0xda, 0xff, 0x03, 0x07, 0x72, 0x78, 0xc5,
+ 0x66, 0xa1, 0x4f, 0x46, 0x43, 0x0e, 0x5f, 0x14,
+ 0x21, 0x8c, 0x75, 0x1a, 0xeb, 0x36, 0xe0, 0x1f,
+ 0xa4, 0x10, 0x15, 0xec, 0xda, 0x33, 0x25, 0x7c,
+ 0x3b, 0xb5, 0x0a, 0xc7, 0x01, 0x38, 0x3d, 0x27,
+ 0xfd, 0x58, 0xd9, 0xcc, 0xea, 0x2d, 0x69, 0x39,
+ 0x7c, 0xbe, 0x97, 0xef, 0x0b, 0xd6, 0x0b, 0x58,
+ 0xe7, 0x8c, 0x7f, 0xbf, 0xb3, 0x4c, 0x1d, 0xf3,
+ 0xb7, 0x90, 0x80, 0xa6, 0x36, 0x7c, 0x14, 0x5b,
+ 0xec, 0x07, 0x2d, 0x02, 0x3e, 0x1b, 0x5b, 0x63,
+ 0x5b, 0x15, 0xab, 0x00, 0xfa, 0x1f, 0x3b, 0x19,
+ 0x2d, 0xdf, 0xe2, 0x23, 0x10, 0x11, 0x07, 0x7e,
+ 0x72, 0x7f, 0xe2, 0xbf, 0xb7, 0x00, 0x1b, 0x98,
+ 0x2f, 0x2c, 0x3f, 0xce, 0x85, 0x9a, 0x27, 0x8c,
+ 0x10, 0x22, 0x08, 0x41, 0x2b, 0x8a, 0x3e, 0x82,
+ 0x4e, 0xfc, 0xdd, 0x21, 0xc6, 0x56, 0x74, 0x70,
+ 0xa4, 0x34, 0xf2, 0xb1, 0x40, 0x9e, 0x2b, 0x58,
+ 0xa2, 0x59, 0x0f, 0x1d, 0x48, 0xef, 0xeb, 0x11,
+ 0x3e, 0xc1, 0x4a, 0x9e, 0xbc, 0x65, 0x55, 0x6d,
+ 0xc6, 0xa3, 0xef, 0xd5, 0xd4, 0x96, 0xcd, 0xf1,
+ 0xae, 0x27, 0xf7, 0xa4, 0x57, 0x14, 0x3c, 0x94,
+ 0x41, 0x05, 0x7a, 0x8b, 0xa1, 0x37, 0x47, 0xd7,
+ 0xf5, 0x7d, 0xdc, 0xfa, 0xce, 0x6f, 0x31, 0xa2,
+ 0xb0, 0x8c, 0xea, 0xcc, 0x12, 0x9b, 0x22, 0xf1,
+ 0x34, 0x70, 0xcf, 0x7d, 0x75, 0x4a, 0x8b, 0x68,
+ 0x29, 0x0c, 0x1e, 0xe9, 0x96, 0xa8, 0xcf, 0xb0,
+ 0x12, 0x1f, 0x5c, 0x2a, 0xee, 0x67, 0x2f, 0x7f,
+ 0xbd, 0x73, 0xf3, 0x5a, 0x01, 0x22, 0x0c, 0x70,
+ 0xfa, 0xcd, 0x45, 0xef, 0x78, 0x5c, 0xce, 0x0d,
+ 0xfa, 0x4e, 0xe1, 0xef, 0xce, 0x65, 0x9f, 0x47,
+ 0x0c, 0x4f, 0xbb, 0x36, 0x44, 0x68, 0x56, 0x5c,
+ 0x56, 0x59, 0xad, 0xaa, 0x8a, 0xbc,
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ f.lastts = SCTIME_FROM_SECS(1474978656L); /* 2016-09-27 */
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls_cert_expired\"; "
+ "tls_cert_expired; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER,
+ client_hello, sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+/**
+ * \test Test matching on a valid TLS certificate.
+ *
+ * \retval 1 on success.
+ * \retval 0 on failure.
+ */
+static int ValidTestDetect01(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ f.lastts = SCTIME_FROM_SECS(1474978656L); /* 2016-09-27 */
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls_cert_valid\"; "
+ "tls_cert_valid; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER,
+ client_hello, sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+/**
+ * \brief Register unit tests for tls_cert_notbefore.
+ */
+void TlsNotBeforeRegisterTests(void)
+{
+ UtRegisterTest("ValidityTestParse01", ValidityTestParse01);
+ UtRegisterTest("ValidityTestParse03", ValidityTestParse03);
+ UtRegisterTest("ValidityTestParse05", ValidityTestParse05);
+ UtRegisterTest("ValidityTestParse07", ValidityTestParse07);
+ UtRegisterTest("ValidityTestParse09", ValidityTestParse09);
+ UtRegisterTest("ValidityTestParse11", ValidityTestParse11);
+ UtRegisterTest("ValidityTestParse13", ValidityTestParse13);
+ UtRegisterTest("ValidityTestParse15", ValidityTestParse15);
+ UtRegisterTest("ValidityTestParse17", ValidityTestParse17);
+ UtRegisterTest("ValidityTestParse19", ValidityTestParse19);
+ UtRegisterTest("ValidityTestParse21", ValidityTestParse21);
+ UtRegisterTest("ValidityTestParse23", ValidityTestParse23);
+ UtRegisterTest("ValidityTestParse24", ValidityTestParse24);
+ UtRegisterTest("ValidityTestParse25", ValidityTestParse25);
+ UtRegisterTest("ValidityTestDetect01", ValidityTestDetect01);
+}
+
+/**
+ * \brief Register unit tests for tls_cert_notafter.
+ */
+void TlsNotAfterRegisterTests(void)
+{
+ UtRegisterTest("ValidityTestParse02", ValidityTestParse02);
+ UtRegisterTest("ValidityTestParse04", ValidityTestParse04);
+ UtRegisterTest("ValidityTestParse06", ValidityTestParse06);
+ UtRegisterTest("ValidityTestParse08", ValidityTestParse08);
+ UtRegisterTest("ValidityTestParse10", ValidityTestParse10);
+ UtRegisterTest("ValidityTestParse12", ValidityTestParse12);
+ UtRegisterTest("ValidityTestParse14", ValidityTestParse14);
+ UtRegisterTest("ValidityTestParse16", ValidityTestParse16);
+ UtRegisterTest("ValidityTestParse18", ValidityTestParse18);
+ UtRegisterTest("ValidityTestParse20", ValidityTestParse20);
+ UtRegisterTest("ValidityTestParse22", ValidityTestParse22);
+}
+
+/**
+ * \brief Register unit tests for tls_cert_expired
+ */
+void TlsExpiredRegisterTests(void)
+{
+ UtRegisterTest("ExpiredTestDetect01", ExpiredTestDetect01);
+}
+
+/**
+ * \brief Register unit tests for tls_cert_valid
+ */
+void TlsValidRegisterTests(void)
+{
+ UtRegisterTest("ValidTestDetect01", ValidTestDetect01);
+}
diff --git a/src/tests/detect-tls-certs.c b/src/tests/detect-tls-certs.c
new file mode 100644
index 0000000..19b5436
--- /dev/null
+++ b/src/tests/detect-tls-certs.c
@@ -0,0 +1,364 @@
+/* Copyright (C) 2019 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 Mats Klepsland <mats.klepsland@gmail.com>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "detect-engine-alert.h"
+#include "app-layer-parser.h"
+
+/**
+ * \test Test that a signature containing tls.certs is correctly parsed
+ * and that the keyword is registered.
+ */
+static int DetectTlsCertsTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Testing tls.certs\"; tls.certs; "
+ "content:\"|01 02 03 04 05|\"; sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ /* sm should not be in the MATCH list */
+ SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
+ FAIL_IF_NOT_NULL(sm);
+
+ sm = DetectBufferGetFirstSigMatch(s, g_tls_certs_buffer_id);
+ FAIL_IF_NULL(sm);
+
+ FAIL_IF(sm->type != DETECT_CONTENT);
+ FAIL_IF_NOT_NULL(sm->next);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test Test matching on bytes in a certificate
+ */
+static int DetectTlsCertsTest02(void)
+{
+ /* client hello */
+ uint8_t client_hello[] = {
+ 0x16, 0x03, 0x01, 0x00, 0xc8, 0x01, 0x00, 0x00,
+ 0xc4, 0x03, 0x03, 0xd6, 0x08, 0x5a, 0xa2, 0x86,
+ 0x5b, 0x85, 0xd4, 0x40, 0xab, 0xbe, 0xc0, 0xbc,
+ 0x41, 0xf2, 0x26, 0xf0, 0xfe, 0x21, 0xee, 0x8b,
+ 0x4c, 0x7e, 0x07, 0xc8, 0xec, 0xd2, 0x00, 0x46,
+ 0x4c, 0xeb, 0xb7, 0x00, 0x00, 0x16, 0xc0, 0x2b,
+ 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13,
+ 0xc0, 0x14, 0x00, 0x33, 0x00, 0x39, 0x00, 0x2f,
+ 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x85,
+ 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00,
+ 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0xff, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31,
+ 0x36, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x35, 0x05,
+ 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32,
+ 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e,
+ 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31,
+ 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x16, 0x00,
+ 0x14, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02,
+ 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02,
+ 0x03, 0x04, 0x02, 0x02, 0x02
+ };
+
+ /* server hello */
+ uint8_t server_hello[] = {
+ 0x16, 0x03, 0x03, 0x00, 0x48, 0x02, 0x00, 0x00,
+ 0x44, 0x03, 0x03, 0x57, 0x91, 0xb8, 0x63, 0xdd,
+ 0xdb, 0xbb, 0x23, 0xcf, 0x0b, 0x43, 0x02, 0x1d,
+ 0x46, 0x11, 0x27, 0x5c, 0x98, 0xcf, 0x67, 0xe1,
+ 0x94, 0x3d, 0x62, 0x7d, 0x38, 0x48, 0x21, 0x23,
+ 0xa5, 0x62, 0x31, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x1c, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00
+ };
+
+ /* certificate */
+ uint8_t certificate[] = {
+ 0x16, 0x03, 0x03, 0x04, 0x93, 0x0b, 0x00, 0x04,
+ 0x8f, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x89, 0x30,
+ 0x82, 0x04, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x5c, 0x19,
+ 0xb7, 0xb1, 0x32, 0x3b, 0x1c, 0xa1, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x37,
+ 0x31, 0x33, 0x31, 0x33, 0x32, 0x34, 0x35, 0x32,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x30,
+ 0x35, 0x31, 0x33, 0x31, 0x36, 0x30, 0x30, 0x5a,
+ 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
+ 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e,
+ 0x63, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0b, 0x2a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xa5, 0x0a, 0xb9, 0xb1, 0xca, 0x36, 0xd1, 0xae,
+ 0x22, 0x38, 0x07, 0x06, 0xc9, 0x1a, 0x56, 0x4f,
+ 0xbb, 0xdf, 0xa8, 0x6d, 0xbd, 0xee, 0x76, 0x16,
+ 0xbc, 0x53, 0x3c, 0x03, 0x6a, 0x5c, 0x94, 0x50,
+ 0x87, 0x2f, 0x28, 0xb4, 0x4e, 0xd5, 0x9b, 0x8f,
+ 0xfe, 0x02, 0xde, 0x2a, 0x83, 0x01, 0xf9, 0x45,
+ 0x61, 0x0e, 0x66, 0x0e, 0x24, 0x22, 0xe2, 0x59,
+ 0x66, 0x0d, 0xd3, 0xe9, 0x77, 0x8a, 0x7e, 0x42,
+ 0xaa, 0x5a, 0xf9, 0x05, 0xbf, 0x30, 0xc7, 0x03,
+ 0x2b, 0xdc, 0xa6, 0x9c, 0xe0, 0x9f, 0x0d, 0xf1,
+ 0x28, 0x19, 0xf8, 0xf2, 0x02, 0xfa, 0xbd, 0x62,
+ 0xa0, 0xf3, 0x02, 0x2b, 0xcd, 0xf7, 0x09, 0x04,
+ 0x3b, 0x52, 0xd8, 0x65, 0x4b, 0x4a, 0x70, 0xe4,
+ 0x57, 0xc9, 0x2e, 0x2a, 0xf6, 0x9c, 0x6e, 0xd8,
+ 0xde, 0x01, 0x52, 0xc9, 0x6f, 0xe9, 0xef, 0x82,
+ 0xbc, 0x0b, 0x95, 0xb2, 0xef, 0xcb, 0x91, 0xa6,
+ 0x0b, 0x2d, 0x14, 0xc6, 0x00, 0xa9, 0x33, 0x86,
+ 0x64, 0x00, 0xd4, 0x92, 0x19, 0x53, 0x3d, 0xfd,
+ 0xcd, 0xc6, 0x1a, 0xf2, 0x0e, 0x67, 0xc2, 0x1d,
+ 0x2c, 0xe0, 0xe8, 0x29, 0x97, 0x1c, 0xb6, 0xc4,
+ 0xb2, 0x02, 0x0c, 0x83, 0xb8, 0x60, 0x61, 0xf5,
+ 0x61, 0x2d, 0x73, 0x5e, 0x85, 0x4d, 0xbd, 0x0d,
+ 0xe7, 0x1a, 0x37, 0x56, 0x8d, 0xe5, 0x50, 0x0c,
+ 0xc9, 0x64, 0x4c, 0x11, 0xea, 0xf3, 0xcb, 0x26,
+ 0x34, 0xbd, 0x02, 0xf5, 0xc1, 0xfb, 0xa2, 0xec,
+ 0x27, 0xbb, 0x60, 0xbe, 0x0b, 0xf6, 0xe7, 0x3c,
+ 0x2d, 0xc9, 0xe7, 0xb0, 0x30, 0x28, 0x17, 0x3d,
+ 0x90, 0xf1, 0x63, 0x8e, 0x49, 0xf7, 0x15, 0x78,
+ 0x21, 0xcc, 0x45, 0xe6, 0x86, 0xb2, 0xd8, 0xb0,
+ 0x2e, 0x5a, 0xb0, 0x58, 0xd3, 0xb6, 0x11, 0x40,
+ 0xae, 0x81, 0x1f, 0x6b, 0x7a, 0xaf, 0x40, 0x50,
+ 0xf9, 0x2e, 0x81, 0x8b, 0xec, 0x26, 0x11, 0x3f,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01,
+ 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x03, 0x02, 0x30, 0x21, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1a, 0x30, 0x18, 0x82,
+ 0x0b, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x6e, 0x6f, 0x82, 0x09, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6e, 0x6f, 0x30,
+ 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30,
+ 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+ 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
+ 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc6, 0x53, 0x87, 0x42,
+ 0x2d, 0xc8, 0xee, 0x7a, 0x62, 0x1e, 0x83, 0xdb,
+ 0x0d, 0xe2, 0x32, 0xeb, 0x8b, 0xaf, 0x69, 0x40,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+ 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6,
+ 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a,
+ 0x30, 0x18, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01,
+ 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01,
+ 0x02, 0x02, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0,
+ 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32,
+ 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x7b, 0x27, 0x00, 0x46, 0x8f, 0xfd, 0x5b, 0xff,
+ 0xcb, 0x05, 0x9b, 0xf7, 0xf1, 0x68, 0xf6, 0x9a,
+ 0x7b, 0xba, 0x53, 0xdf, 0x63, 0xed, 0x11, 0x94,
+ 0x39, 0xf2, 0xd0, 0x20, 0xcd, 0xa3, 0xc4, 0x98,
+ 0xa5, 0x10, 0x74, 0xe7, 0x10, 0x6d, 0x07, 0xf8,
+ 0x33, 0x87, 0x05, 0x43, 0x0e, 0x64, 0x77, 0x09,
+ 0x18, 0x4f, 0x38, 0x2e, 0x45, 0xae, 0xa8, 0x34,
+ 0x3a, 0xa8, 0x33, 0xac, 0x9d, 0xdd, 0x25, 0x91,
+ 0x59, 0x43, 0xbe, 0x0f, 0x87, 0x16, 0x2f, 0xb5,
+ 0x27, 0xfd, 0xce, 0x2f, 0x35, 0x5d, 0x12, 0xa1,
+ 0x66, 0xac, 0xf7, 0x95, 0x38, 0x0f, 0xe5, 0xb1,
+ 0x18, 0x18, 0xe6, 0x80, 0x52, 0x31, 0x8a, 0x66,
+ 0x02, 0x52, 0x1a, 0xa4, 0x32, 0x6a, 0x61, 0x05,
+ 0xcf, 0x1d, 0xf9, 0x90, 0x73, 0xf0, 0xeb, 0x20,
+ 0x31, 0x7b, 0x2e, 0xc0, 0xb0, 0xfb, 0x5c, 0xcc,
+ 0xdc, 0x76, 0x55, 0x72, 0xaf, 0xb1, 0x05, 0xf4,
+ 0xad, 0xf9, 0xd7, 0x73, 0x5c, 0x2c, 0xbf, 0x0d,
+ 0x84, 0x18, 0x01, 0x1d, 0x4d, 0x08, 0xa9, 0x4e,
+ 0x37, 0xb7, 0x58, 0xc4, 0x05, 0x0e, 0x65, 0x63,
+ 0xd2, 0x88, 0x02, 0xf5, 0x82, 0x17, 0x08, 0xd5,
+ 0x8f, 0x80, 0xc7, 0x82, 0x29, 0xbb, 0xe1, 0x04,
+ 0xbe, 0xf6, 0xe1, 0x8c, 0xbc, 0x3a, 0xf8, 0xf9,
+ 0x56, 0xda, 0xdc, 0x8e, 0xc6, 0xe6, 0x63, 0x98,
+ 0x12, 0x08, 0x41, 0x2c, 0x9d, 0x7c, 0x82, 0x0d,
+ 0x1e, 0xea, 0xba, 0xde, 0x32, 0x09, 0xda, 0x52,
+ 0x24, 0x4f, 0xcc, 0xb6, 0x09, 0x33, 0x8b, 0x00,
+ 0xf9, 0x83, 0xb3, 0xc6, 0xa4, 0x90, 0x49, 0x83,
+ 0x2d, 0x36, 0xd9, 0x11, 0x78, 0xd0, 0x62, 0x9f,
+ 0xc4, 0x8f, 0x84, 0xba, 0x7f, 0xaa, 0x04, 0xf1,
+ 0xd9, 0xa4, 0xad, 0x5d, 0x63, 0xee, 0x72, 0xc6,
+ 0x4d, 0xd1, 0x4b, 0x41, 0x8f, 0x40, 0x0f, 0x7d,
+ 0xcd, 0xb8, 0x2e, 0x5b, 0x6e, 0x21, 0xc9, 0x3d
+ };
+
+ Flow f;
+ SSLState *ssl_state = NULL;
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacketReal(client_hello, sizeof(client_hello), IPPROTO_TCP,
+ "192.168.1.5", "192.168.1.1", 51251, 443);
+ p2 = UTHBuildPacketReal(server_hello, sizeof(server_hello), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+ p3 = UTHBuildPacketReal(certificate, sizeof(certificate), IPPROTO_TCP,
+ "192.168.1.1", "192.168.1.5", 443, 51251);
+
+ FLOW_INITIALIZE(&f);
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ f.protomap = FlowGetProtoMapping(f.proto);
+ f.alproto = ALPROTO_TLS;
+
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->pcap_cnt = 1;
+
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p2->flowflags |= FLOW_PKT_TOCLIENT;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->pcap_cnt = 2;
+
+ p3->flow = &f;
+ p3->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+ p3->flowflags |= FLOW_PKT_TOCLIENT;
+ p3->flowflags |= FLOW_PKT_ESTABLISHED;
+ p3->pcap_cnt = 3;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->mpm_matcher = mpm_default_matcher;
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
+ "(msg:\"Test tls.certs\"; tls.certs; "
+ "content:\"|06 09 2a 86 48|\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+ STREAM_TOSERVER, client_hello,
+ sizeof(client_hello));
+
+ FAIL_IF(r != 0);
+
+ ssl_state = f.alstate;
+ FAIL_IF_NULL(ssl_state);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ FAIL_IF(PacketAlertCheck(p1, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ server_hello, sizeof(server_hello));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ FAIL_IF(PacketAlertCheck(p2, 1));
+
+ r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+ certificate, sizeof(certificate));
+
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
+
+ FAIL_IF_NOT(PacketAlertCheck(p3, 1));
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ UTHFreePacket(p1);
+ UTHFreePacket(p2);
+ UTHFreePacket(p3);
+
+ PASS;
+}
+
+static void DetectTlsCertsRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsCertsTest01", DetectTlsCertsTest01);
+ UtRegisterTest("DetectTlsCertsTest02", DetectTlsCertsTest02);
+}
diff --git a/src/tests/detect-tls-version.c b/src/tests/detect-tls-version.c
new file mode 100644
index 0000000..3f55faa
--- /dev/null
+++ b/src/tests/detect-tls-version.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2007-2019 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 Victor Julien <victor@inliniac.net>
+ *
+ */
+
+#include "detect-engine-build.h"
+#include "app-layer-parser.h"
+
+/**
+ * \test DetectTlsVersionTestParse01 is a test to make sure that we parse the "id"
+ * option correctly when given valid id option
+ */
+static int DetectTlsVersionTestParse01 (void)
+{
+ DetectTlsVersionData *tls = NULL;
+ tls = DetectTlsVersionParse(NULL, "1.0");
+ FAIL_IF_NULL(tls);
+ FAIL_IF_NOT(tls->ver == TLS_VERSION_10);
+ DetectTlsVersionFree(NULL, tls);
+ PASS;
+}
+
+/**
+ * \test DetectTlsVersionTestParse02 is a test to make sure that we parse the "id"
+ * option correctly when given an invalid id option
+ * it should return id_d = NULL
+ */
+static int DetectTlsVersionTestParse02 (void)
+{
+ DetectTlsVersionData *tls = NULL;
+ tls = DetectTlsVersionParse(NULL, "2.5");
+ FAIL_IF_NOT_NULL(tls);
+ DetectTlsVersionFree(NULL, tls);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTlsVersion
+ */
+static void DetectTlsVersionRegisterTests(void)
+{
+ UtRegisterTest("DetectTlsVersionTestParse01", DetectTlsVersionTestParse01);
+ UtRegisterTest("DetectTlsVersionTestParse02", DetectTlsVersionTestParse02);
+}
diff --git a/src/tests/detect-transform-pcrexform.c b/src/tests/detect-transform-pcrexform.c
new file mode 100644
index 0000000..be23615
--- /dev/null
+++ b/src/tests/detect-transform-pcrexform.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect-engine.h"
+
+#include "../detect-transform-pcrexform.h"
+
+#include "../util-unittest.h"
+
+/**
+ * \test signature with an invalid pcrexform value.
+ */
+
+static int DetectTransformPcrexformParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any <> any 1 pcrexform:\"[\";");
+ FAIL_IF_NOT_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test signature with a valid pcrexform value.
+ */
+
+static int DetectTransformPcrexformParseTest02 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any (msg:\"HTTP with pcrexform\"; http.request_line; pcrexform:\"[a-zA-Z]+\\s+(.*)\\s+HTTP\"; content:\"/z4d4kWk.jpg\"; sid:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test signature with a pcrexform value without substring capture
+ */
+
+static int DetectTransformPcrexformParseTest03(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any (msg:\"HTTP with pcrexform\"; http.request_line; "
+ "pcrexform:\"No-match\"; content:\"/no-match.jpg\"; sid:1;)");
+ FAIL_IF_NOT_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTransformPcrexform
+ */
+void DetectTransformPcrexformRegisterTests(void)
+{
+ UtRegisterTest("DetectTransformPcrexformParseTest01", DetectTransformPcrexformParseTest01);
+ UtRegisterTest("DetectTransformPcrexformParseTest02", DetectTransformPcrexformParseTest02);
+ UtRegisterTest("DetectTransformPcrexformParseTest03", DetectTransformPcrexformParseTest03);
+}
diff --git a/src/tests/detect-transform-xor.c b/src/tests/detect-transform-xor.c
new file mode 100644
index 0000000..3a73665
--- /dev/null
+++ b/src/tests/detect-transform-xor.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 2021 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect-engine.h"
+
+#include "../detect-transform-xor.h"
+
+#include "../util-unittest.h"
+
+/**
+ * \test signature with an invalid xor value.
+ */
+
+static int DetectTransformXorParseTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx, "alert tcp any any <> any 1 xor:\"nohexa\";");
+ FAIL_IF_NOT_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test signature with a valid xor value.
+ */
+
+static int DetectTransformXorParseTest02(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert http any any -> any any (msg:\"HTTP with xor\"; http.request_line; "
+ "xor:\"0a0DC8ff\"; content:\"/z4d4kWk.jpg\"; sid:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTransformXor
+ */
+void DetectTransformXorRegisterTests(void)
+{
+ UtRegisterTest("DetectTransformXorParseTest01", DetectTransformXorParseTest01);
+ UtRegisterTest("DetectTransformXorParseTest02", DetectTransformXorParseTest02);
+}
diff --git a/src/tests/detect-ttl.c b/src/tests/detect-ttl.c
new file mode 100644
index 0000000..7494931
--- /dev/null
+++ b/src/tests/detect-ttl.c
@@ -0,0 +1,223 @@
+
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../util-unittest.h"
+#include "../util-unittest-helper.h"
+#include "detect-engine.h"
+#include "detect-engine-alert.h"
+#include "detect-engine-build.h"
+
+/**
+ * \test DetectTtlParseTest01 is a test for setting up an valid ttl value.
+ */
+
+static int DetectTtlParseTest01 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse("10");
+ FAIL_IF_NULL(ttld);
+ FAIL_IF_NOT(ttld->arg1 == 10);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_EQ);
+ DetectTtlFree(NULL, ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest02 is a test for setting up an valid ttl value with
+ * "<" operator.
+ */
+
+static int DetectTtlParseTest02 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse("<10");
+ FAIL_IF_NULL(ttld);
+ FAIL_IF_NOT(ttld->arg1 == 10);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_LT);
+ DetectTtlFree(NULL, ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest03 is a test for setting up an valid ttl values with
+ * "-" operator.
+ */
+
+static int DetectTtlParseTest03 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse("1-3");
+ FAIL_IF_NULL(ttld);
+ FAIL_IF_NOT(ttld->arg1 == 1);
+ FAIL_IF_NOT(ttld->arg2 == 3);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_RA);
+ DetectTtlFree(NULL, ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest04 is a test for setting up an valid ttl value with
+ * ">" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest04 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse(" > 10 ");
+ FAIL_IF_NULL(ttld);
+ FAIL_IF_NOT(ttld->arg1 == 10);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_GT);
+ DetectTtlFree(NULL, ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest05 is a test for setting up an valid ttl values with
+ * "-" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest05 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse(" 1 - 3 ");
+ FAIL_IF_NULL(ttld);
+ FAIL_IF_NOT(ttld->arg1 == 1);
+ FAIL_IF_NOT(ttld->arg2 == 3);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_RA);
+ DetectTtlFree(NULL, ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest06 is a test for setting up an valid ttl values with
+ * invalid "=" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest06 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse(" 1 = 2 ");
+ FAIL_IF_NOT_NULL(ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlParseTest07 is a test for setting up an valid ttl values with
+ * invalid "<>" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest07 (void)
+{
+ DetectU8Data *ttld = DetectU8Parse(" 1<>2 ");
+ FAIL_IF_NOT_NULL(ttld);
+ PASS;
+}
+
+/**
+ * \test DetectTtlSetupTest01 is a test for setting up an valid ttl values with
+ * valid "-" operator and include spaces arround the given values. In the
+ * test the values are setup with initializing the detection engine context
+ * setting up the signature itself.
+ */
+
+static int DetectTtlSetupTest01(void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(
+ de_ctx, "alert ip any any -> any any (msg:\"with in ttl limit\"; ttl:1 - 3; sid:1;)");
+ FAIL_IF_NULL(s);
+ SigGroupBuild(de_ctx);
+ FAIL_IF_NULL(s->sm_arrays[DETECT_SM_LIST_MATCH]);
+ FAIL_IF_NULL(s->sm_arrays[DETECT_SM_LIST_MATCH]->ctx);
+ DetectU8Data *ttld = (DetectU8Data *)s->sm_arrays[DETECT_SM_LIST_MATCH]->ctx;
+
+ FAIL_IF_NOT(ttld->arg1 == 1);
+ FAIL_IF_NOT(ttld->arg2 == 3);
+ FAIL_IF_NOT(ttld->mode == DETECT_UINT_RA);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \test DetectTtlTestSig01 is a test for checking the working of ttl keyword
+ * by setting up the signature and later testing its working by matching
+ * the received packet against the sig.
+ */
+
+static int DetectTtlTestSig1(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Signature *s = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx;
+ IPV4Hdr ip4h;
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&ip4h, 0, sizeof(ip4h));
+
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->proto = IPPROTO_TCP;
+ ip4h.ip_ttl = 15;
+ p->ip4h = &ip4h;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"with in ttl limit\"; ttl: >16; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Less than 17\"; ttl: <17; sid:2;)");
+ FAIL_IF_NULL(s);
+
+ s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Greater than 5\"; ttl:15; sid:3;)");
+ FAIL_IF_NULL(s);
+
+ s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Equals tcp\"; ttl: 1-30; sid:4;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF(PacketAlertCheck(p, 1));
+ FAIL_IF_NOT(PacketAlertCheck(p, 2));
+ FAIL_IF_NOT(PacketAlertCheck(p, 3));
+ FAIL_IF_NOT(PacketAlertCheck(p, 4));
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ SCFree(p);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTtl
+ */
+void DetectTtlRegisterTests(void)
+{
+ UtRegisterTest("DetectTtlParseTest01", DetectTtlParseTest01);
+ UtRegisterTest("DetectTtlParseTest02", DetectTtlParseTest02);
+ UtRegisterTest("DetectTtlParseTest03", DetectTtlParseTest03);
+ UtRegisterTest("DetectTtlParseTest04", DetectTtlParseTest04);
+ UtRegisterTest("DetectTtlParseTest05", DetectTtlParseTest05);
+ UtRegisterTest("DetectTtlParseTest06", DetectTtlParseTest06);
+ UtRegisterTest("DetectTtlParseTest07", DetectTtlParseTest07);
+ UtRegisterTest("DetectTtlSetupTest01", DetectTtlSetupTest01);
+ UtRegisterTest("DetectTtlTestSig1", DetectTtlTestSig1);
+}
diff --git a/src/tests/detect-udphdr.c b/src/tests/detect-udphdr.c
new file mode 100644
index 0000000..5e661fb
--- /dev/null
+++ b/src/tests/detect-udphdr.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-tcphdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectUdphdrParseTest01 (void)
+{
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ Signature *sig = DetectEngineAppendSig(de_ctx,
+ "alert udp any any -> any any (udp.hdr; content:\"A\"; sid:1; rev:1;)");
+ FAIL_IF_NULL(sig);
+
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectUdphdr
+ */
+void DetectUdphdrRegisterTests(void)
+{
+ UtRegisterTest("DetectUdphdrParseTest01", DetectUdphdrParseTest01);
+}
diff --git a/src/tests/detect.c b/src/tests/detect.c
new file mode 100644
index 0000000..302666a
--- /dev/null
+++ b/src/tests/detect.c
@@ -0,0 +1,5150 @@
+/* Copyright (C) 2007-2017 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.
+ */
+
+#ifdef UNITTESTS
+
+#include "../app-layer-htp.h"
+#include "../conf-yaml-loader.h"
+#include "../detect-parse.h"
+#include "../detect-engine-content-inspection.h"
+#include "../detect-engine-build.h"
+#include "../pkt-var.h"
+#include "../flow-util.h"
+#include "../stream-tcp-reassemble.h"
+#include "../util-unittest.h"
+#include "../util-var-name.h"
+#include "../util-unittest-helper.h"
+
+static const char *dummy_conf_string =
+ "%YAML 1.1\n"
+ "---\n"
+ "\n"
+ "default-log-dir: /var/log/suricata\n"
+ "\n"
+ "logging:\n"
+ "\n"
+ " default-log-level: debug\n"
+ "\n"
+ " default-format: \"<%t> - <%l>\"\n"
+ "\n"
+ " default-startup-message: Your IDS has started.\n"
+ "\n"
+ " default-output-filter:\n"
+ "\n"
+ " output:\n"
+ "\n"
+ " - interface: console\n"
+ " log-level: info\n"
+ "\n"
+ " - interface: file\n"
+ " filename: /var/log/suricata.log\n"
+ "\n"
+ " - interface: syslog\n"
+ " facility: local5\n"
+ " format: \"%l\"\n"
+ "\n"
+ "pfring:\n"
+ "\n"
+ " interface: eth0\n"
+ "\n"
+ " clusterid: 99\n"
+ "\n"
+ "vars:\n"
+ "\n"
+ " address-groups:\n"
+ "\n"
+ " HOME_NET: \"[192.168.0.0/16,10.8.0.0/16,127.0.0.1,2001:888:"
+ "13c5:5AFE::/64,2001:888:13c5:CAFE::/64]\"\n"
+ "\n"
+ " EXTERNAL_NET: \"[!192.168.0.0/16,2000::/3]\"\n"
+ "\n"
+ " HTTP_SERVERS: \"!192.168.0.0/16\"\n"
+ "\n"
+ " SMTP_SERVERS: \"!192.168.0.0/16\"\n"
+ "\n"
+ " SQL_SERVERS: \"!192.168.0.0/16\"\n"
+ "\n"
+ " DNS_SERVERS: any\n"
+ "\n"
+ " TELNET_SERVERS: any\n"
+ "\n"
+ " AIM_SERVERS: any\n"
+ "\n"
+ " port-groups:\n"
+ "\n"
+ " HTTP_PORTS: \"80:81,88\"\n"
+ "\n"
+ " SHELLCODE_PORTS: 80\n"
+ "\n"
+ " ORACLE_PORTS: 1521\n"
+ "\n"
+ " SSH_PORTS: 22\n"
+ "\n";
+
+static int SigTest01 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n"
+ "Host: one.example.org\r\n"
+ "\r\n\r\n"
+ "GET /two/ HTTP/1.1\r\n"
+ "Host: two.example.org\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
+ int result = 0;
+
+ char sig[] = "alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)";
+ if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
+ result = 0;
+ goto end;
+ }
+#if 0
+ //printf("URI0 \"%s\", len %" PRIu32 "\n", p.http_uri.raw[0], p.http_uri.raw_size[0]);
+ //printf("URI1 \"%s\", len %" PRIu32 "\n", p.http_uri.raw[1], p.http_uri.raw_size[1]);
+
+ if (p->http_uri.raw_size[0] == 5 &&
+ memcmp(p->http_uri.raw[0], "/one/", 5) == 0 &&
+ p->http_uri.raw_size[1] == 5 &&
+ memcmp(p->http_uri.raw[1], "/two/", 5) == 0)
+ {
+ result = 1;
+ }
+
+#endif
+ result = 1;
+end:
+ if (p != NULL)
+ UTHFreePacket(p);
+ return result;
+}
+
+static int SigTest02 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n"
+ "Host: one.example.org\r\n"
+ "\r\n\r\n"
+ "GET /two/ HTTP/1.1\r\n"
+ "Host: two.example.org\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
+ char sig[] = "alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host: one.example.org\"; offset:20; depth:41; sid:1;)";
+ int ret = UTHPacketMatchSigMpm(p, sig, MPM_AC);
+ UTHFreePacket(p);
+ return ret;
+}
+
+static int SigTest03 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n"
+ "Host: one.example.org\r\n"
+ "\r\n\r\n"
+ "GET /two/ HTTP/1.1\r\n"
+ "Host: two.example.org\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host: one.example.org\"; offset:20; depth:39; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTest04 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n" /* 20*/
+ "Host: one.example.org\r\n" /* 23, post "Host:" 18 */
+ "\r\n\r\n" /* 4 */
+ "GET /two/ HTTP/1.1\r\n" /* 20 */
+ "Host: two.example.org\r\n" /* 23 */
+ "\r\n\r\n"; /* 4 */
+ uint16_t buflen = strlen((char *)buf);
+
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host:\"; offset:20; depth:25; content:\"Host:\"; distance:42; within:47; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTest05 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.1\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host:\"; offset:20; depth:25; content:\"Host:\"; distance:48; within:52; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("sig parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!PacketAlertCheck(p, 1)) {
+ result = 1;
+ } else {
+ printf("sig matched but shouldn't have: ");
+ }
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTest06 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.1\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+ FAIL_IF_NULL(p);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+ FAIL_IF_NULL(det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buflen);
+ FAIL_IF(r != 0);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+ FAIL_IF_NOT(PacketAlertCheck(p, 2));
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ AppLayerParserThreadCtxFree(alp_tctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ PASS;
+}
+
+static int SigTest07 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.1\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"three\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buflen);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
+ result = 0;
+ else
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FlowCleanupAppLayer(&f);
+ FLOW_DESTROY(&f);
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ return result;
+}
+
+static int SigTest08 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.0\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.0\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/1\\.0\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"one\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buflen);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
+ result = 1;
+ else
+ printf("sid:1 %s, sid:2 %s: ",
+ PacketAlertCheck(p, 1) ? "OK" : "FAIL",
+ PacketAlertCheck(p, 2) ? "OK" : "FAIL");
+
+end:
+ FlowCleanupAppLayer(&f);
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ if (det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest09 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.0\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.0\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.flags |= FLOW_IPV4;
+ f.proto = IPPROTO_TCP;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/1\\.0\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI test\"; uricontent:\"two\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buflen);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
+ result = 1;
+ else
+ result = 0;
+
+end:
+ FlowCleanupAppLayer(&f);
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest10 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "ABC";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ int result = 0;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Long content test (1)\"; content:\"ABCD\"; depth:4; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Long content test (2)\"; content:\"VWXYZ\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, buf, buflen);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ result = 0;
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
+ result = 0;
+ else
+ result = 1;
+
+ end:
+ FlowCleanupAppLayer(&f);
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest11 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ Flow f;
+ TcpSession ssn;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&f, 0, sizeof(f));
+ memset(&ssn, 0, sizeof(ssn));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+ p->flow = &f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (content:\"ABCDEFGHIJ\"; content:\"klmnop\"; content:\"1234\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (content:\"VWXYZabcde\"; content:\"5678\"; content:\"89\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1) && PacketAlertCheck(p, 2))
+ result = 1;
+
+ end:
+ FlowCleanupAppLayer(&f);
+ SigGroupCleanup(de_ctx);
+ if (det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ UTHFreePackets(&p, 1);
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest12 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Flow f;
+ memset(&f, 0, sizeof(Flow));
+
+ FLOW_INITIALIZE(&f);
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Content order test\"; content:\"ABCDEFGHIJ\"; content:\"klmnop\"; content:\"1234\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+ else
+ result = 0;
+
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ if (de_ctx != NULL) {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+ }
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest13 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Flow f;
+ memset(&f, 0, sizeof(Flow));
+
+ FLOW_INITIALIZE(&f);
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+ p->flow = &f;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Content order test\"; content:\"ABCDEFGHIJ\"; content:\"1234\"; content:\"klmnop\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+ else
+ result = 0;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest14 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Content order test\"; content:\"ABCDEFGHIJ\"; content:\"1234\"; content:\"klmnop\"; distance:0; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 0;
+ else
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTest15 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "CONNECT 213.92.8.7:31204 HTTP/1.1";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->dp = 80;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any !$HTTP_PORTS (msg:\"ET POLICY Inbound HTTP CONNECT Attempt on Off-Port\"; content:\"CONNECT \"; nocase; depth:8; content:\" HTTP/1.\"; nocase; within:1000; sid:2008284; rev:2;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 2008284))
+ result = 0;
+ else
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ return result;
+}
+
+static int SigTest16 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "CONNECT 213.92.8.7:31204 HTTP/1.1";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&p, 0, sizeof(p));
+
+ p = UTHBuildPacketSrcDstPorts((uint8_t *)buf, buflen, IPPROTO_TCP, 12345, 1234);
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any !$HTTP_PORTS (msg:\"ET POLICY Inbound HTTP CONNECT Attempt on Off-Port\"; content:\"CONNECT \"; nocase; depth:8; content:\" HTTP/1.\"; nocase; within:1000; sid:2008284; rev:2;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 2008284))
+ result = 1;
+ else
+ printf("sid:2008284 %s: ", PacketAlertCheck(p, 2008284) ? "OK" : "FAIL");
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTest17 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n" /* 20 */
+ "Host: one.example.org\r\n" /* 23, 43 */
+ "\r\n\r\n" /* 4, 47 */
+ "GET /two/ HTTP/1.1\r\n" /* 20, 67 */
+ "Host: two.example.org\r\n" /* 23, 90 */
+ "\r\n\r\n"; /* 4, 94 */
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacketSrcDstPorts((uint8_t *)buf, buflen, IPPROTO_TCP, 12345, 80);
+ FAIL_IF_NULL(p);
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,"alert tcp any any -> any $HTTP_PORTS (msg:\"HTTP host cap\"; content:\"Host:\"; pcre:\"/^Host: (?P<pkt_http_host>.*)\\r\\n/m\"; noalert; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ uint32_t capid = VarNameStoreLookupByName("http_host", VAR_TYPE_PKT_VAR);
+
+ PktVar *pv_hn = PktVarGet(p, capid);
+ FAIL_IF_NULL(pv_hn);
+
+ FAIL_IF(pv_hn->value_len != 15);
+ FAIL_IF_NOT(memcmp(pv_hn->value, "one.example.org", pv_hn->value_len) == 0);
+
+ PktVarFree(pv_hn);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ UTHFreePackets(&p, 1);
+
+ PASS;
+}
+
+static int SigTest18 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "220 (vsFTPd 2.0.5)\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->dp = 34260;
+ p->sp = 21;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any !21:902 -> any any (msg:\"ET MALWARE Suspicious 220 Banner on Local Port\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:2003055; rev:4;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (!PacketAlertCheck(p, 2003055))
+ result = 1;
+ else
+ printf("signature shouldn't match, but did: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p);
+ return result;
+}
+
+static int SigTest19 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "220 (vsFTPd 2.0.5)\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ p->src.family = AF_INET;
+ p->src.addr_data32[0] = UTHSetIPv4Address("192.168.0.1");
+ p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->dp = 34260;
+ p->sp = 21;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert ip $HOME_NET any -> 1.2.3.4 any (msg:\"IP-ONLY test (1)\"; sid:999; rev:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 999))
+ result = 1;
+ else
+ printf("signature didn't match, but should have: ");
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ return result;
+}
+
+static int SigTest20 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "220 (vsFTPd 2.0.5)\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ p->src.family = AF_INET;
+ p->src.addr_data32[0] = UTHSetIPv4Address("192.168.0.1");
+ p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->dp = 34260;
+ p->sp = 21;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert ip $HOME_NET any -> [99.99.99.99,1.2.3.0/24,1.1.1.1,3.0.0.0/8] any (msg:\"IP-ONLY test (2)\"; sid:999; rev:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 999))
+ result = 1;
+ else
+ printf("signature didn't match, but should have: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ return result;
+}
+
+static int SigTest21 (void)
+{
+ ThreadVars th_v;
+ memset(&th_v, 0, sizeof(th_v));
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ Flow f;
+ memset(&f, 0, sizeof(f));
+ FLOW_INITIALIZE(&f);
+
+ /* packet 1 */
+ uint8_t *buf1 = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf1len = strlen((char *)buf1);
+ Packet *p1 = NULL;
+ /* packet 2 */
+ uint8_t *buf2 = (uint8_t *)"GET /two/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf2len = strlen((char *)buf2);
+ Packet *p2 = NULL;
+
+ p1 = UTHBuildPacket((uint8_t *)buf1, buf1len, IPPROTO_TCP);
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ p2 = UTHBuildPacket((uint8_t *)buf2, buf2len, IPPROTO_TCP);
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT SET\"; content:\"/one/\"; flowbits:set,TEST.one; flowbits:noalert; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT TEST\"; content:\"/two/\"; flowbits:isset,TEST.one; sid:2;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 alerted, but shouldn't: ");
+ goto end;
+ }
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 2))) {
+ printf("sid 2 didn't alert, but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (de_ctx != NULL) {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ if (det_ctx != NULL) {
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ }
+ }
+ DetectEngineCtxFree(de_ctx);
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest22 (void)
+{
+ ThreadVars th_v;
+ memset(&th_v, 0, sizeof(th_v));
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ Flow f;
+ memset(&f, 0, sizeof(f));
+ FLOW_INITIALIZE(&f);
+
+ /* packet 1 */
+ uint8_t *buf1 = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf1len = strlen((char *)buf1);
+ Packet *p1 = NULL;
+
+ p1 = UTHBuildPacket((uint8_t *)buf1, buf1len, IPPROTO_TCP);
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ /* packet 2 */
+ uint8_t *buf2 = (uint8_t *)"GET /two/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf2len = strlen((char *)buf2);
+ Packet *p2 = NULL;
+
+ p2 = UTHBuildPacket((uint8_t *)buf2, buf2len, IPPROTO_TCP);
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT SET\"; content:\"/one/\"; flowbits:set,TEST.one; flowbits:noalert; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT TEST\"; content:\"/two/\"; flowbits:isset,TEST.abc; sid:2;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 alerted, but shouldn't: ");
+ goto end;
+ }
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 2)))
+ result = 1;
+ else
+ printf("sid 2 alerted, but shouldn't: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest23 (void)
+{
+ ThreadVars th_v;
+ memset(&th_v, 0, sizeof(th_v));
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ Flow f;
+ memset(&f, 0, sizeof(f));
+ FLOW_INITIALIZE(&f);
+
+ /* packet 1 */
+ uint8_t *buf1 = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf1len = strlen((char *)buf1);
+ Packet *p1 = NULL;
+
+ p1 = UTHBuildPacket((uint8_t *)buf1, buf1len, IPPROTO_TCP);
+ p1->flow = &f;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ /* packet 2 */
+ uint8_t *buf2 = (uint8_t *)"GET /two/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buf2len = strlen((char *)buf2);
+ Packet *p2 = NULL;
+
+ p2 = UTHBuildPacket((uint8_t *)buf2, buf2len, IPPROTO_TCP);
+ p2->flow = &f;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT SET\"; content:\"/one/\"; flowbits:toggle,TEST.one; flowbits:noalert; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"FLOWBIT TEST\"; content:\"/two/\"; flowbits:isset,TEST.one; sid:2;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sid 1 alerted, but shouldn't: ");
+ goto end;
+ }
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ result = 1;
+ else
+ printf("sid 2 didn't alert, but should have: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+ FLOW_DESTROY(&f);
+ return result;
+}
+
+static int SigTest24IPV4Keyword(void)
+{
+ uint8_t valid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t invalid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03,
+ 0xc0, 0xa8, 0x01, 0x06};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+ PACKET_RESET_CHECKSUMS(p1);
+ PACKET_RESET_CHECKSUMS(p2);
+
+ p1->ip4h = (IPV4Hdr *)valid_raw_ipv4;
+
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_TCP;
+
+ p2->ip4h = (IPV4Hdr *)invalid_raw_ipv4;
+
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = buflen;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"/one/\"; ipv4-csum:valid; "
+ "msg:\"ipv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("sig 1 parse: ");
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"/one/\"; ipv4-csum:invalid; "
+ "msg:\"ipv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ printf("sig 2 parse: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("signature 1 didn't match, but should have: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!((PacketAlertCheck(p2, 2)))) {
+ printf("signature 2 didn't match, but should have: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ if (det_ctx != NULL) {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ }
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest25NegativeIPV4Keyword(void)
+{
+ uint8_t valid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t invalid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03,
+ 0xc0, 0xa8, 0x01, 0x06};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+ PACKET_RESET_CHECKSUMS(p1);
+ PACKET_RESET_CHECKSUMS(p2);
+
+ p1->ip4h = (IPV4Hdr *)valid_raw_ipv4;
+
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_TCP;
+
+ p2->ip4h = (IPV4Hdr *)invalid_raw_ipv4;
+
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = buflen;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"/one/\"; ipv4-csum:invalid; "
+ "msg:\"ipv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"/one/\"; ipv4-csum:valid; "
+ "msg:\"ipv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest26TCPV4Keyword(void)
+{
+ uint8_t raw_ipv4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x7e, 0xb2,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t valid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0x4A, 0x04, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02};
+
+ uint8_t invalid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PacketCopyData(p1, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p1, GET_PKT_LEN(p1), valid_raw_tcp, sizeof(valid_raw_tcp));
+
+ PacketCopyData(p2, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p2, GET_PKT_LEN(p2), invalid_raw_tcp, sizeof(invalid_raw_tcp));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)GET_PKT_DATA(p1);
+ p1->tcph = (TCPHdr *)(GET_PKT_DATA(p1) + sizeof(raw_ipv4));
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = (uint8_t *)GET_PKT_DATA(p1) + sizeof(raw_ipv4) + 20;
+ p1->payload_len = 20;
+ p1->proto = IPPROTO_TCP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)GET_PKT_DATA(p2);
+ p2->tcph = (TCPHdr *)(GET_PKT_DATA(p2) + sizeof(raw_ipv4));
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = (uint8_t *)GET_PKT_DATA(p2) + sizeof(raw_ipv4) + 20;
+ p2->payload_len = 20;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:valid; dsize:20; "
+ "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:invalid; "
+ "msg:\"tcpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ FAIL_IF_NULL(de_ctx->sig_list->next);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF(!(PacketAlertCheck(p1, 1)));
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF(!(PacketAlertCheck(p2, 2)));
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ PASS;
+}
+
+/* Test SigTest26TCPV4Keyword but also check for invalid IPV4 checksum */
+static int SigTest26TCPV4AndNegativeIPV4Keyword(void)
+{
+ uint8_t raw_ipv4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x7e, 0xb2,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t valid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0x4A, 0x04, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02};
+
+ uint8_t invalid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PacketCopyData(p1, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p1, GET_PKT_LEN(p1), valid_raw_tcp, sizeof(valid_raw_tcp));
+
+ PacketCopyData(p2, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p2, GET_PKT_LEN(p2), invalid_raw_tcp, sizeof(invalid_raw_tcp));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)GET_PKT_DATA(p1);
+ p1->tcph = (TCPHdr *)(GET_PKT_DATA(p1) + sizeof(raw_ipv4));
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = (uint8_t *)GET_PKT_DATA(p1) + sizeof(raw_ipv4) + 20;
+ p1->payload_len = 20;
+ p1->proto = IPPROTO_TCP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)GET_PKT_DATA(p2);
+ p2->tcph = (TCPHdr *)(GET_PKT_DATA(p2) + sizeof(raw_ipv4));
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = (uint8_t *)GET_PKT_DATA(p2) + sizeof(raw_ipv4) + 20;
+ p2->payload_len = 20;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:valid; dsize:20; "
+ "ipv4-csum:invalid; "
+ "msg:\"tcpv4-csum and ipv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:invalid; "
+ "ipv4-csum:invalid; "
+ "msg:\"tcpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sig 1 didn't match: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 2))) {
+ printf("sig 2 didn't match: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+/* Similar to SigTest26, but with different packet */
+static int SigTest26TCPV4AndIPV4Keyword(void)
+{
+ /* IPV4: src:192.168.176.67 dst: 192.168.176.116
+ * TTL: 64 Flags: Don't Fragment
+ */
+ uint8_t raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x40, 0x9b, 0xa4, 0x40, 0x00,
+ 0x40, 0x06, 0xbd, 0x0a, 0xc0, 0xa8, 0xb0, 0x43,
+ 0xc0, 0xa8, 0xb0, 0x74};
+
+ /* TCP: sport: 49517 dport: 445 Flags: SYN
+ * Window size: 65535, checksum: 0x2009,
+ * MTU: 1460, Window scale: 4, TSACK permitted,
+ * 24 bytes of options, no payload.
+ */
+ uint8_t valid_raw_tcp[] = {
+ 0xc1, 0x6d, 0x01, 0xbd, 0x03, 0x10, 0xd3, 0xc9,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xff, 0xff,
+ 0x20, 0x09, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x01, 0x03, 0x03, 0x04, 0x01, 0x01, 0x08, 0x0a,
+ 0x19, 0x69, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x02, 0x00, 0x00};
+
+ uint8_t invalid_raw_tcp[] = {
+ 0xc1, 0x6d, 0x01, 0xbd, 0x03, 0x10, 0xd3, 0xc9,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xff, 0xff,
+ 0x20, 0x09, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x01, 0x03, 0x03, 0x04, 0x01, 0x01, 0x08, 0x0a,
+ 0x19, 0x69, 0x81, 0x7e, 0xFF, 0xAA, 0x00, 0x00,
+ 0x04, 0x02, 0x00, 0x00};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PacketCopyData(p1, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p1, GET_PKT_LEN(p1), valid_raw_tcp, sizeof(valid_raw_tcp));
+
+ PacketCopyData(p2, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p2, GET_PKT_LEN(p2), invalid_raw_tcp, sizeof(invalid_raw_tcp));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)GET_PKT_DATA(p1);
+ p1->tcph = (TCPHdr *)(GET_PKT_DATA(p1) + sizeof(raw_ipv4));
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = (uint8_t *)GET_PKT_DATA(p1) + sizeof(raw_ipv4) + 20 + 24;
+ p1->payload_len = 0;
+ p1->proto = IPPROTO_TCP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)GET_PKT_DATA(p2);
+ p2->tcph = (TCPHdr *)(GET_PKT_DATA(p2) + sizeof(raw_ipv4));
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = (uint8_t *)GET_PKT_DATA(p2) + sizeof(raw_ipv4) + 20 + 24;
+ p2->payload_len = 0;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(tcpv4-csum:valid; "
+ "ipv4-csum:valid; "
+ "msg:\"tcpv4-csum and ipv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert ip any any -> any any "
+ "(tcpv4-csum:invalid; "
+ "ipv4-csum:valid; "
+ "msg:\"tcpv4-csum and ipv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sig 1 didn't match: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 2))) {
+ printf("sig 2 didn't match: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest27NegativeTCPV4Keyword(void)
+{
+ uint8_t raw_ipv4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x7e, 0xb2,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t valid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x02};
+
+ uint8_t invalid_raw_tcp[] = {
+ 0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
+ 0xcf, 0x0d, 0x21, 0x80, 0x50, 0x12, 0x16, 0xa0,
+ 0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+ 0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
+ 0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 0x03};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PacketCopyData(p1, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p1, GET_PKT_LEN(p1), valid_raw_tcp, sizeof(valid_raw_tcp));
+
+ PacketCopyData(p2, raw_ipv4, sizeof(raw_ipv4));
+ PacketCopyDataOffset(p2, GET_PKT_LEN(p2), invalid_raw_tcp, sizeof(invalid_raw_tcp));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)GET_PKT_DATA(p1);
+ p1->tcph = (TCPHdr *)(GET_PKT_DATA(p1) + sizeof(raw_ipv4));
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = (uint8_t *)GET_PKT_DATA(p1) + sizeof(raw_ipv4) + 20;
+ p1->payload_len = 20;
+ p1->proto = IPPROTO_TCP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)GET_PKT_DATA(p2);
+ p2->tcph = (TCPHdr *)(GET_PKT_DATA(p2) + sizeof(raw_ipv4));
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = (uint8_t *)GET_PKT_DATA(p2) + sizeof(raw_ipv4) + 20;
+ p2->payload_len = 20;
+ p2->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:invalid; dsize:20; "
+ "msg:\"tcpv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|DE 01 03|\"; tcpv4-csum:valid; dsize:20; "
+ "msg:\"tcpv4-csum keyword check(2)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!PacketAlertCheck(p1, 1)) {
+ printf("sig 1 didn't match on p1: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2)) {
+ printf("sig 2 matched on p2: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest28TCPV6Keyword(void)
+{
+ static uint8_t valid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd,
+
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40,
+ 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda,
+ 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00,
+ 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e,
+
+ 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d,
+ 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c,
+ 0xf2, 0xf1, 0x00, 0x00,
+
+ 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a,
+ 0x00, 0x01, 0x69, 0x27};
+
+ static uint8_t invalid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd,
+
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40,
+ 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda,
+ 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00,
+ 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e,
+
+ 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d,
+ 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c,
+ 0xc2, 0xf1, 0x00, 0x00,
+
+ 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a,
+ 0x00, 0x01, 0x69, 0x28};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14);
+ p1->tcph = (TCPHdr *) (valid_raw_ipv6 + 54);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = valid_raw_ipv6 + 54 + 20;
+ p1->payload_len = 12;
+ p1->proto = IPPROTO_TCP;
+
+ if (TCP_GET_HLEN(p1) != 20) {
+ BUG_ON(1);
+ }
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14);
+ p2->tcph = (TCPHdr *) (invalid_raw_ipv6 + 54);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = invalid_raw_ipv6 + 54 + 20;
+ p2->payload_len = 12;
+ p2->proto = IPPROTO_TCP;
+
+ if (TCP_GET_HLEN(p2) != 20) {
+ BUG_ON(1);
+ }
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|00 01 69|\"; tcpv6-csum:valid; dsize:12; "
+ "msg:\"tcpv6-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|00 01 69|\"; tcpv6-csum:invalid; dsize:12; "
+ "msg:\"tcpv6-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!(PacketAlertCheck(p1, 1))) {
+ printf("sid 1 didn't match on p1: ");
+ goto end;
+ }
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 2))) {
+ printf("sid 2 didn't match on p2: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest29NegativeTCPV6Keyword(void)
+{
+ static uint8_t valid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd,
+
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40,
+ 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda,
+ 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00,
+ 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e,
+
+ 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d,
+ 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c,
+ 0xf2, 0xf1, 0x00, 0x00,
+
+ 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a,
+ 0x00, 0x01, 0x69, 0x27};
+
+ static uint8_t invalid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd,
+
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40,
+ 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda,
+ 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00,
+ 0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e,
+
+ 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf5, 0x2d,
+ 0x0c, 0x7a, 0x08, 0x77, 0x50, 0x10, 0x21, 0x5c,
+ 0xc2, 0xf1, 0x00, 0x00,
+
+ 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x5a,
+ 0x00, 0x01, 0x69, 0x28};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14);
+ p1->tcph = (TCPHdr *) (valid_raw_ipv6 + 54);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = valid_raw_ipv6 + 54 + 20;
+ p1->payload_len = 12;
+ p1->proto = IPPROTO_TCP;
+
+ if (TCP_GET_HLEN(p1) != 20) {
+ BUG_ON(1);
+ }
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14);
+ p2->tcph = (TCPHdr *) (invalid_raw_ipv6 + 54);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = invalid_raw_ipv6 + 54 + 20;
+ p2->payload_len = 12;
+ p2->proto = IPPROTO_TCP;
+
+ if (TCP_GET_HLEN(p2) != 20) {
+ BUG_ON(1);
+ }
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|00 01 69|\"; tcpv6-csum:invalid; dsize:12; "
+ "msg:\"tcpv6-csum keyword check(1)\"; "
+ "sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"|00 01 69|\"; tcpv6-csum:valid; dsize:12; "
+ "msg:\"tcpv6-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ goto end;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ goto end;
+
+ result = 1;
+end:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest30UDPV4Keyword(void)
+{
+ uint8_t raw_ipv4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x00, 0xd0, 0x43, 0xdc, 0xdc,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t valid_raw_udp[] = {
+ 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
+ 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
+ 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
+ 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
+ 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
+ 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
+ 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0xc0, 0x26};
+
+ uint8_t invalid_raw_udp[] = {
+ 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
+ 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
+ 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
+ 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
+ 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
+ 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
+ 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0xc0, 0x27};
+
+ Packet *p1 = PacketGetFromAlloc();
+ FAIL_IF_NULL(p1);
+ Packet *p2 = PacketGetFromAlloc();
+ FAIL_IF_NULL(p2);
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n"
+ "\r\n\r\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)raw_ipv4;
+ p1->udph = (UDPHdr *)valid_raw_udp;
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = sizeof(valid_raw_udp) - UDP_HEADER_LEN;
+ p1->proto = IPPROTO_UDP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)raw_ipv4;
+ p2->udph = (UDPHdr *)invalid_raw_udp;
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = sizeof(invalid_raw_udp) - UDP_HEADER_LEN;
+ p2->proto = IPPROTO_UDP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv4-csum:valid; "
+ "msg:\"udpv4-csum keyword check(1)\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv4-csum:invalid; "
+ "msg:\"udpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ FAIL_IF_NULL(de_ctx->sig_list->next);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF_NOT(PacketAlertCheck(p1, 1));
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF_NOT(PacketAlertCheck(p2, 2));
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p1);
+ SCFree(p2);
+ PASS;
+}
+
+static int SigTest31NegativeUDPV4Keyword(void)
+{
+ uint8_t raw_ipv4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd0, 0x43, 0xdc, 0xdc,
+ 0xc0, 0xa8, 0x01, 0x03};
+
+ uint8_t valid_raw_udp[] = {
+ 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
+ 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
+ 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
+ 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
+ 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
+ 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
+ 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0xc0, 0x26};
+
+ uint8_t invalid_raw_udp[] = {
+ 0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
+ 0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
+ 0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
+ 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
+ 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
+ 0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
+ 0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0xc0, 0x27};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0yyyyyyyyyyyyyyyy\r\n"
+ "\r\n\r\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)raw_ipv4;
+ p1->udph = (UDPHdr *)valid_raw_udp;
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = sizeof(valid_raw_udp) - UDP_HEADER_LEN;
+ p1->proto = IPPROTO_UDP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)raw_ipv4;
+ p2->udph = (UDPHdr *)invalid_raw_udp;
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = sizeof(invalid_raw_udp) - UDP_HEADER_LEN;
+ p2->proto = IPPROTO_UDP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv4-csum:invalid; "
+ "msg:\"udpv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv4-csum:valid; "
+ "msg:\"udpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2)) {
+ result &= 0;
+ }
+ else
+ result &= 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+
+static int SigTest32UDPV6Keyword(void)
+{
+ static uint8_t valid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
+ 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
+ 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
+ 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
+ 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
+ 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
+ 0x09, 0x00};
+
+ static uint8_t invalid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
+ 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
+ 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
+ 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
+ 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
+ 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
+ 0x09, 0x01};
+
+ Packet *p1 = PacketGetFromAlloc();
+ FAIL_IF_NULL(p1);
+ Packet *p2 = PacketGetFromAlloc();
+ FAIL_IF_NULL(p2);
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP\r\n"
+ "\r\n\r\n";
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14);
+ p1->udph = (UDPHdr *) (valid_raw_ipv6 + 54);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = IPV6_GET_PLEN((p1)) - UDP_HEADER_LEN;
+ p1->proto = IPPROTO_UDP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14);
+ p2->udph = (UDPHdr *) (invalid_raw_ipv6 + 54);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = IPV6_GET_PLEN((p2)) - UDP_HEADER_LEN;
+ p2->proto = IPPROTO_UDP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv6-csum:valid; "
+ "msg:\"udpv6-csum keyword check(1)\"; sid:1;)");
+ FAIL_IF_NULL(de_ctx->sig_list);
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv6-csum:invalid; "
+ "msg:\"udpv6-csum keyword check(1)\"; "
+ "sid:2;)");
+ FAIL_IF_NULL(de_ctx->sig_list->next);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ FAIL_IF_NOT(PacketAlertCheck(p1, 1));
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ FAIL_IF_NOT(PacketAlertCheck(p2, 2));
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ SCFree(p1);
+ SCFree(p2);
+ PASS;
+}
+
+static int SigTest33NegativeUDPV6Keyword(void)
+{
+ static uint8_t valid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
+ 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
+ 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
+ 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
+ 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
+ 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
+ 0x09, 0x00};
+
+ static uint8_t invalid_raw_ipv6[] = {
+ 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
+ 0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
+ 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
+ 0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
+ 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
+ 0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
+ 0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
+ 0x09, 0x01};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP\r\n"
+ "\r\n\r\n";
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip6h = (IPV6Hdr *)(valid_raw_ipv6 + 14);
+ p1->udph = (UDPHdr *) (valid_raw_ipv6 + 54);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = IPV6_GET_PLEN((p1)) - UDP_HEADER_LEN;
+ p1->proto = IPPROTO_UDP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip6h = (IPV6Hdr *)(invalid_raw_ipv6 + 14);
+ p2->udph = (UDPHdr *) (invalid_raw_ipv6 + 54);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = IPV6_GET_PLEN((p2)) - UDP_HEADER_LEN;
+ p2->proto = IPPROTO_UDP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv6-csum:invalid; "
+ "msg:\"udpv6-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert udp any any -> any any "
+ "(content:\"/one/\"; udpv6-csum:valid; "
+ "msg:\"udpv6-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest34ICMPV4Keyword(void)
+{
+ uint8_t valid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01,
+ 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a,
+ 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37};
+
+ uint8_t invalid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01,
+ 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a,
+ 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x38};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)(valid_raw_ipv4);
+ p1->ip4h->ip_verhl = 69;
+ p1->icmpv4h = (ICMPV4Hdr *) (valid_raw_ipv4 + IPV4_GET_RAW_HLEN(p1->ip4h) * 4);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_ICMP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)(invalid_raw_ipv4);
+ p2->ip4h->ip_verhl = 69;
+ p2->icmpv4h = (ICMPV4Hdr *) (invalid_raw_ipv4 + IPV4_GET_RAW_HLEN(p2->ip4h) * 4);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = buflen;
+ p2->proto = IPPROTO_ICMP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"/one/\"; icmpv4-csum:valid; "
+ "msg:\"icmpv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"/one/\"; icmpv4-csum:invalid; "
+ "msg:\"icmpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ result &= 1;
+ else
+ result &= 0;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ result &= 1;
+ else
+ result &= 0;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest35NegativeICMPV4Keyword(void)
+{
+ uint8_t valid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01,
+ 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a,
+ 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37};
+
+ uint8_t invalid_raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00,
+ 0x40, 0x01, 0x3c, 0xa7, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc3, 0x01,
+ 0x2b, 0x36, 0x00, 0x01, 0x3f, 0x16, 0x9a, 0x4a,
+ 0x41, 0x63, 0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x38};
+
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ Packet *p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL)) {
+ SCFree(p1);
+ return 0;
+ }
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+
+ uint8_t *buf = (uint8_t *)"GET /one/ HTTP/1.0\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ip4h = (IPV4Hdr *)(valid_raw_ipv4);
+ p1->ip4h->ip_verhl = 69;
+ p1->icmpv4h = (ICMPV4Hdr *) (valid_raw_ipv4 + IPV4_GET_RAW_HLEN(p1->ip4h) * 4);
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = buf;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_ICMP;
+
+ PACKET_RESET_CHECKSUMS(p2);
+ p2->ip4h = (IPV4Hdr *)(invalid_raw_ipv4);
+ p2->ip4h->ip_verhl = 69;
+ p2->icmpv4h = (ICMPV4Hdr *) (invalid_raw_ipv4 + IPV4_GET_RAW_HLEN(p2->ip4h) * 4);
+ p2->src.family = AF_INET;
+ p2->dst.family = AF_INET;
+ p2->payload = buf;
+ p2->payload_len = buflen;
+ p2->proto = IPPROTO_ICMP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"/one/\"; icmpv4-csum:invalid; "
+ "msg:\"icmpv4-csum keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert icmp any any -> any any "
+ "(content:\"/one/\"; icmpv4-csum:valid; "
+ "msg:\"icmpv4-csum keyword check(1)\"; "
+ "sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1))
+ result &= 0;
+ else
+ result &= 1;
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (PacketAlertCheck(p2, 2))
+ result &= 0;
+ else {
+ result &= 1;
+ }
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p1);
+ SCFree(p2);
+ return result;
+}
+
+static int SigTest38(void)
+{
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+ uint8_t raw_eth[] = {
+ 0x00, 0x00, 0x03, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00
+ };
+ uint8_t raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x7d, 0xd8, 0xf3, 0x40, 0x00,
+ 0x40, 0x06, 0x63, 0x85, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01
+ };
+ uint8_t raw_tcp[] = {
+ 0xad, 0x22, 0x04, 0x00, 0x16, 0x39, 0x72,
+ 0xe2, 0x16, 0x1f, 0x79, 0x84, 0x80, 0x18,
+ 0x01, 0x01, 0xfe, 0x71, 0x00, 0x00, 0x01,
+ 0x01, 0x08, 0x0a, 0x00, 0x22, 0xaa, 0x10,
+ 0x00, 0x22, 0xaa, 0x10
+ };
+ uint8_t buf[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x62, 0x6f, 0x6f, 0x65,
+ 0x65, 0x6b, 0x0d, 0x0a, 0x4c, 0x45, 0x4e, 0x31,
+ 0x20, 0x38, 0x0d, 0x0a, 0x66, 0x6f, 0x30, 0x30, /* LEN1|20| ends at 17 */
+ 0x30, 0x38, 0x0d, 0x0a, 0x4c, 0x45, 0x4e, 0x32, /* "0008" at offset 5 */
+ 0x20, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x0d, 0x0a, 0x41, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x0d, 0x0a, 0x0d, 0x0a, 0x0d,
+ 0x0a
+ };
+ uint16_t ethlen = sizeof(raw_eth);
+ uint16_t ipv4len = sizeof(raw_ipv4);
+ uint16_t tcplen = sizeof(raw_tcp);
+ uint16_t buflen = sizeof(buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ /* Copy raw data into packet */
+ if (PacketCopyData(p1, raw_eth, ethlen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen, raw_ipv4, ipv4len) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen + ipv4len, raw_tcp, tcplen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen + ipv4len + tcplen, buf, buflen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ SET_PKT_LEN(p1, ethlen + ipv4len + tcplen + buflen);
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ethh = (EthernetHdr *)raw_eth;
+ p1->ip4h = (IPV4Hdr *)raw_ipv4;
+ p1->tcph = (TCPHdr *)raw_tcp;
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = GET_PKT_DATA(p1) + ethlen + ipv4len + tcplen;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"LEN1|20|\"; "
+ "byte_test:4,=,8,0; "
+ "msg:\"byte_test keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"LEN1|20|\"; "
+ "byte_test:4,=,8,5,relative,string,dec; "
+ "msg:\"byte_test keyword check(2)\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ result = 1;
+ } else {
+ result = 0;
+ printf("sid 1 didn't alert, but should have: ");
+ goto cleanup;
+ }
+ if (PacketAlertCheck(p1, 2)) {
+ result = 1;
+ } else {
+ result = 0;
+ printf("sid 2 didn't alert, but should have: ");
+ goto cleanup;
+ }
+
+cleanup:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+end:
+ SCFree(p1);
+ return result;
+}
+
+static int SigTest39(void)
+{
+ Packet *p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 1;
+ uint8_t raw_eth[] = {
+ 0x00, 0x00, 0x03, 0x04, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00
+ };
+ uint8_t raw_ipv4[] = {
+ 0x45, 0x00, 0x00, 0x7d, 0xd8, 0xf3, 0x40, 0x00,
+ 0x40, 0x06, 0x63, 0x85, 0x7f, 0x00, 0x00, 0x01,
+ 0x7f, 0x00, 0x00, 0x01
+ };
+ uint8_t raw_tcp[] = {
+ 0xad, 0x22, 0x04, 0x00, 0x16, 0x39, 0x72,
+ 0xe2, 0x16, 0x1f, 0x79, 0x84, 0x80, 0x18,
+ 0x01, 0x01, 0xfe, 0x71, 0x00, 0x00, 0x01,
+ 0x01, 0x08, 0x0a, 0x00, 0x22, 0xaa, 0x10,
+ 0x00, 0x22, 0xaa, 0x10
+ };
+ uint8_t buf[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x62, 0x6f, 0x6f, 0x65,
+ 0x65, 0x6b, 0x0d, 0x0a, 0x4c, 0x45, 0x4e, 0x31,
+ 0x20, 0x38, 0x0d, 0x0a, 0x66, 0x30, 0x30, 0x30,
+ 0x38, 0x72, 0x0d, 0x0a, 0x4c, 0x45, 0x4e, 0x32,
+ 0x20, 0x39, 0x39, 0x4c, 0x45, 0x4e, 0x32, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x0d, 0x0a, 0x41, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x0d, 0x0a, 0x0d, 0x0a, 0x0d,
+ 0x0a
+ };
+ uint16_t ethlen = sizeof(raw_eth);
+ uint16_t ipv4len = sizeof(raw_ipv4);
+ uint16_t tcplen = sizeof(raw_tcp);
+ uint16_t buflen = sizeof(buf);
+
+ memset(&th_v, 0, sizeof(ThreadVars));
+
+ /* Copy raw data into packet */
+ if (PacketCopyData(p1, raw_eth, ethlen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen, raw_ipv4, ipv4len) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen + ipv4len, raw_tcp, tcplen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ if (PacketCopyDataOffset(p1, ethlen + ipv4len + tcplen, buf, buflen) == -1) {
+ SCFree(p1);
+ return 1;
+ }
+ SET_PKT_LEN(p1, ethlen + ipv4len + tcplen + buflen);
+
+ PACKET_RESET_CHECKSUMS(p1);
+ p1->ethh = (EthernetHdr *)raw_eth;
+ p1->ip4h = (IPV4Hdr *)raw_ipv4;
+ p1->tcph = (TCPHdr *)raw_tcp;
+ p1->src.family = AF_INET;
+ p1->dst.family = AF_INET;
+ p1->payload = GET_PKT_DATA(p1) + ethlen + ipv4len + tcplen;
+ p1->payload_len = buflen;
+ p1->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"LEN1|20|\"; "
+ "byte_test:4,=,8,0; "
+ "byte_jump:4,0; "
+ "byte_test:6,=,0x4c454e312038,0,relative; "
+ "msg:\"byte_jump keyword check(1)\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result &= 0;
+ goto end;
+ }
+ // XXX TODO
+ de_ctx->sig_list->next = SigInit(de_ctx,
+ "alert tcp any any -> any any "
+ "(content:\"LEN1|20|\"; "
+ "byte_test:4,=,8,4,relative,string,dec; "
+ "byte_jump:4,4,relative,string,dec,post_offset 2; "
+ "byte_test:4,=,0x4c454e32,0,relative; "
+ "msg:\"byte_jump keyword check(2)\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result &= 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (PacketAlertCheck(p1, 1)) {
+ result = 1;
+ } else {
+ result = 0;
+ printf("sid 1 didn't alert, but should have: ");
+ goto cleanup;
+ }
+ if (PacketAlertCheck(p1, 2)) {
+ result = 1;
+ } else {
+ result = 0;
+ printf("sid 2 didn't alert, but should have: ");
+ goto cleanup;
+ }
+
+cleanup:
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+end:
+ SCFree(p1);
+ return result;
+}
+
+/**
+ * \test SigTest36ContentAndIsdataatKeywords01 is a test to check window with constructed packets,
+ * \brief expecting to match a size
+ */
+
+static int SigTest36ContentAndIsdataatKeywords01 (void)
+{
+ int result = 0;
+
+ // Build and decode the packet
+
+ uint8_t raw_eth [] = {
+ 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
+ ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
+ ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
+ ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
+ ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
+ ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
+ ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
+ ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
+ ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
+ ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
+ ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
+ ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
+ ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
+ ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
+ ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
+ ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
+ ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
+ ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
+ ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
+ ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
+ ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
+ ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
+ ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
+ ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
+ ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
+ ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
+ ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
+ ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
+ ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
+ ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
+
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ DecodeThreadVars dtv;
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ memset(&dtv, 0, sizeof(DecodeThreadVars));
+ memset(&th_v, 0, sizeof(th_v));
+
+ FlowInitConfig(FLOW_QUIET);
+ DecodeEthernet(&th_v, &dtv, p, raw_eth, sizeof(raw_eth));
+
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest36ContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:404, relative; sid:101;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 101) == 0) {
+ result = 0;
+ goto end;
+ } else {
+ result=1;
+ }
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ PacketRecycle(p);
+ FlowShutdown();
+
+ SCFree(p);
+ return result;
+
+end:
+ if(de_ctx)
+ {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ }
+
+ if(det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+
+ //PatternMatchDestroy(mpm_ctx);
+
+ if(de_ctx)
+ DetectEngineCtxFree(de_ctx);
+
+ if (p != NULL)
+ PacketRecycle(p);
+
+ FlowShutdown();
+
+ SCFree(p);
+ return result;
+}
+
+
+/**
+ * \test SigTest37ContentAndIsdataatKeywords02 is a test to check window with constructed packets,
+ * \brief not expecting to match a size
+ */
+
+static int SigTest37ContentAndIsdataatKeywords02 (void)
+{
+ int result = 0;
+
+ // Build and decode the packet
+
+ uint8_t raw_eth [] = {
+ 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00
+ ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8
+ ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18
+ ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21
+ ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46
+ ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20
+ ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c
+ ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e
+ ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43
+ ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78
+ ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d
+ ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e
+ ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38
+ ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76
+ ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74
+ ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a
+ ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74
+ ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f
+ ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74
+ ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63
+ ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c
+ ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c
+ ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42
+ ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76
+ ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75
+ ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c
+ ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77
+ ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68
+ ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59
+ ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a };
+
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ DecodeThreadVars dtv;
+
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ memset(&dtv, 0, sizeof(DecodeThreadVars));
+ memset(&th_v, 0, sizeof(th_v));
+
+ FlowInitConfig(FLOW_QUIET);
+ DecodeEthernet(&th_v, &dtv, p, raw_eth, sizeof(raw_eth));
+
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest37ContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:500, relative; sid:101;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("sig parse failed: ");
+ result = 0;
+ goto end;
+ }
+
+ if (s->init_data->smlists[DETECT_SM_LIST_PMATCH]->type != DETECT_CONTENT) {
+ printf("type not content: ");
+ goto end;
+ }
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 101) == 0) {
+ result = 1;
+ goto end;
+ } else {
+ printf("sig matched, but should not have: ");
+ result=0;
+ }
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ PacketRecycle(p);
+ FlowShutdown();
+
+ SCFree(p);
+ return result;
+
+end:
+ if(de_ctx)
+ {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ }
+
+ if(det_ctx)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+
+ if(de_ctx)
+ DetectEngineCtxFree(de_ctx);
+
+ if (p != NULL)
+ PacketRecycle(p);
+
+ FlowShutdown();
+
+ SCFree(p);
+ return result;
+}
+
+/**
+ * \test SigTest41NoPacketInspection is a test to check that when PKT_NOPACKET_INSPECTION
+ * flag is set, we don't need to inspect the packet protocol header or its contents.
+ */
+
+static int SigTest40NoPacketInspection01(void)
+{
+
+ uint8_t *buf = (uint8_t *)
+ "220 (vsFTPd 2.0.5)\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ TCPHdr tcphdr;
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ PacketQueue pq;
+ Flow f;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ memset(&pq, 0, sizeof(pq));
+ memset(&f, 0, sizeof(f));
+ memset(&tcphdr, 0, sizeof(tcphdr));
+
+ p->src.family = AF_INET;
+ p->src.addr_data32[0] = UTHSetIPv4Address("192.168.0.1");
+ p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->dp = 34260;
+ p->sp = 21;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flags |= PKT_NOPACKET_INSPECTION;
+ p->tcph = &tcphdr;
+ p->flow = &f;
+
+ FLOW_INITIALIZE(&f);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> 1.2.3.4 any (msg:\"No Packet Inspection Test\"; flow:to_server; sid:2; rev:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
+ det_ctx->de_ctx = de_ctx;
+
+ Detect(&th_v, p, det_ctx);
+ if (PacketAlertCheck(p, 2))
+ result = 0;
+ else
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ //PatternMatchDestroy(mpm_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ SCFree(p);
+ return result;
+}
+
+/**
+ * \test SigTest42NoPayloadInspection is a test to check that when PKT_NOPAYLOAD_INSPECTION
+ * flag is set, we don't need to inspect the packet contents.
+ */
+
+static int SigTest40NoPayloadInspection02(void)
+{
+
+ uint8_t *buf = (uint8_t *)
+ "220 (vsFTPd 2.0.5)\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ memset(&th_v, 0, sizeof(th_v));
+
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+ p->flags |= PKT_NOPAYLOAD_INSPECTION;
+
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ Signature *s = DetectEngineAppendSig(de_ctx,
+ "alert tcp any any -> any any (msg:\"No Payload TEST\"; content:\"220 (vsFTPd 2.0.5)\"; sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ FAIL_IF(PacketAlertCheck(p, 1));
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ SCFree(p);
+ PASS;
+}
+
+static int SigTestMemory01 (void)
+{
+ uint8_t *buf = (uint8_t *)
+ "GET /one/ HTTP/1.1\r\n"
+ "Host: one.example.org\r\n"
+ "\r\n\r\n"
+ "GET /two/ HTTP/1.1\r\n"
+ "Host: two.example.org\r\n"
+ "\r\n\r\n";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = PacketGetFromAlloc();
+ if (unlikely(p == NULL))
+ return 0;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->payload = buf;
+ p->payload_len = buflen;
+ p->proto = IPPROTO_TCP;
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ result = 1;
+end:
+ SCFree(p);
+ return result;
+}
+
+static int SigTestMemory02 (void)
+{
+ ThreadVars th_v;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 456 (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any 1:1000 (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ result = 1;
+end:
+ return result;
+}
+
+static int SigTestMemory03 (void)
+{
+ ThreadVars th_v;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> 1.2.3.4 456 (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> 1.2.3.3-1.2.3.6 1:1000 (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next->next = SigInit(de_ctx,"alert tcp any any -> !1.2.3.5 1:990 (msg:\"HTTP URI cap\"; content:\"GET \"; depth:4; pcre:\"/GET (?P<pkt_http_uri>.*) HTTP\\/\\d\\.\\d\\r\\n/G\"; sid:3;)");
+ if (de_ctx->sig_list->next->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+
+ SigGroupCleanup(de_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ result = 1;
+end:
+ return result;
+}
+
+static int SigTestContent01 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+ else
+ printf("sig 1 didn't match: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTestContent02 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 31\"; content:\"0123456789012345678901234567890\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)) {
+ if (PacketAlertCheck(p, 2)) {
+ result = 1;
+ } else
+ printf("sig 2 didn't match: ");
+ }
+ else
+ printf("sig 1 didn't match: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTestContent03 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+ else
+ printf("sig 1 didn't match: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTestContent04 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; within:32; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+ else
+ printf("sig 1 didn't match: ");
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test sigs with patterns at the limit of the pm's size limit */
+static int SigTestContent05 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901PADabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ printf("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 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; within:32; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ printf("sig1 parse failed: ");
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:1; within:32; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ printf("sig2 parse failed: ");
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 matched but shouldn't: ");
+ goto end;
+ }
+
+ if (PacketAlertCheck(p, 2)) {
+ printf("sig 2 matched but shouldn't: ");
+ goto end;
+ }
+
+ result = 1;
+end:
+ UTHFreePackets(&p, 1);
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ if (det_ctx != NULL) {
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ }
+ if (de_ctx != NULL) {
+ DetectEngineCtxFree(de_ctx);
+ }
+ return result;
+}
+
+static int SigTestContent06 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ uint16_t buflen = strlen((char *)buf);
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+ Packet *p = NULL;
+ p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Test 32 sig1\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; within:32; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+ de_ctx->sig_list->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Test 32 sig2\"; content:\"01234567890123456789012345678901\"; content:\"abcdefg\"; sid:2;)");
+ if (de_ctx->sig_list->next == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1)){
+ //printf("sig 1 matched :");
+ }else{
+ printf("sig 1 didn't match: ");
+ goto end;
+ }
+
+ if (PacketAlertCheck(p, 2)){
+ result = 1;
+ }else{
+ printf("sig 2 didn't match: ");
+ goto end;
+ }
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTestWithin01 (void)
+{
+ DecodeThreadVars dtv;
+ ThreadVars th_v;
+ int result = 0;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Packet *p3 = NULL;
+ Packet *p4 = NULL;
+
+ uint8_t rawpkt1[] = {
+ 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24,
+ 0xe8,0x29,0xfa,0x4f,0x08,0x00,0x45,0x00,
+ 0x00,0x8c,0x95,0x50,0x00,0x00,0x40,0x06,
+ 0x2d,0x45,0xc0,0xa8,0x02,0x03,0xd0,0x45,
+ 0x24,0xe6,0x06,0xcc,0x03,0x09,0x18,0x72,
+ 0xd0,0xe3,0x1a,0xab,0x7c,0x98,0x50,0x00,
+ 0x02,0x00,0x46,0xa0,0x00,0x00,0x48,0x69,
+ 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
+ 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
+ 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
+ 0x74,0x63,0x68,0x65,0x73,0x0a,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00 }; /* end rawpkt1 */
+
+ uint8_t rawpkt2[] = {
+ 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24,
+ 0xe8,0x29,0xfa,0x4f,0x08,0x00,0x45,0x00,
+ 0x00,0x8c,0x30,0x87,0x00,0x00,0x40,0x06,
+ 0x92,0x0e,0xc0,0xa8,0x02,0x03,0xd0,0x45,
+ 0x24,0xe6,0x06,0xcd,0x03,0x09,0x73,0xec,
+ 0xd5,0x35,0x14,0x7d,0x7c,0x12,0x50,0x00,
+ 0x02,0x00,0xed,0x86,0x00,0x00,0x48,0x69,
+ 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
+ 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
+ 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
+ 0x74,0x63,0x68,0x65,0x73,0x0a,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00 }; /* end rawpkt2 */
+
+ uint8_t rawpkt3[] = {
+ 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24,
+ 0xe8,0x29,0xfa,0x4f,0x08,0x00,0x45,0x00,
+ 0x00,0x8c,0x57,0xd8,0x00,0x00,0x40,0x06,
+ 0x6a,0xbd,0xc0,0xa8,0x02,0x03,0xd0,0x45,
+ 0x24,0xe6,0x06,0xce,0x03,0x09,0x06,0x3d,
+ 0x02,0x22,0x2f,0x9b,0x6f,0x8f,0x50,0x00,
+ 0x02,0x00,0x1f,0xae,0x00,0x00,0x48,0x69,
+ 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
+ 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
+ 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
+ 0x74,0x63,0x68,0x65,0x73,0x0a,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00 }; /* end rawpkt3 */
+
+ uint8_t rawpkt4[] = {
+ 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24,
+ 0xe8,0x29,0xfa,0x4f,0x08,0x00,0x45,0x00,
+ 0x00,0x8c,0xa7,0x2e,0x00,0x00,0x40,0x06,
+ 0x1b,0x67,0xc0,0xa8,0x02,0x03,0xd0,0x45,
+ 0x24,0xe6,0x06,0xcf,0x03,0x09,0x00,0x0e,
+ 0xdf,0x72,0x3d,0xc2,0x21,0xce,0x50,0x00,
+ 0x02,0x00,0x88,0x25,0x00,0x00,0x48,0x69,
+ 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
+ 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
+ 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
+ 0x74,0x63,0x68,0x65,0x73,0x0a,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00 }; /* end rawpkt4 */
+
+ memset(&dtv, 0, sizeof(DecodeThreadVars));
+ memset(&th_v, 0, sizeof(th_v));
+
+ DetectEngineThreadCtx *det_ctx = NULL;
+
+ FlowInitConfig(FLOW_QUIET);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"within test\"; content:\"Hi, this is a big test to check \"; content:\"content matches\"; distance:0; within:15; sid:556;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ /* packet 1 */
+ p1 = PacketGetFromAlloc();
+ if (unlikely(p1 == NULL))
+ return 0;
+ DecodeEthernet(&th_v, &dtv, p1, rawpkt1, sizeof(rawpkt1));
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
+ if (!(PacketAlertCheck(p1, 556))) {
+ printf("failed to match on packet 1: ");
+ goto end;
+ }
+
+ /* packet 2 */
+ p2 = PacketGetFromAlloc();
+ if (unlikely(p2 == NULL))
+ return 0;
+ DecodeEthernet(&th_v, &dtv, p2, rawpkt2, sizeof(rawpkt2));
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
+ if (!(PacketAlertCheck(p2, 556))) {
+ printf("failed to match on packet 2: ");
+ goto end;
+ }
+
+ /* packet 3 */
+ p3 = PacketGetFromAlloc();
+ if (unlikely(p3 == NULL))
+ return 0;
+ DecodeEthernet(&th_v, &dtv, p3, rawpkt3, sizeof(rawpkt3));
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
+ if (!(PacketAlertCheck(p3, 556))) {
+ printf("failed to match on packet 3: ");
+ goto end;
+ }
+
+ /* packet 4 */
+ p4 = PacketGetFromAlloc();
+ if (unlikely(p4 == NULL))
+ return 0;
+ DecodeEthernet(&th_v, &dtv, p4, rawpkt4, sizeof(rawpkt4));
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p4);
+ if (!(PacketAlertCheck(p4, 556))) {
+ printf("failed to match on packet 4: ");
+ goto end;
+ }
+
+ /* packet 5 */
+ uint8_t *p5buf = (uint8_t *)"Hi, this is a big test to check content matches";
+ uint16_t p5buflen = strlen((char *)p5buf);
+ Packet *p5 = UTHBuildPacket(p5buf, p5buflen, IPPROTO_TCP);
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p5);
+ if (!(PacketAlertCheck(p5, 556))) {
+ printf("failed to match on packet 5: ");
+ goto end;
+ }
+ UTHFreePackets(&p5, 1);
+
+ result = 1;
+end:
+ if (de_ctx != NULL) {
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+ }
+
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ if (p1 != NULL) {
+ PacketRecycle(p1);
+ SCFree(p1);
+ }
+ if (p2 != NULL) {
+ PacketRecycle(p2);
+ SCFree(p2);
+ }
+ if (p3 != NULL) {
+ PacketRecycle(p3);
+ SCFree(p3);
+ }
+ if (p4 != NULL) {
+ PacketRecycle(p4);
+ SCFree(p4);
+ }
+ FlowShutdown();
+ return result;
+}
+
+static int SigTestDepthOffset01 (void)
+{
+ uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ uint16_t buflen = strlen((char *)buf);
+ Packet *p = NULL;
+ ThreadVars th_v;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ int result = 0;
+
+ memset(&th_v, 0, sizeof(th_v));
+
+ p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"depth offset\"; content:\"456\"; offset:4; depth:3; sid:1;)");
+ if (de_ctx->sig_list == NULL) {
+ result = 0;
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+ SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+ if (PacketAlertCheck(p, 1))
+ result = 1;
+
+ SigGroupCleanup(de_ctx);
+ SigCleanSignatures(de_ctx);
+
+ DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+end:
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+static int SigTestDetectAlertCounter(void)
+{
+ Packet *p = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ memset(&tv, 0, sizeof(tv));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"Test counter\"; "
+ "content:\"boo\"; sid:1;)");
+ FAIL_IF(de_ctx->sig_list == NULL);
+
+ SigGroupBuild(de_ctx);
+ strlcpy(tv.name, "detect_test", sizeof(tv.name));
+ DetectEngineThreadCtxInit(&tv, de_ctx, (void *)&det_ctx);
+ /* init counters */
+ StatsSetupPrivate(&tv);
+
+ p = UTHBuildPacket((uint8_t *)"boo", strlen("boo"), IPPROTO_TCP);
+ Detect(&tv, p, det_ctx);
+ FAIL_IF_NOT(StatsGetLocalCounterValue(&tv, det_ctx->counter_alerts) == 1);
+
+ Detect(&tv, p, det_ctx);
+ FAIL_IF_NOT(StatsGetLocalCounterValue(&tv, det_ctx->counter_alerts) == 2);
+ UTHFreePackets(&p, 1);
+
+ p = UTHBuildPacket((uint8_t *)"roo", strlen("roo"), IPPROTO_TCP);
+ Detect(&tv, p, det_ctx);
+ FAIL_IF_NOT(StatsGetLocalCounterValue(&tv, det_ctx->counter_alerts) == 2);
+ UTHFreePackets(&p, 1);
+
+ p = UTHBuildPacket((uint8_t *)"laboosa", strlen("laboosa"), IPPROTO_TCP);
+ Detect(&tv, p, det_ctx);
+ FAIL_IF_NOT(StatsGetLocalCounterValue(&tv, det_ctx->counter_alerts) == 3);
+ UTHFreePackets(&p, 1);
+
+ DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
+ DetectEngineCtxFree(de_ctx);
+ PASS;
+}
+
+/** \test test if the engine set flag to drop pkts of a flow that
+ * triggered a drop action on IPS mode */
+static int SigTestDropFlow01(void)
+{
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ StreamTcpInitConfig(true);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ FAIL_IF_NULL(de_ctx);
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "drop http any any -> any any "
+ "(msg:\"Test proto match\"; "
+ "sid:1;)");
+ FAIL_IF_NULL(s);
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ FAIL_IF_NOT(r == 0);
+
+ http_state = f.alstate;
+ FAIL_IF_NULL(http_state);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ FAIL_IF_NOT(PacketAlertCheck(p, 1));
+
+ FAIL_IF_NOT(p->flow->flags & FLOW_ACTION_DROP);
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(true);
+ FLOW_DESTROY(&f);
+
+ UTHFreePackets(&p, 1);
+ PASS;
+}
+
+/** \test test if the engine set flag to drop pkts of a flow that
+ * triggered a drop action on IPS mode */
+static int SigTestDropFlow02(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ 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_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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, "drop tcp any any -> any 80 "
+ "(msg:\"Test proto match\"; uricontent:\"one\";"
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ 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 it should: ");
+ goto end;
+ }
+
+ if ( !(p->flow->flags & FLOW_ACTION_DROP)) {
+ printf("sig 1 alerted but flow was not flagged correctly: ");
+ goto end;
+ }
+
+ /* Ok, now we know that the flag is set for app layer sigs
+ * (ex: inspecting uricontent) */
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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);
+
+ UTHFreePackets(&p, 1);
+ return result;
+}
+
+/** \test test if the engine set flag to drop pkts of a flow that
+ * triggered a drop action on IPS mode, and it doesn't inspect
+ * any other packet of the stream */
+static int SigTestDropFlow03(void)
+{
+ int result = 0;
+ Flow f;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+
+ uint8_t http_buf2[] = "POST /two HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf2_len = sizeof(http_buf1) - 1;
+
+ /* Set the engine mode to IPS */
+ EngineModeSetIPS();
+
+ TcpSession ssn;
+ Packet *p1 = NULL;
+ Packet *p2 = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+
+ FLOW_INITIALIZE(&f);
+ f.protoctx = (void *)&ssn;
+ f.proto = IPPROTO_TCP;
+ f.flags |= FLOW_IPV4;
+
+ p1->flow = &f;
+ p1->flowflags |= FLOW_PKT_TOSERVER;
+ p1->flowflags |= FLOW_PKT_ESTABLISHED;
+ p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ p2->flow = &f;
+ p2->flowflags |= FLOW_PKT_TOSERVER;
+ p2->flowflags |= FLOW_PKT_ESTABLISHED;
+ p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f.alproto = ALPROTO_HTTP1;
+
+ 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, "drop tcp any any -> any 80 "
+ "(msg:\"Test proto match\"; uricontent:\"one\";"
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ /* the no inspection flag should be set after the first sig gets triggered,
+ * so the second packet should not match the next sig (because of no inspection) */
+ s = de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any 80 "
+ "(msg:\"Test proto match\"; uricontent:\"two\";"
+ "sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ int r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ http_state = f.alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ if (!PacketAlertCheck(p1, 1)) {
+ printf("sig 1 didn't alert on p1, but it should: ");
+ goto end;
+ }
+
+ if ( !(p1->flow->flags & FLOW_ACTION_DROP)) {
+ printf("sig 1 alerted but flow was not flagged correctly: ");
+ goto end;
+ }
+
+ /* Second part.. Let's feed with another packet */
+ if (StreamTcpCheckFlowDrops(p2) == 1) {
+ SCLogDebug("This flow/stream triggered a drop rule");
+ FlowSetNoPacketInspectionFlag(p2->flow);
+ DecodeSetNoPacketInspectionFlag(p2);
+ StreamTcpDisableAppLayer(p2->flow);
+ p2->action |= ACTION_DROP;
+ /* return the segments to the pool */
+ StreamTcpSessionPktFree(p2);
+ }
+
+
+ if ( !(p2->flags & PKT_NOPACKET_INSPECTION)) {
+ printf("The packet was not flagged with no-inspection: ");
+ goto end;
+ }
+
+ r = AppLayerParserParse(
+ NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_buf2_len);
+ if (r != 0) {
+ printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
+
+ if (PacketAlertCheck(p2, 1)) {
+ printf("sig 1 alerted, but it should not since the no pkt inspection should be set: ");
+ goto end;
+ }
+
+ if (PacketAlertCheck(p2, 2)) {
+ printf("sig 2 alerted, but it should not since the no pkt inspection should be set: ");
+ goto end;
+ }
+
+ if (!(PacketTestAction(p2, ACTION_DROP))) {
+ printf("A \"drop\" action should be set from the flow to the packet: ");
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ 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);
+
+ UTHFreePackets(&p1, 1);
+ UTHFreePackets(&p2, 1);
+
+ /* Restore mode to IDS */
+ EngineModeSetIDS();
+ return result;
+}
+
+/** \test ICMP packet shouldn't be matching port based sig
+ * Bug #611 */
+static int SigTestPorts01(void)
+{
+ int result = 0;
+ Packet *p1 = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ uint8_t payload[] = "AAAAAAAAAAAAAAAAAA";
+
+ memset(&tv, 0, sizeof(ThreadVars));
+
+ p1 = UTHBuildPacket(payload, sizeof(payload), IPPROTO_ICMP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any 80 "
+ "(content:\"AAA\"; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sig 1 alerted on p1, but it should not: ");
+ 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);
+
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+/** \test almost identical patterns */
+static int SigTestBug01(void)
+{
+ int result = 0;
+ Packet *p1 = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ uint8_t payload[] = "!mymy";
+
+ memset(&tv, 0, sizeof(ThreadVars));
+
+ p1 = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->flags |= DE_QUIET;
+
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+ "(content:\"Omymy\"; nocase; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+ s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
+ "(content:\"!mymy\"; nocase; sid:2;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
+
+ if (PacketAlertCheck(p1, 1)) {
+ printf("sig 1 alerted on p1, but it should not: ");
+ goto end;
+ }
+ if (!(PacketAlertCheck(p1, 2))) {
+ printf("sig 2 did not p1, but it 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);
+
+ UTHFreePackets(&p1, 1);
+ return result;
+}
+
+static const char *dummy_conf_string2 =
+ "%YAML 1.1\n"
+ "---\n"
+ "vars:\n"
+ "\n"
+ " address-groups:\n"
+ "\n"
+ " HOME_NET: \"[10.10.10.0/24, !10.10.10.247]\"\n"
+ "\n"
+ " EXTERNAL_NET: \"any\"\n"
+ "\n"
+ " port-groups:\n"
+ "\n"
+ " HTTP_PORTS: \"80:81,88\"\n"
+ "\n";
+
+static int DetectAddressYamlParsing01 (void)
+{
+ int result = 0;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string2, strlen(dummy_conf_string2));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> any any (sid:1;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp any any -> $HOME_NET any (sid:2;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> $HOME_NET any (sid:3;)")) == NULL)
+ goto end;
+
+ result = 1;
+
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ return result;
+}
+
+static const char *dummy_conf_string3 =
+ "%YAML 1.1\n"
+ "---\n"
+ "vars:\n"
+ "\n"
+ " address-groups:\n"
+ "\n"
+ " HOME_NET: \"[10.10.10.0/24, !10.10.10.247/32]\"\n"
+ "\n"
+ " EXTERNAL_NET: \"any\"\n"
+ "\n"
+ " port-groups:\n"
+ "\n"
+ " HTTP_PORTS: \"80:81,88\"\n"
+ "\n";
+
+static int DetectAddressYamlParsing02 (void)
+{
+ int result = 0;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string3, strlen(dummy_conf_string3));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> any any (sid:1;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp any any -> $HOME_NET any (sid:2;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> $HOME_NET any (sid:3;)")) == NULL)
+ goto end;
+
+ result = 1;
+
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ return result;
+}
+
+static const char *dummy_conf_string4 =
+ "%YAML 1.1\n"
+ "---\n"
+ "vars:\n"
+ "\n"
+ " address-groups:\n"
+ "\n"
+ " HOME_NET: \"[10.10.10.0/24, !10.10.10.247/32]\"\n"
+ "\n"
+ " EXTERNAL_NET: \"any\"\n"
+ "\n"
+ " port-groups:\n"
+ "\n"
+ " HTTP_PORTS: \"80:81,88\"\n"
+ "\n";
+
+static int DetectAddressYamlParsing03 (void)
+{
+ int result = 0;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string4, strlen(dummy_conf_string4));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> any any (sid:1;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp any any -> $HOME_NET any (sid:2;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> $HOME_NET any (sid:3;)")) == NULL)
+ goto end;
+
+ result = 1;
+
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ return result;
+}
+
+static const char *dummy_conf_string5 =
+ "%YAML 1.1\n"
+ "---\n"
+ "vars:\n"
+ "\n"
+ " address-groups:\n"
+ "\n"
+ " HOME_NET: \"[10.196.0.0/24, !10.196.0.15]\"\n"
+ "\n"
+ " EXTERNAL_NET: \"any\"\n"
+ "\n"
+ " port-groups:\n"
+ "\n"
+ " HTTP_PORTS: \"80:81,88\"\n"
+ "\n";
+
+/** \test bug #815 */
+static int DetectAddressYamlParsing04 (void)
+{
+ int result = 0;
+
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string5, strlen(dummy_conf_string5));
+
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ de_ctx->flags |= DE_QUIET;
+
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> any any (sid:1;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp any any -> $HOME_NET any (sid:2;)")) == NULL)
+ goto end;
+ if ((DetectEngineAppendSig(de_ctx, "alert tcp $HOME_NET any -> $HOME_NET any (sid:3;)")) == NULL)
+ goto end;
+
+ result = 1;
+
+ DetectEngineCtxFree(de_ctx);
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ return result;
+}
+
+void SigRegisterTests(void)
+{
+ SigParseRegisterTests();
+ IPOnlyRegisterTests();
+
+ UtRegisterTest("SigTest01", SigTest01);
+ UtRegisterTest("SigTest02 -- Offset/Depth match", SigTest02);
+ UtRegisterTest("SigTest03 -- offset/depth mismatch", SigTest03);
+ UtRegisterTest("SigTest04 -- distance/within match", SigTest04);
+ UtRegisterTest("SigTest05 -- distance/within mismatch", SigTest05);
+ UtRegisterTest("SigTest06 -- uricontent HTTP/1.1 match test", SigTest06);
+ UtRegisterTest("SigTest07 -- uricontent HTTP/1.1 mismatch test",
+ SigTest07);
+ UtRegisterTest("SigTest08 -- uricontent HTTP/1.0 match test", SigTest08);
+ UtRegisterTest("SigTest09 -- uricontent HTTP/1.0 mismatch test",
+ SigTest09);
+ UtRegisterTest("SigTest10 -- long content match, longer than pkt",
+ SigTest10);
+ UtRegisterTest("SigTest11 -- mpm searching", SigTest11);
+ UtRegisterTest("SigTest12 -- content order matching, normal", SigTest12);
+ UtRegisterTest("SigTest13 -- content order matching, diff order",
+ SigTest13);
+ UtRegisterTest("SigTest14 -- content order matching, distance 0",
+ SigTest14);
+ UtRegisterTest("SigTest15 -- port negation sig (no match)", SigTest15);
+ UtRegisterTest("SigTest16 -- port negation sig (match)", SigTest16);
+ UtRegisterTest("SigTest17 -- HTTP Host Pkt var capture", SigTest17);
+ UtRegisterTest("SigTest18 -- Ftp negation sig test", SigTest18);
+ UtRegisterTest("SigTest19 -- IP-ONLY test (1)", SigTest19);
+ UtRegisterTest("SigTest20 -- IP-ONLY test (2)", SigTest20);
+ UtRegisterTest("SigTest21 -- FLOWBIT test (1)", SigTest21);
+ UtRegisterTest("SigTest22 -- FLOWBIT test (2)", SigTest22);
+ UtRegisterTest("SigTest23 -- FLOWBIT test (3)", SigTest23);
+
+ UtRegisterTest("SigTest24IPV4Keyword", SigTest24IPV4Keyword);
+ UtRegisterTest("SigTest25NegativeIPV4Keyword",
+ SigTest25NegativeIPV4Keyword);
+
+ UtRegisterTest("SigTest26TCPV4Keyword", SigTest26TCPV4Keyword);
+ UtRegisterTest("SigTest26TCPV4AndNegativeIPV4Keyword",
+ SigTest26TCPV4AndNegativeIPV4Keyword);
+ UtRegisterTest("SigTest26TCPV4AndIPV4Keyword",
+ SigTest26TCPV4AndIPV4Keyword);
+ UtRegisterTest("SigTest27NegativeTCPV4Keyword",
+ SigTest27NegativeTCPV4Keyword);
+
+ UtRegisterTest("SigTest28TCPV6Keyword", SigTest28TCPV6Keyword);
+ UtRegisterTest("SigTest29NegativeTCPV6Keyword",
+ SigTest29NegativeTCPV6Keyword);
+
+ UtRegisterTest("SigTest30UDPV4Keyword", SigTest30UDPV4Keyword);
+ UtRegisterTest("SigTest31NegativeUDPV4Keyword",
+ SigTest31NegativeUDPV4Keyword);
+
+ UtRegisterTest("SigTest32UDPV6Keyword", SigTest32UDPV6Keyword);
+ UtRegisterTest("SigTest33NegativeUDPV6Keyword",
+ SigTest33NegativeUDPV6Keyword);
+
+ UtRegisterTest("SigTest34ICMPV4Keyword", SigTest34ICMPV4Keyword);
+ UtRegisterTest("SigTest35NegativeICMPV4Keyword",
+ SigTest35NegativeICMPV4Keyword);
+ UtRegisterTest("SigTest36ContentAndIsdataatKeywords01",
+ SigTest36ContentAndIsdataatKeywords01);
+ UtRegisterTest("SigTest37ContentAndIsdataatKeywords02",
+ SigTest37ContentAndIsdataatKeywords02);
+
+ UtRegisterTest("SigTest38 -- byte_test test (1)", SigTest38);
+
+ UtRegisterTest("SigTest39 -- byte_jump test (2)", SigTest39);
+
+ UtRegisterTest("SigTest40NoPacketInspection01",
+ SigTest40NoPacketInspection01);
+ UtRegisterTest("SigTest40NoPayloadInspection02",
+ SigTest40NoPayloadInspection02);
+
+ UtRegisterTest("SigTestMemory01", SigTestMemory01);
+ UtRegisterTest("SigTestMemory02", SigTestMemory02);
+ UtRegisterTest("SigTestMemory03", SigTestMemory03);
+
+ UtRegisterTest("SigTestContent01 -- 32 byte pattern", SigTestContent01);
+ UtRegisterTest("SigTestContent02 -- 32+31 byte pattern", SigTestContent02);
+ UtRegisterTest("SigTestContent03 -- 32 byte pattern, x2 + distance",
+ SigTestContent03);
+ UtRegisterTest("SigTestContent04 -- 32 byte pattern, x2 + distance/within",
+ SigTestContent04);
+ UtRegisterTest("SigTestContent05 -- distance/within", SigTestContent05);
+ UtRegisterTest("SigTestContent06 -- distance/within ip only",
+ SigTestContent06);
+
+ UtRegisterTest("SigTestWithinReal01", SigTestWithin01);
+ UtRegisterTest("SigTestDepthOffset01", SigTestDepthOffset01);
+
+ UtRegisterTest("SigTestDetectAlertCounter", SigTestDetectAlertCounter);
+
+ UtRegisterTest("SigTestDropFlow01", SigTestDropFlow01);
+ UtRegisterTest("SigTestDropFlow02", SigTestDropFlow02);
+ UtRegisterTest("SigTestDropFlow03", SigTestDropFlow03);
+
+ UtRegisterTest("DetectAddressYamlParsing01", DetectAddressYamlParsing01);
+ UtRegisterTest("DetectAddressYamlParsing02", DetectAddressYamlParsing02);
+ UtRegisterTest("DetectAddressYamlParsing03", DetectAddressYamlParsing03);
+ UtRegisterTest("DetectAddressYamlParsing04", DetectAddressYamlParsing04);
+
+ UtRegisterTest("SigTestPorts01", SigTestPorts01);
+ UtRegisterTest("SigTestBug01", SigTestBug01);
+
+ DetectEngineContentInspectionRegisterTests();
+}
+#endif /* UNITTESTS */
diff --git a/src/tests/fuzz/fuzz_applayerparserparse.c b/src/tests/fuzz/fuzz_applayerparserparse.c
new file mode 100644
index 0000000..0ee263f
--- /dev/null
+++ b/src/tests/fuzz/fuzz_applayerparserparse.c
@@ -0,0 +1,213 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for AppLayerParserParse
+ */
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "app-layer-detect-proto.h"
+#include "flow-util.h"
+#include "app-layer-parser.h"
+#include "util-unittest-helper.h"
+#include "util-byte.h"
+#include "conf-yaml-loader.h"
+#include "util-conf.h"
+
+#define HEADER_LEN 6
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+int LLVMFuzzerInitialize(int *argc, char ***argv);
+
+AppLayerParserThreadCtx *alp_tctx = NULL;
+
+#include "confyaml.c"
+
+/* input buffer is structured this way :
+ * 6 bytes header,
+ * then sequence of buffers separated by magic bytes 01 D5 CA 7A */
+
+/* The 6 bytes header is
+ * alproto
+ * proto
+ * source port (uint16_t)
+ * destination port (uint16_t) */
+
+const uint8_t separator[] = {0x01, 0xD5, 0xCA, 0x7A};
+SCInstance surifuzz;
+AppProto forceLayer = 0;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ char *target_suffix = strrchr((*argv)[0], '_');
+ if (target_suffix != NULL) {
+ AppProto applayer = StringToAppProto(target_suffix + 1);
+ if (applayer != ALPROTO_UNKNOWN) {
+ forceLayer = applayer;
+ printf("Forcing %s=%" PRIu16 "\n", AppProtoToString(forceLayer), forceLayer);
+ return 0;
+ }
+ }
+ // else
+ const char *forceLayerStr = getenv("FUZZ_APPLAYER");
+ if (forceLayerStr) {
+ if (ByteExtractStringUint16(&forceLayer, 10, 0, forceLayerStr) < 0) {
+ forceLayer = 0;
+ printf("Invalid numeric value for FUZZ_APPLAYER environment variable");
+ } else {
+ printf("Forcing %s\n", AppProtoToString(forceLayer));
+ }
+ }
+ // http is the output name, but we want to fuzz HTTP1
+ if (forceLayer == ALPROTO_HTTP) {
+ forceLayer = ALPROTO_HTTP1;
+ }
+ return 0;
+}
+
+// arbitrary value
+#define ALPROTO_MAXTX 4096
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ Flow * f;
+ TcpSession ssn;
+ const uint8_t * albuffer;
+ uint8_t * alnext;
+ size_t alsize;
+ // used to find under and overflows
+ // otherwise overflows do not fail as they read the next packet
+ uint8_t * isolatedBuffer;
+
+ if (alp_tctx == NULL) {
+ //Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+
+ InitGlobal();
+ run_mode = RUNMODE_PCAP_FILE;
+ GlobalsInitPreConfig();
+
+ //redirect logs to /tmp
+ ConfigSetLogDirectory("/tmp/");
+ // disables checksums validation for fuzzing
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+
+ PostConfLoadedSetup(&surifuzz);
+ alp_tctx = AppLayerParserThreadCtxAlloc();
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+ }
+
+ if (size < HEADER_LEN) {
+ return 0;
+ }
+
+ if (data[0] >= ALPROTO_MAX) {
+ return 0;
+ }
+ //no UTHBuildFlow to have storage
+ f = FlowAlloc();
+ if (f == NULL) {
+ return 0;
+ }
+ f->flags |= FLOW_IPV4;
+ f->src.addr_data32[0] = 0x01020304;
+ f->dst.addr_data32[0] = 0x05060708;
+ f->sp = (uint16_t)((data[2] << 8) | data[3]);
+ f->dp = (uint16_t)((data[4] << 8) | data[5]);
+ f->proto = data[1];
+ memset(&ssn, 0, sizeof(TcpSession));
+ f->protoctx = &ssn;
+ f->protomap = FlowGetProtoMapping(f->proto);
+ if (forceLayer > 0) {
+ f->alproto = forceLayer;
+ } else {
+ f->alproto = data[0];
+ }
+
+ FLOWLOCK_WRLOCK(f);
+ /*
+ * We want to fuzz multiple calls to AppLayerParserParse
+ * because some parts of the code are only reached after
+ * multiple packets (in SMTP for example).
+ * So we treat our input as a list of buffers with magic separator.
+ */
+ albuffer = data + HEADER_LEN;
+ alsize = size - HEADER_LEN;
+ uint8_t flags = STREAM_START;
+ int flip = 0;
+ alnext = memmem(albuffer, alsize, separator, 4);
+ while (alnext) {
+ if (flip) {
+ flags |= STREAM_TOCLIENT;
+ flags &= ~(STREAM_TOSERVER);
+ flip = 0;
+ } else {
+ flags |= STREAM_TOSERVER;
+ flags &= ~(STREAM_TOCLIENT);
+ flip = 1;
+ }
+
+ if (alnext != albuffer) {
+ // only if we have some data
+ isolatedBuffer = malloc(alnext - albuffer);
+ if (isolatedBuffer == NULL) {
+ goto bail;
+ }
+ memcpy(isolatedBuffer, albuffer, alnext - albuffer);
+ (void) AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, alnext - albuffer);
+ free(isolatedBuffer);
+ if (FlowChangeProto(f)) {
+ // exits if a protocol change is requested
+ alsize = 0;
+ break;
+ }
+ flags &= ~(STREAM_START);
+ if (f->alparser &&
+ (((flags & STREAM_TOSERVER) != 0 &&
+ AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF_TS)) ||
+ ((flags & STREAM_TOCLIENT) != 0 &&
+ AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF_TC)))) {
+ //no final chunk
+ alsize = 0;
+ break;
+ }
+
+ AppLayerParserTransactionsCleanup(f, flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
+ }
+ alsize -= alnext - albuffer + 4;
+ albuffer = alnext + 4;
+ if (alsize == 0) {
+ break;
+ }
+ alnext = memmem(albuffer, alsize, separator, 4);
+ }
+ if (alsize > 0 ) {
+ if (flip) {
+ flags |= STREAM_TOCLIENT;
+ flags &= ~(STREAM_TOSERVER);
+ flip = 0;
+ } else {
+ flags |= STREAM_TOSERVER;
+ flags &= ~(STREAM_TOCLIENT);
+ flip = 1;
+ }
+ flags |= STREAM_EOF;
+ isolatedBuffer = malloc(alsize);
+ if (isolatedBuffer == NULL) {
+ goto bail;
+ }
+ memcpy(isolatedBuffer, albuffer, alsize);
+ (void) AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, alsize);
+ free(isolatedBuffer);
+ }
+
+bail:
+ FLOWLOCK_UNLOCK(f);
+ FlowFree(f);
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c b/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
new file mode 100644
index 0000000..598e7cc
--- /dev/null
+++ b/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
@@ -0,0 +1,99 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for AppLayerProtoDetectGetProto
+ */
+
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "app-layer-detect-proto.h"
+#include "flow-util.h"
+#include "app-layer-parser.h"
+#include "util-unittest-helper.h"
+#include "conf-yaml-loader.h"
+
+#define HEADER_LEN 6
+
+//rule of thumb constant, so as not to timeout target
+#define PROTO_DETECT_MAX_LEN 1024
+
+#include "confyaml.c"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ Flow *f;
+ TcpSession ssn;
+ bool reverse;
+ AppProto alproto;
+ AppProto alproto2;
+
+ if (alpd_tctx == NULL) {
+ //global init
+ InitGlobal();
+ run_mode = RUNMODE_UNITTEST;
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+ MpmTableSetup();
+ SpmTableSetup();
+ EngineModeSetIDS();
+ AppLayerProtoDetectSetup();
+ AppLayerParserSetup();
+ AppLayerParserRegisterProtocolParsers();
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+ }
+
+ if (size < HEADER_LEN) {
+ return 0;
+ }
+
+ f = TestHelperBuildFlow(AF_INET, "1.2.3.4", "5.6.7.8", (uint16_t)((data[2] << 8) | data[3]),
+ (uint16_t)((data[4] << 8) | data[5]));
+ if (f == NULL) {
+ return 0;
+ }
+ f->proto = data[1];
+ memset(&ssn, 0, sizeof(TcpSession));
+ f->protoctx = &ssn;
+ f->protomap = FlowGetProtoMapping(f->proto);
+
+ uint8_t flags = STREAM_TOCLIENT;
+ if (data[0] & STREAM_TOSERVER) {
+ flags = STREAM_TOSERVER;
+ }
+ alproto = AppLayerProtoDetectGetProto(
+ alpd_tctx, f, data + HEADER_LEN, size - HEADER_LEN, f->proto, flags, &reverse);
+ if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED && f->proto == IPPROTO_TCP) {
+ /* If we find a valid protocol at the start of a stream :
+ * check that with smaller input
+ * we find the same protocol or ALPROTO_UNKNOWN.
+ * Otherwise, we have evasion with TCP splitting
+ */
+ for (size_t i = 0; i < size-HEADER_LEN && i < PROTO_DETECT_MAX_LEN; i++) {
+ // reset detection at each try cf probing_parser_toserver_alproto_masks
+ AppLayerProtoDetectReset(f);
+ alproto2 = AppLayerProtoDetectGetProto(
+ alpd_tctx, f, data + HEADER_LEN, i, f->proto, flags, &reverse);
+ if (alproto2 != ALPROTO_UNKNOWN && alproto2 != alproto) {
+ printf("Failed with input length %" PRIuMAX " versus %" PRIuMAX
+ ", found %s instead of %s\n",
+ (uintmax_t)i, (uintmax_t)size - HEADER_LEN, AppProtoToString(alproto2),
+ AppProtoToString(alproto));
+ printf("Assertion failure: %s-%s\n", AppProtoToString(alproto2),
+ AppProtoToString(alproto));
+ fflush(stdout);
+ abort();
+ }
+ }
+ }
+ FlowFree(f);
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_confyamlloadstring.c b/src/tests/fuzz/fuzz_confyamlloadstring.c
new file mode 100644
index 0000000..f5f9ed3
--- /dev/null
+++ b/src/tests/fuzz/fuzz_confyamlloadstring.c
@@ -0,0 +1,31 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for ConfYamlLoadString
+ */
+
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "conf-yaml-loader.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int initialized = 0;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (initialized == 0) {
+ //Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+ //global init
+ InitGlobal();
+ run_mode = RUNMODE_UNITTEST;
+ initialized = 1;
+ }
+
+ ConfYamlLoadString((const char *) data, size);
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_decodepcapfile.c b/src/tests/fuzz/fuzz_decodepcapfile.c
new file mode 100644
index 0000000..cf50869
--- /dev/null
+++ b/src/tests/fuzz/fuzz_decodepcapfile.c
@@ -0,0 +1,101 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for TMM_DECODEPCAPFILE
+ */
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "app-layer-detect-proto.h"
+#include "defrag.h"
+#include "tm-modules.h"
+#include "tm-threads.h"
+#include "source-pcap-file.h"
+#include "util-unittest-helper.h"
+#include "conf-yaml-loader.h"
+#include "util-time.h"
+#include "util-conf.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int initialized = 0;
+SCInstance surifuzz;
+
+const char configNoChecksum[] = "\
+%YAML 1.1\n\
+---\n\
+pcap-file:\n\
+\n\
+ checksum-checks: no\n\
+";
+
+ThreadVars *tv;
+DecodeThreadVars *dtv;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ void *ptv = NULL;
+
+ if (initialized == 0) {
+ //Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+
+ InitGlobal();
+ run_mode = RUNMODE_PCAP_FILE;
+
+ //redirect logs to /tmp
+ ConfigSetLogDirectory("/tmp/");
+ //disables checksums validation for fuzzing
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+
+ PostConfLoadedSetup(&surifuzz);
+
+ RunModeInitializeThreadSettings();
+ TimeModeSetOffline();
+ PcapFileGlobalInit();
+
+ tv = TmThreadCreatePacketHandler("fuzz",
+ "packetpool", "packetpool",
+ "packetpool", "packetpool",
+ "pktacqloop");
+ if (tv == NULL) {
+ return 0;
+ }
+ TmModule *tm_module = TmModuleGetByName("ReceivePcapFile");
+ if (tm_module == NULL) {
+ return 0;
+ }
+ TmSlotSetFuncAppend(tv, tm_module, "/tmp/fuzz.pcap");
+ tm_module = TmModuleGetByName("DecodePcapFile");
+ if (tm_module == NULL) {
+ return 0;
+ }
+ TmSlotSetFuncAppend(tv, tm_module, NULL);
+ tmm_modules[TMM_DECODEPCAPFILE].ThreadInit(tv, NULL, (void **) &dtv);
+ (void)SC_ATOMIC_SET(tv->tm_slots->slot_next->slot_data, dtv);
+
+ extern uint16_t max_pending_packets;
+ max_pending_packets = 128;
+ PacketPoolInit();
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+
+ initialized = 1;
+ }
+
+ //rewrite buffer to a file as libpcap does not have buffer inputs
+ if (TestHelperBufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
+ return 0;
+ }
+
+ if (tmm_modules[TMM_RECEIVEPCAPFILE].ThreadInit(tv, "/tmp/fuzz.pcap", &ptv) == TM_ECODE_OK && ptv != NULL) {
+ suricata_ctl_flags = 0;
+ tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqLoop(tv, ptv, tv->tm_slots);
+ tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit(tv, ptv);
+ }
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_mimedecparseline.c b/src/tests/fuzz/fuzz_mimedecparseline.c
new file mode 100644
index 0000000..432ce7d
--- /dev/null
+++ b/src/tests/fuzz/fuzz_mimedecparseline.c
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for ConfYamlLoadString
+ */
+
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "util-decode-mime.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int initialized = 0;
+static int dummy = 0;
+
+static int MimeParserDataFromFileCB(const uint8_t *chunk, uint32_t len,
+ MimeDecParseState *state)
+{
+ if (len > 0 && chunk[len-1] == 0) {
+ // do not get optimized away
+ dummy++;
+ }
+ return MIME_DEC_OK;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (initialized == 0) {
+ //Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+ //global init
+ InitGlobal();
+ run_mode = RUNMODE_UNITTEST;
+ initialized = 1;
+ }
+
+ uint32_t line_count = 0;
+
+ MimeDecParseState *state = MimeDecInitParser(&line_count, MimeParserDataFromFileCB);
+ MimeDecEntity *msg_head = state->msg;
+ const uint8_t * buffer = data;
+ while (1) {
+ uint8_t * next = memchr(buffer, '\n', size);
+ if (next == NULL) {
+ if (state->state_flag >= BODY_STARTED)
+ (void)MimeDecParseLine(buffer, size, 0, state);
+ break;
+ } else {
+ (void) MimeDecParseLine(buffer, next - buffer, 1, state);
+ if (buffer + size < next + 1) {
+ break;
+ }
+ size -= next - buffer + 1;
+ buffer = next + 1;
+ }
+ }
+ /* Completed */
+ (void)MimeDecParseComplete(state);
+ /* De Init parser */
+ MimeDecDeInitParser(state);
+ MimeDecFreeEntity(msg_head);
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_predefpcap_aware.c b/src/tests/fuzz/fuzz_predefpcap_aware.c
new file mode 100644
index 0000000..c20e3d3
--- /dev/null
+++ b/src/tests/fuzz/fuzz_predefpcap_aware.c
@@ -0,0 +1,165 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for predefined signatures and pcap (aware)
+ */
+
+#include "suricata-common.h"
+#include "source-pcap-file.h"
+#include "detect-engine.h"
+#include "util-classification-config.h"
+#include "util-reference-config.h"
+#include "app-layer.h"
+#include "tm-queuehandlers.h"
+#include "util-cidr.h"
+#include "util-profiling.h"
+#include "util-proto-name.h"
+#include "detect-engine-tag.h"
+#include "detect-engine-threshold.h"
+#include "host-bit.h"
+#include "ippair-bit.h"
+#include "app-layer-htp.h"
+#include "detect-fast-pattern.h"
+#include "util-unittest-helper.h"
+#include "conf-yaml-loader.h"
+#include "pkt-var.h"
+#include "flow-util.h"
+#include "tm-modules.h"
+#include "tmqh-packetpool.h"
+#include "util-conf.h"
+#include "packet.h"
+
+#include <fuzz_pcap.h>
+
+int LLVMFuzzerInitialize(const int *argc, char ***argv);
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int initialized = 0;
+ThreadVars tv;
+DecodeThreadVars *dtv;
+// FlowWorkerThreadData
+void *fwd;
+SCInstance surifuzz;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+#include "confyaml.c"
+
+char *filepath = NULL;
+
+int LLVMFuzzerInitialize(const int *argc, char ***argv)
+{
+ filepath = dirname(strdup((*argv)[0]));
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ FPC_buffer_t pkts;
+ const u_char *pkt;
+ struct pcap_pkthdr header;
+ int r;
+ Packet *p;
+ size_t pcap_cnt = 0;
+
+ if (initialized == 0) {
+ // Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+
+ InitGlobal();
+
+ GlobalsInitPreConfig();
+ run_mode = RUNMODE_PCAP_FILE;
+ // redirect logs to /tmp
+ ConfigSetLogDirectory("/tmp/");
+ // disables checksums validation for fuzzing
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+ surifuzz.sig_file = malloc(strlen(filepath) + strlen("/fuzz.rules") + 1);
+ memcpy(surifuzz.sig_file, filepath, strlen(filepath));
+ memcpy(surifuzz.sig_file + strlen(filepath), "/fuzz.rules", strlen("/fuzz.rules"));
+ surifuzz.sig_file[strlen(filepath) + strlen("/fuzz.rules")] = 0;
+ surifuzz.sig_file_exclusive = 1;
+ // loads rules after init
+ surifuzz.delayed_detect = 1;
+
+ PostConfLoadedSetup(&surifuzz);
+ PreRunPostPrivsDropInit(run_mode);
+ PostConfLoadedDetectSetup(&surifuzz);
+
+ memset(&tv, 0, sizeof(tv));
+ tv.flow_queue = FlowQueueNew();
+ if (tv.flow_queue == NULL)
+ abort();
+ dtv = DecodeThreadVarsAlloc(&tv);
+ DecodeRegisterPerfCounters(dtv, &tv);
+ tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
+ StatsSetupPrivate(&tv);
+
+ extern uint16_t max_pending_packets;
+ max_pending_packets = 128;
+ PacketPoolInit();
+ if (DetectEngineReload(&surifuzz) < 0) {
+ return 0;
+ }
+
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+ initialized = 1;
+ }
+
+ if (size < FPC0_HEADER_LEN) {
+ return 0;
+ }
+ // initialize FPC with the buffer
+ if (FPC_init(&pkts, data, size) < 0) {
+ return 0;
+ }
+
+ // loop over packets
+ r = FPC_next(&pkts, &header, &pkt);
+ p = PacketGetFromAlloc();
+ if (p == NULL || r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
+ goto bail;
+ }
+ p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
+ p->datalink = pkts.datalink;
+ p->pkt_src = PKT_SRC_WIRE;
+ while (r > 0) {
+ if (PacketCopyData(p, pkt, header.caplen) == 0) {
+ // DecodePcapFile
+ TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
+ if (ecode == TM_ECODE_FAILED) {
+ break;
+ }
+ Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ }
+ r = FPC_next(&pkts, &header, &pkt);
+ if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
+ goto bail;
+ }
+ PacketRecycle(p);
+ p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
+ p->datalink = pkts.datalink;
+ pcap_cnt++;
+ p->pcap_cnt = pcap_cnt;
+ p->pkt_src = PKT_SRC_WIRE;
+ }
+bail:
+ if (p != NULL) {
+ PacketFree(p);
+ }
+ FlowReset();
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_siginit.c b/src/tests/fuzz/fuzz_siginit.c
new file mode 100644
index 0000000..80514b2
--- /dev/null
+++ b/src/tests/fuzz/fuzz_siginit.c
@@ -0,0 +1,59 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for SigInit
+ */
+
+
+#include "suricata-common.h"
+#include "util-reference-config.h"
+#include "util-classification-config.h"
+#include "detect-engine.h"
+#include "detect-parse.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static uint32_t cnt = 0;
+DetectEngineCtx *de_ctx = NULL;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (de_ctx == NULL) {
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+ //global init
+ InitGlobal();
+ run_mode = RUNMODE_UNITTEST;
+ MpmTableSetup();
+ SpmTableSetup();
+ EngineModeSetIDS();
+ SigTableSetup();
+ }
+ if (cnt++ == 1024) {
+ DetectEngineCtxFree(de_ctx);
+ de_ctx = NULL;
+ cnt = 0;
+ }
+ if (de_ctx == NULL) {
+ de_ctx = DetectEngineCtxInit();
+ BUG_ON(de_ctx == NULL);
+ de_ctx->flags |= DE_QUIET;
+ de_ctx->rule_file = (char *)"fuzzer";
+ }
+
+ char * buffer = malloc(size+1);
+ if (buffer) {
+ memcpy(buffer, data, size);
+ //null terminate string
+ buffer[size] = 0;
+ Signature *s = SigInit(de_ctx, buffer);
+ free(buffer);
+ if (s && s->next) {
+ SigFree(de_ctx, s->next);
+ s->next = NULL;
+ }
+ SigFree(de_ctx, s);
+ }
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_sigpcap.c b/src/tests/fuzz/fuzz_sigpcap.c
new file mode 100644
index 0000000..e5bd56d
--- /dev/null
+++ b/src/tests/fuzz/fuzz_sigpcap.c
@@ -0,0 +1,208 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for signature file and pcap file
+ */
+
+#include "suricata-common.h"
+#include "source-pcap-file.h"
+#include "detect-engine.h"
+#include "util-classification-config.h"
+#include "util-reference-config.h"
+#include "app-layer.h"
+#include "tm-queuehandlers.h"
+#include "util-cidr.h"
+#include "util-profiling.h"
+#include "util-proto-name.h"
+#include "detect-engine-tag.h"
+#include "detect-engine-threshold.h"
+#include "host-bit.h"
+#include "ippair-bit.h"
+#include "app-layer-htp.h"
+#include "detect-fast-pattern.h"
+#include "util-unittest-helper.h"
+#include "conf-yaml-loader.h"
+#include "pkt-var.h"
+#include "flow-util.h"
+#include "flow-worker.h"
+#include "tm-modules.h"
+#include "tmqh-packetpool.h"
+#include "util-file.h"
+#include "util-conf.h"
+#include "packet.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+
+static int initialized = 0;
+ThreadVars tv;
+DecodeThreadVars *dtv;
+//FlowWorkerThreadData
+void *fwd;
+SCInstance surifuzz;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+#include "confyaml.c"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ pcap_t * pkts;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ const u_char *pkt;
+ struct pcap_pkthdr *header;
+ int r;
+ Packet *p;
+ size_t pos;
+ size_t pcap_cnt = 0;
+
+ if (initialized == 0) {
+ //Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+
+ InitGlobal();
+
+ GlobalsInitPreConfig();
+ run_mode = RUNMODE_PCAP_FILE;
+ //redirect logs to /tmp
+ ConfigSetLogDirectory("/tmp/");
+ //disables checksums validation for fuzzing
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+ // do not load rules before reproducible DetectEngineReload
+ remove("/tmp/fuzz.rules");
+ surifuzz.sig_file = strdup("/tmp/fuzz.rules");
+ surifuzz.sig_file_exclusive = 1;
+ //loads rules after init
+ surifuzz.delayed_detect = 1;
+
+ PostConfLoadedSetup(&surifuzz);
+ PreRunPostPrivsDropInit(run_mode);
+ PostConfLoadedDetectSetup(&surifuzz);
+
+ memset(&tv, 0, sizeof(tv));
+ tv.flow_queue = FlowQueueNew();
+ if (tv.flow_queue == NULL)
+ abort();
+ dtv = DecodeThreadVarsAlloc(&tv);
+ DecodeRegisterPerfCounters(dtv, &tv);
+ tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
+ StatsSetupPrivate(&tv);
+
+ extern uint16_t max_pending_packets;
+ max_pending_packets = 128;
+ PacketPoolInit();
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+ initialized = 1;
+ }
+
+ /* TODO add yaml config
+ for (pos = 0; pos < size; pos++) {
+ if (data[pos] == 0) {
+ break;
+ }
+ }
+ if (ConfYamlLoadString(data, pos) != 0) {
+ return 0;
+ }
+ if (pos < size) {
+ //skip zero
+ pos++;
+ }
+ data += pos;
+ size -= pos;*/
+
+ for (pos=0; pos < size; pos++) {
+ if (data[pos] == 0) {
+ break;
+ }
+ }
+ if (pos > 0 && pos < size) {
+ // dump signatures to a file so as to reuse SigLoadSignatures
+ if (TestHelperBufferToFile(surifuzz.sig_file, data, pos-1) < 0) {
+ return 0;
+ }
+ } else {
+ if (TestHelperBufferToFile(surifuzz.sig_file, data, pos) < 0) {
+ return 0;
+ }
+ }
+
+ if (DetectEngineReload(&surifuzz) < 0) {
+ return 0;
+ }
+ DetectEngineThreadCtx *old_det_ctx = FlowWorkerGetDetectCtxPtr(fwd);
+
+ DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
+ de_ctx->ref_cnt--;
+ DetectEngineThreadCtx *new_det_ctx = DetectEngineThreadCtxInitForReload(&tv, de_ctx, 1);
+ FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
+
+ DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
+
+ if (pos < size) {
+ //skip zero
+ pos++;
+ }
+ data += pos;
+ size -= pos;
+
+ //rewrite buffer to a file as libpcap does not have buffer inputs
+ if (TestHelperBufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
+ return 0;
+ }
+
+ //initialize structure
+ pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
+ if (pkts == NULL) {
+ return 0;
+ }
+
+ //loop over packets
+ r = pcap_next_ex(pkts, &header, &pkt);
+ p = PacketGetFromAlloc();
+ if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
+ goto bail;
+ }
+ p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
+ p->datalink = pcap_datalink(pkts);
+ p->pkt_src = PKT_SRC_WIRE;
+ while (r > 0) {
+ if (PacketCopyData(p, pkt, header->caplen) == 0) {
+ // DecodePcapFile
+ TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
+ if (ecode == TM_ECODE_FAILED) {
+ break;
+ }
+ Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ }
+ r = pcap_next_ex(pkts, &header, &pkt);
+ if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
+ goto bail;
+ }
+ PacketRecycle(p);
+ p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
+ p->datalink = pcap_datalink(pkts);
+ p->pkt_src = PKT_SRC_WIRE;
+ pcap_cnt++;
+ p->pcap_cnt = pcap_cnt;
+ }
+bail:
+ //close structure
+ pcap_close(pkts);
+ PacketFree(p);
+ FlowReset();
+
+ return 0;
+}
diff --git a/src/tests/fuzz/fuzz_sigpcap_aware.c b/src/tests/fuzz/fuzz_sigpcap_aware.c
new file mode 100644
index 0000000..d245476
--- /dev/null
+++ b/src/tests/fuzz/fuzz_sigpcap_aware.c
@@ -0,0 +1,203 @@
+/**
+ * @file
+ * @author Philippe Antoine <contact@catenacyber.fr>
+ * fuzz target for AppLayerProtoDetectGetProto
+ */
+
+#include "suricata-common.h"
+#include "source-pcap-file.h"
+#include "detect-engine.h"
+#include "util-classification-config.h"
+#include "util-reference-config.h"
+#include "app-layer.h"
+#include "tm-queuehandlers.h"
+#include "util-cidr.h"
+#include "util-profiling.h"
+#include "util-proto-name.h"
+#include "detect-engine-tag.h"
+#include "detect-engine-threshold.h"
+#include "host-bit.h"
+#include "ippair-bit.h"
+#include "app-layer-htp.h"
+#include "detect-fast-pattern.h"
+#include "util-unittest-helper.h"
+#include "conf-yaml-loader.h"
+#include "pkt-var.h"
+#include "flow-util.h"
+#include "flow-worker.h"
+#include "tm-modules.h"
+#include "tmqh-packetpool.h"
+#include "util-conf.h"
+#include "packet.h"
+
+#include <fuzz_pcap.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int initialized = 0;
+ThreadVars tv;
+DecodeThreadVars *dtv;
+// FlowWorkerThreadData
+void *fwd;
+SCInstance surifuzz;
+SC_ATOMIC_EXTERN(unsigned int, engine_stage);
+
+#include "confyaml.c"
+
+static void SigGenerateAware(const uint8_t *data, size_t size, char *r, size_t *len)
+{
+ *len = snprintf(r, 511, "alert ip any any -> any any (");
+ for (size_t i = 0; i + 1 < size && *len < 511; i++) {
+ if (data[i] & 0x80) {
+ size_t off = (data[i] & 0x7F + ((data[i + 1] & 0xF) << 7)) %
+ (sizeof(sigmatch_table) / sizeof(SigTableElmt));
+ if (sigmatch_table[off].flags & SIGMATCH_NOOPT ||
+ ((data[i + 1] & 0x80) && sigmatch_table[off].flags & SIGMATCH_OPTIONAL_OPT)) {
+ *len += snprintf(r + *len, 511 - *len, "; %s;", sigmatch_table[off].name);
+ } else {
+ *len += snprintf(r + *len, 511 - *len, "; %s:", sigmatch_table[off].name);
+ }
+ i++;
+ } else {
+ r[*len] = data[i];
+ *len = *len + 1;
+ }
+ }
+ if (*len < 511) {
+ *len += snprintf(r + *len, 511 - *len, ")");
+ } else {
+ r[511] = 0;
+ *len = 511;
+ }
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ FPC_buffer_t pkts;
+ const u_char *pkt;
+ struct pcap_pkthdr header;
+ int r;
+ Packet *p;
+ size_t pos;
+ size_t pcap_cnt = 0;
+
+ if (initialized == 0) {
+ // Redirects logs to /dev/null
+ setenv("SC_LOG_OP_IFACE", "file", 0);
+ setenv("SC_LOG_FILE", "/dev/null", 0);
+
+ InitGlobal();
+
+ GlobalsInitPreConfig();
+ run_mode = RUNMODE_PCAP_FILE;
+ // redirect logs to /tmp
+ ConfigSetLogDirectory("/tmp/");
+ // disables checksums validation for fuzzing
+ if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
+ abort();
+ }
+ // do not load rules before reproducible DetectEngineReload
+ remove("/tmp/fuzz.rules");
+ surifuzz.sig_file = strdup("/tmp/fuzz.rules");
+ surifuzz.sig_file_exclusive = 1;
+ // loads rules after init
+ surifuzz.delayed_detect = 1;
+
+ PostConfLoadedSetup(&surifuzz);
+ PreRunPostPrivsDropInit(run_mode);
+ PostConfLoadedDetectSetup(&surifuzz);
+
+ memset(&tv, 0, sizeof(tv));
+ tv.flow_queue = FlowQueueNew();
+ if (tv.flow_queue == NULL)
+ abort();
+ dtv = DecodeThreadVarsAlloc(&tv);
+ DecodeRegisterPerfCounters(dtv, &tv);
+ tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
+ StatsSetupPrivate(&tv);
+
+ extern uint16_t max_pending_packets;
+ max_pending_packets = 128;
+ PacketPoolInit();
+ SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
+ initialized = 1;
+ }
+
+ if (size < 1 + FPC0_HEADER_LEN) {
+ return 0;
+ }
+ for (pos = 0; pos < size - FPC0_HEADER_LEN; pos++) {
+ if (data[pos] == 0) {
+ break;
+ }
+ }
+ // initialize FPC with the buffer
+ if (FPC_init(&pkts, data + pos + 1, size - pos - 1) < 0) {
+ return 0;
+ }
+
+ // dump signatures to a file so as to reuse SigLoadSignatures
+ char sigaware[512];
+ size_t len;
+ SigGenerateAware(data, pos + 1, sigaware, &len);
+ if (TestHelperBufferToFile(surifuzz.sig_file, (uint8_t *)sigaware, len) < 0) {
+ return 0;
+ }
+
+ if (DetectEngineReload(&surifuzz) < 0) {
+ return 0;
+ }
+ DetectEngineThreadCtx *old_det_ctx = FlowWorkerGetDetectCtxPtr(fwd);
+
+ DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
+ de_ctx->ref_cnt--;
+ DetectEngineThreadCtx *new_det_ctx = DetectEngineThreadCtxInitForReload(&tv, de_ctx, 1);
+ FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
+
+ DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
+
+ // loop over packets
+ r = FPC_next(&pkts, &header, &pkt);
+ p = PacketGetFromAlloc();
+ if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
+ goto bail;
+ }
+ p->pkt_src = PKT_SRC_WIRE;
+ p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
+ p->datalink = pkts.datalink;
+ while (r > 0) {
+ if (PacketCopyData(p, pkt, header.caplen) == 0) {
+ // DecodePcapFile
+ TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
+ if (ecode == TM_ECODE_FAILED) {
+ break;
+ }
+ Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ while (extra_p != NULL) {
+ PacketFreeOrRelease(extra_p);
+ extra_p = PacketDequeueNoLock(&tv.decode_pq);
+ }
+ }
+ r = FPC_next(&pkts, &header, &pkt);
+ if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
+ goto bail;
+ }
+ PacketRecycle(p);
+ p->pkt_src = PKT_SRC_WIRE;
+ p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
+ p->datalink = pkts.datalink;
+ pcap_cnt++;
+ p->pcap_cnt = pcap_cnt;
+ }
+bail:
+ PacketFree(p);
+ FlowReset();
+
+ return 0;
+}
diff --git a/src/tests/fuzz/onefile.c b/src/tests/fuzz/onefile.c
new file mode 100644
index 0000000..344ef8e
--- /dev/null
+++ b/src/tests/fuzz/onefile.c
@@ -0,0 +1,88 @@
+#include "suricata-common.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+
+static int runOneFile(const char *fname)
+{
+ // opens the file, get its size, and reads it into a buffer
+ uint8_t *data;
+ size_t size;
+ FILE *fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ return 2;
+ }
+ if (fseek(fp, 0L, SEEK_END) != 0) {
+ fclose(fp);
+ return 2;
+ }
+ size = ftell(fp);
+ if (size == (size_t) -1) {
+ fclose(fp);
+ return 2;
+ }
+ if (fseek(fp, 0L, SEEK_SET) != 0) {
+ fclose(fp);
+ return 2;
+ }
+ data = malloc(size);
+ if (data == NULL) {
+ fclose(fp);
+ return 2;
+ }
+ if (fread(data, size, 1, fp) != 1) {
+ fclose(fp);
+ free(data);
+ return 2;
+ }
+
+ // launch fuzzer
+ LLVMFuzzerTestOneInput(data, size);
+ free(data);
+ fclose(fp);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ DIR *d;
+ struct dirent *dir;
+ int r;
+
+ if (argc != 2) {
+ return 1;
+ }
+#ifdef AFLFUZZ_PERSISTENT_MODE
+ while (__AFL_LOOP(1000)) {
+#endif /* AFLFUZZ_PERSISTENT_MODE */
+
+ d = opendir(argv[1]);
+ if (d == NULL) {
+ // run one file
+ r = runOneFile(argv[1]);
+ if (r != 0) {
+ return r;
+ }
+ } else {
+ // run every file in one directory
+ if (chdir(argv[1]) != 0) {
+ closedir(d);
+ printf("Invalid directory\n");
+ return 2;
+ }
+ while ((dir = readdir(d)) != NULL) {
+ if (dir->d_type != DT_REG) {
+ continue;
+ }
+ r = runOneFile(dir->d_name);
+ if (r != 0) {
+ return r;
+ }
+ }
+ closedir(d);
+ }
+#ifdef AFLFUZZ_PERSISTENT_MODE
+ }
+#endif /* AFLFUZZ_PERSISTENT_MODE */
+
+ return 0;
+}
diff --git a/src/tests/reputation.c b/src/tests/reputation.c
new file mode 100644
index 0000000..8b72a8a
--- /dev/null
+++ b/src/tests/reputation.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2019 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.
+ */
+
+/**
+ *
+ * \author Giuseppe Longo <giuseppe@glongo.it>
+ *
+ */
+
+#include "conf-yaml-loader.h"
+#include "detect-engine.h"
+#include "stream-tcp-private.h"
+#include "stream-tcp-reassemble.h"
+#include "stream-tcp.h"
+#include "util-unittest-helper.h"
+
+#define TEST_INIT \
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
+ FAIL_IF(de_ctx == NULL); \
+ SRepInit(de_ctx); \
+ \
+ Address a; \
+ uint8_t cat = 0, value = 0;
+
+#define TEST_INIT_WITH_PACKET_IPV6(src, dst) \
+ uint8_t *buf = (uint8_t *)"Hi all!"; \
+ uint16_t buflen = strlen((char *)buf); \
+ Packet *p = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, (src), (dst)); \
+ FAIL_IF(p == NULL); \
+ TEST_INIT
+
+#define TEST_INIT_WITH_PACKET(ip) \
+ uint8_t *buf = (uint8_t *)"Hi all!"; \
+ uint16_t buflen = strlen((char *)buf); \
+ Packet *p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP); \
+ FAIL_IF(p == NULL); \
+ p->src.addr_data32[0] = UTHSetIPv4Address(ip); \
+ TEST_INIT
+
+#define TEST_CLEANUP \
+ DetectEngineCtxFree(de_ctx);
+
+#define TEST_CLEANUP_WITH_PACKET \
+ UTHFreePacket(p); \
+ TEST_CLEANUP
+
+static int SRepTest01(void)
+{
+ TEST_INIT;
+
+ char ipstr[16];
+ char str[] = "1.2.3.4,1,2";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 0);
+ PrintInet(AF_INET, (const void *)&a.address, ipstr, sizeof(ipstr));
+ FAIL_IF(strcmp(ipstr, "1.2.3.4") != 0);
+ FAIL_IF(cat != 1);
+ FAIL_IF(value != 2);
+
+ TEST_CLEANUP;
+ PASS;
+}
+
+static int SRepTest02(void)
+{
+ TEST_INIT;
+
+ char str[] = "1.1.1.1,";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) == 0);
+
+ TEST_CLEANUP;
+ PASS;
+}
+
+static int SRepTest03(void)
+{
+ char str[] = "1,Shortname,Long Name";
+ uint8_t cat = 0;
+ char shortname[SREP_SHORTNAME_LEN];
+
+ FAIL_IF(SRepCatSplitLine(str, &cat, shortname, sizeof(shortname)) != 0);
+ FAIL_IF(strcmp(shortname, "Shortname") != 0);
+ FAIL_IF(cat != 1);
+
+ PASS;
+}
+
+static int SRepTest04(void)
+{
+ TEST_INIT;
+
+ char str[] = "10.0.0.0/16,1,2";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 1);
+
+ TEST_CLEANUP;
+ PASS;
+}
+
+static int SRepTest05(void)
+{
+ TEST_INIT_WITH_PACKET("10.0.0.1");
+
+ char str[] = "10.0.0.0/16,1,20";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 1);
+
+ cat = 1;
+ FAIL_IF(SRepCIDRGetIPRepSrc(de_ctx->srepCIDR_ctx, p, cat, 0) != 20);
+
+ TEST_CLEANUP_WITH_PACKET;
+ PASS;
+}
+
+static int SRepTest06(void)
+{
+ TEST_INIT_WITH_PACKET("192.168.0.1");
+
+ char str1[] = "0.0.0.0/0,1,10\n";
+ char str2[] = "192.168.0.0/16,2,127";
+
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str1, &a, &cat, &value) != 1);
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str2, &a, &cat, &value) != 1);
+
+ cat = 1;
+ FAIL_IF(SRepCIDRGetIPRepSrc(de_ctx->srepCIDR_ctx, p, cat, 0) != 10);
+
+ TEST_CLEANUP_WITH_PACKET;
+ PASS;
+}
+
+static int SRepTest07(void) {
+ TEST_INIT;
+
+ char str[] = "2000:0000:0000:0000:0000:0000:0000:0001,";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) == 0);
+
+ TEST_CLEANUP;
+ PASS;
+}
+
+static int SRepTest08(void)
+{
+ TEST_INIT_WITH_PACKET_IPV6("2000:0000:0000:0000:0000:0000:0000:0001", "FFFF::1");
+
+ char str1[] = "0.0.0.0/0,1,10\n";
+ char str2[] = "192.168.0.0/16,2,127\n";
+ char str3[] = "2000::/3,1,10\n";
+ char str4[] = "FFFF::/127,2,127\n";
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str1, &a, &cat, &value) != 1);
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str2, &a, &cat, &value) != 1);
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str3, &a, &cat, &value) != 1);
+ FAIL_IF(SRepSplitLine(de_ctx->srepCIDR_ctx, str4, &a, &cat, &value) != 1);
+
+ cat = 1;
+ FAIL_IF(SRepCIDRGetIPRepSrc(de_ctx->srepCIDR_ctx, p, cat, 0) != 10);
+
+ TEST_CLEANUP_WITH_PACKET;
+ PASS;
+}
+
+/** Register the following unittests for the Reputation module */
+void SCReputationRegisterTests(void)
+{
+ UtRegisterTest("SRepTest01", SRepTest01);
+ UtRegisterTest("SRepTest02", SRepTest02);
+ UtRegisterTest("SRepTest03", SRepTest03);
+ UtRegisterTest("SRepTest04", SRepTest04);
+ UtRegisterTest("SRepTest05", SRepTest05);
+ UtRegisterTest("SRepTest06", SRepTest06);
+ UtRegisterTest("SRepTest07", SRepTest07);
+ UtRegisterTest("SRepTest08", SRepTest08);
+}
diff --git a/src/tests/source-pcap.c b/src/tests/source-pcap.c
new file mode 100644
index 0000000..fc1b275
--- /dev/null
+++ b/src/tests/source-pcap.c
@@ -0,0 +1,232 @@
+/* Copyright (C) 2020 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.
+ */
+
+#include "../suricata-common.h"
+#include "../util-unittest.h"
+
+static uint32_t Upper32(uint64_t value)
+{
+ /* uint64_t -> uint32_t is defined behaviour. It slices lower 32bits. */
+ return value >> 32;
+}
+static uint32_t Lower32(uint64_t value)
+{
+ /* uint64_t -> uint32_t is defined behaviour. It slices lower 32bits. */
+ return value;
+}
+
+/* Structured test data to make it easier on my eyes */
+typedef struct TestData_ {
+ uint64_t last; /* internal 64bit counter to drag along */
+ u_int current; /* 32bit pcap stat */
+} TestData;
+
+static int UpdatePcapStatsValue64NoChange01(void)
+{
+ /*
+ * No change in counter values.
+ * Last count is within first 32bit range, i.e. same as pcap_stat range.
+ */
+ TestData data[] = {{.last = 0, .current = 0},
+ {.last = 12345, .current = 12345},
+ {.last = (uint64_t)UINT32_MAX, .current = UINT_MAX}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ FAIL_IF_NOT(data[i].last == data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(data[i].last == data[i].current);
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64NoChange02(void)
+{
+ /*
+ * No change in counter values.
+ * Last count is outside 32bits range.
+ */
+ TestData data[] = {{.last = (2ull << 32) + 0, .current = 0},
+ {.last = (3ull << 32) + 12345, .current = 12345},
+ {.last = (3ull << 32) + (uint64_t)UINT32_MAX, .current = UINT_MAX},
+ {.last = UINT64_MAX, .current = UINT_MAX}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ uint32_t upper = Upper32(data[i].last);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+ FAIL_IF_NOT(Upper32(data[i].last) == upper);
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64NoOverflow01(void)
+{
+ /*
+ * Non-overflowing counter value is simply taken over in lower 32bits.
+ * Last count is within first 32bit range, i.e. same as pcap_stat range.
+ * Also test edges and simple +1.
+ */
+ TestData data[] = {{.last = 0, .current = 1},
+ {.last = 12345, .current = 34567},
+ {.last = (uint64_t)UINT32_MAX - 1, .current = UINT_MAX}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ FAIL_IF_NOT(data[i].last < data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(data[i].last == data[i].current);
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64NoOverflow02(void)
+{
+ /*
+ * Non-overflowing counter value is simply taken over in lower 32bits.
+ * Last count is outside 32bits range.
+ */
+ TestData data[] = {{.last = (2ull << 32) + 0, .current = 1},
+ {.last = (3ull << 32) + 12345, .current = 34567},
+ {.last = UINT64_MAX - 1, .current = UINT_MAX}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ uint32_t upper = Upper32(data[i].last);
+ FAIL_IF_NOT(Lower32(data[i].last) < data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+ FAIL_IF_NOT(Upper32(data[i].last) == upper);
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64Overflow01(void)
+{
+ /*
+ * Overflowing counter value is simply taken over in lower 32bits.
+ * Last count is within first 32bit range, i.e. same as pcap_stat range.
+ */
+ TestData data[] = {{.last = 1, .current = 0},
+ {.last = 12345, .current = 22}, {.last = 12345, .current = 12344},
+ {.last = (uint64_t)UINT32_MAX, .current = UINT_MAX - 1}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ FAIL_IF_NOT(data[i].last > data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+ FAIL_IF_NOT(Upper32(data[i].last) == 1); /* wrap around */
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64Overflow02(void)
+{
+ /*
+ * Overflowing counter value is simply taken over in lower 32bits.
+ * Last count is outside 32bits range.
+ */
+ TestData data[] = {{.last = (2ull << 32) + 1, .current = 0},
+ {.last = (3ull << 32) + 12345, .current = 22},
+ {.last = (3ull << 32) + 12345, .current = 12344},
+ {.last = UINT64_MAX, .current = UINT_MAX - 1}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ uint32_t upper = Upper32(data[i].last);
+ FAIL_IF_NOT(Lower32(data[i].last) > data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+ FAIL_IF_NOT(Upper32(data[i].last) == upper + 1); /* wrap around */
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStatsValue64Overflow03(void)
+{
+ /*
+ * Overflowing counter value is simply taken over in lower 32bits.
+ * Edge cases where upper32 bit wrap around to 0.
+ */
+ TestData data[] = {{.last = UINT64_MAX, .current = 0},
+ {.last = UINT64_MAX, .current = 3333}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); ++i) {
+ FAIL_IF_NOT(Lower32(data[i].last) > data[i].current);
+
+ UpdatePcapStatsValue64(&data[i].last, data[i].current);
+ FAIL_IF_NOT(Lower32(data[i].last) == data[i].current);
+ FAIL_IF_NOT(Upper32(data[i].last) == 0); /* wrap around */
+ }
+
+ PASS;
+}
+
+static int UpdatePcapStats64Assorted01(void)
+{
+ /*
+ * Test that all fields of the struct are correctly updated.
+ *
+ * Full testing of value behaviour is done in UpdatePcapStatsValue64...()
+ * tests.
+ */
+ PcapStats64 last = {.ps_recv = 0, .ps_drop = 1234, .ps_ifdrop = 8765};
+ struct pcap_stat current = {
+ .ps_recv = 12, .ps_drop = 2345, .ps_ifdrop = 9876};
+
+ // test setup sanity check
+ FAIL_IF_NOT(last.ps_recv < current.ps_recv);
+ FAIL_IF_NOT(last.ps_drop < current.ps_drop);
+ FAIL_IF_NOT(last.ps_ifdrop < current.ps_ifdrop);
+
+ UpdatePcapStats64(&last, &current);
+
+ FAIL_IF_NOT(last.ps_recv == current.ps_recv);
+ FAIL_IF_NOT(last.ps_drop == current.ps_drop);
+ FAIL_IF_NOT(last.ps_ifdrop == current.ps_ifdrop);
+
+ PASS;
+}
+
+static void SourcePcapRegisterStatsTests(void)
+{
+ UtRegisterTest("UpdatePcapStatsValue64NoChange01",
+ UpdatePcapStatsValue64NoChange01);
+ UtRegisterTest("UpdatePcapStatsValue64NoChange02",
+ UpdatePcapStatsValue64NoChange02);
+ UtRegisterTest("UpdatePcapStatsValue64NoOverflow01",
+ UpdatePcapStatsValue64NoOverflow01);
+ UtRegisterTest("UpdatePcapStatsValue64NoOverflow02",
+ UpdatePcapStatsValue64NoOverflow02);
+ UtRegisterTest("UpdatePcapStatsValue64Overflow01",
+ UpdatePcapStatsValue64Overflow01);
+ UtRegisterTest("UpdatePcapStatsValue64Overflow02",
+ UpdatePcapStatsValue64Overflow02);
+ UtRegisterTest("UpdatePcapStatsValue64Overflow03",
+ UpdatePcapStatsValue64Overflow03);
+
+ UtRegisterTest("UpdatePcapStats64Assorted01", UpdatePcapStats64Assorted01);
+}
diff --git a/src/tests/stream-tcp-inline.c b/src/tests/stream-tcp-inline.c
new file mode 100644
index 0000000..410451a
--- /dev/null
+++ b/src/tests/stream-tcp-inline.c
@@ -0,0 +1,196 @@
+/* Copyright (C) 2007-2017 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.
+ */
+
+#include "../suricata-common.h"
+#include "../stream-tcp-private.h"
+#include "../stream-tcp.h"
+#include "../stream-tcp-reassemble.h"
+#include "../stream-tcp-inline.h"
+#include "../stream-tcp-list.h"
+#include "../stream-tcp-util.h"
+#include "../util-streaming-buffer.h"
+#include "../util-print.h"
+#include "../util-unittest.h"
+
+static int VALIDATE(TcpStream *stream, uint8_t *data, uint32_t data_len)
+{
+ if (StreamingBufferCompareRawData(&stream->sb,
+ data, data_len) == 0)
+ {
+ SCReturnInt(0);
+ }
+ SCLogInfo("OK");
+ PrintRawDataFp(stdout, data, data_len);
+ return 1;
+}
+
+#define INLINE_START(isn) \
+ Packet *p; \
+ TcpReassemblyThreadCtx *ra_ctx = NULL; \
+ TcpSession ssn; \
+ ThreadVars tv; \
+ memset(&tv, 0, sizeof(tv)); \
+ \
+ StreamTcpUTInit(&ra_ctx); \
+ StreamTcpUTInitInline(); \
+ \
+ StreamTcpUTSetupSession(&ssn); \
+ StreamTcpUTSetupStream(&ssn.server, (isn)); \
+ StreamTcpUTSetupStream(&ssn.client, (isn)); \
+ \
+ TcpStream *stream = &ssn.client;
+
+#define INLINE_END \
+ StreamTcpUTClearSession(&ssn); \
+ StreamTcpUTDeinit(ra_ctx); \
+ PASS
+
+#define INLINE_ADD_PAYLOAD(rseq, seg, seglen, packet, packetlen) \
+ p = UTHBuildPacketReal( \
+ (uint8_t *)(seg), (seglen), IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); \
+ FAIL_IF(p == NULL); \
+ p->tcph->th_seq = htonl(stream->isn + (rseq)); \
+ p->tcph->th_ack = htonl(31); \
+ FAIL_IF(StreamTcpReassembleHandleSegmentHandleData(&tv, ra_ctx, &ssn, stream, p) < 0); \
+ FAIL_IF(memcmp(p->payload, packet, MIN((packetlen), p->payload_len)) != 0); \
+ UTHFreePacket(p);
+
+#define INLINE_STEP(rseq, seg, seglen, buf, buflen, packet, packetlen) \
+ INLINE_ADD_PAYLOAD((rseq), (seg), (seglen), (packet), (packetlen)); \
+ FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
+
+int UTHCheckGapAtPosition(TcpStream *stream, int pos, uint64_t offset, uint32_t len);
+int UTHCheckDataAtPosition(
+ TcpStream *stream, int pos, uint64_t offset, const char *data, uint32_t len);
+
+/** \test full overlap */
+static int StreamTcpInlineTest01(void)
+{
+ INLINE_START(0);
+ INLINE_STEP(1, "AAC", 3, "AAC", 3, "AAC", 3);
+ INLINE_STEP(1, "ABC", 3, "AAC", 3, "AAC", 3);
+ INLINE_END;
+}
+
+/** \test full overlap */
+static int StreamTcpInlineTest02(void)
+{
+ INLINE_START(0);
+ INLINE_STEP(1, "ABCDE", 5, "ABCDE", 5, "ABCDE", 5);
+ INLINE_STEP(2, "xxx", 3, "ABCDE", 5, "BCD", 3);
+ INLINE_END;
+}
+
+/** \test partial overlap */
+static int StreamTcpInlineTest03(void)
+{
+ INLINE_START(0);
+ INLINE_STEP(1, "ABCDE", 5, "ABCDE", 5, "ABCDE", 5);
+ INLINE_STEP(3, "xxxxx", 5, "ABCDExx", 7, "CDExx", 5);
+ INLINE_END;
+}
+
+/** \test partial overlap */
+static int StreamTcpInlineTest04(void)
+{
+ INLINE_START(0);
+ INLINE_ADD_PAYLOAD(3, "ABCDE", 5, "ABCDE", 5);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 2) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 2, "ABCDE", 5) == 1);
+ INLINE_STEP(1, "xxxxx", 5, "xxABCDE", 7, "xxABC", 5);
+ INLINE_END;
+}
+
+/** \test no overlap */
+static int StreamTcpInlineTest05(void)
+{
+ INLINE_START(0);
+ INLINE_ADD_PAYLOAD(8, "ABCDE", 5, "ABCDE", 5);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 7) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 7, "ABCDE", 5) == 1);
+ INLINE_ADD_PAYLOAD(1, "xxxxx", 5, "xxxxx", 5);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 0, 0, "xxxxx", 5) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 1, 5, 2) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 2, 7, "ABCDE", 5) == 1);
+ INLINE_END;
+}
+
+/** \test multiple overlaps */
+static int StreamTcpInlineTest06(void)
+{
+ INLINE_START(0);
+ INLINE_ADD_PAYLOAD(2, "A", 1, "A", 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 1, "A", 1) == 1);
+ INLINE_ADD_PAYLOAD(4, "A", 1, "A", 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 1, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 2, 2, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 3, 3, "A", 1) == 1);
+ INLINE_ADD_PAYLOAD(6, "A", 1, "A", 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 1, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 2, 2, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 3, 3, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 4, 4, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 5, 5, "A", 1) == 1);
+ INLINE_ADD_PAYLOAD(8, "A", 1, "A", 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 1, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 2, 2, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 3, 3, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 4, 4, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 5, 5, "A", 1) == 1);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 6, 6, 1) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 7, 7, "A", 1) == 1);
+ INLINE_STEP(1, "xxxxxxxxx", 9, "xAxAxAxAx", 9, "xAxAxAxAx", 9);
+ INLINE_END;
+}
+
+/** \test overlap, data not different */
+static int StreamTcpInlineTest07(void)
+{
+ INLINE_START(0);
+ INLINE_ADD_PAYLOAD(3, "ABCDE", 5, "ABCDE", 5);
+ FAIL_IF_NOT(UTHCheckGapAtPosition(stream, 0, 0, 2) == 1);
+ FAIL_IF_NOT(UTHCheckDataAtPosition(stream, 1, 2, "ABCDE", 5) == 1);
+ INLINE_STEP(1, "XXABC", 5, "XXABCDE", 7, "XXABC", 5);
+ INLINE_END;
+}
+
+static int StreamTcpInlineTest08(void)
+{
+ INLINE_START(0);
+ INLINE_STEP(1, "AAAAA", 5, "AAAAA", 5, "AAAAA", 5);
+ INLINE_STEP(1, "BBBBB", 5, "AAAAA", 5, "AAAAA", 5);
+ INLINE_STEP(1, "CCCCCCCCCC", 10, "AAAAACCCCC", 10, "AAAAACCCCC", 10);
+ INLINE_STEP(10, "X", 1, "AAAAACCCCC", 10, "C", 1);
+ INLINE_STEP(11, "X", 1, "AAAAACCCCCX", 11, "X", 1);
+ INLINE_END;
+}
+
+void StreamTcpInlineRegisterTests(void)
+{
+ UtRegisterTest("StreamTcpInlineTest01", StreamTcpInlineTest01);
+ UtRegisterTest("StreamTcpInlineTest02", StreamTcpInlineTest02);
+ UtRegisterTest("StreamTcpInlineTest03", StreamTcpInlineTest03);
+ UtRegisterTest("StreamTcpInlineTest04", StreamTcpInlineTest04);
+ UtRegisterTest("StreamTcpInlineTest05", StreamTcpInlineTest05);
+ UtRegisterTest("StreamTcpInlineTest06", StreamTcpInlineTest06);
+ UtRegisterTest("StreamTcpInlineTest07", StreamTcpInlineTest07);
+ UtRegisterTest("StreamTcpInlineTest08", StreamTcpInlineTest08);
+}
diff --git a/src/tests/stream-tcp-list.c b/src/tests/stream-tcp-list.c
new file mode 100644
index 0000000..d10c756
--- /dev/null
+++ b/src/tests/stream-tcp-list.c
@@ -0,0 +1,732 @@
+/* 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.
+ */
+
+#include "../suricata-common.h"
+#include "../stream-tcp-private.h"
+#include "../stream-tcp.h"
+#include "../stream-tcp-reassemble.h"
+#include "../stream-tcp-inline.h"
+#include "../stream-tcp-list.h"
+#include "../stream-tcp-util.h"
+#include "../util-streaming-buffer.h"
+#include "../util-print.h"
+#include "../util-unittest.h"
+
+static int VALIDATE(TcpStream *stream, uint8_t *data, uint32_t data_len)
+{
+ // HACK: these tests should be updated to check the SBB blocks
+ if (memcmp(stream->sb.region.buf, data, data_len) != 0) {
+ SCReturnInt(0);
+ }
+ SCLogInfo("OK");
+ PrintRawDataFp(stdout, data, data_len);
+ return 1;
+}
+
+#define OVERLAP_START(isn, policy) \
+ TcpReassemblyThreadCtx *ra_ctx = NULL; \
+ TcpSession ssn; \
+ ThreadVars tv; \
+ memset(&tv, 0, sizeof(tv)); \
+ \
+ StreamTcpUTInit(&ra_ctx); \
+ \
+ StreamTcpUTSetupSession(&ssn); \
+ StreamTcpUTSetupStream(&ssn.server, (isn)); \
+ StreamTcpUTSetupStream(&ssn.client, (isn)); \
+ \
+ TcpStream *stream = &ssn.client; \
+ stream->os_policy = (policy);
+
+#define OVERLAP_END \
+ StreamTcpUTClearSession(&ssn); \
+ StreamTcpUTDeinit(ra_ctx); \
+ PASS
+
+#define OVERLAP_STEP(rseq, seg, seglen, buf, buflen) \
+ StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, stream->isn + (rseq), (uint8_t *)(seg), (seglen)); \
+ FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
+
+static int OverlapBSD(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_BSD);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* AA not overwritten, gap filled and B overwritten because 'starts before' */
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AAAJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* no-op, overlaps CCC which takes precedence */
+ OVERLAP_STEP(8, "KKK", 3, "\0AAAJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* LLL fills gaps and replaces D as it starts before */
+ OVERLAP_STEP(11, "LLL", 3, "\0AAAJJBCCCLLL\0EEFFFGGHHI", 24);
+ /* MMM fills gap and replaces EE as it starts before */
+ OVERLAP_STEP(14, "MMM", 3, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(18, "N", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(21, "O", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(22, "P", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no replace of I as it starts the same */
+ OVERLAP_STEP(24, "QQ", 2, "\0AAAJJBCCCLLLMMMFFFGGHHIQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AAAJJBCCCLLLMMMFFFGGHHIQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapBSDBefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_BSD);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AA\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JJJJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JJJJ\0\0\0LLL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JJJJ\0\0\0LLLMMM", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapBSDSame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_BSD);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ /* ignored as 'starts the same' */
+ OVERLAP_STEP(1, "KKK", 3, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ /* original data not overwritten as it starts on the same seq */
+ OVERLAP_STEP(1, "LLLL", 4, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapBSDAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_BSD);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(17, "N", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+
+ OVERLAP_END;
+}
+
+static int OverlapVISTA(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_VISTA);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* AA not overwritten, gap filled and B not overwritten */
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AAAJBBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* no-op, overlaps CCC which takes precedence */
+ OVERLAP_STEP(8, "KKK", 3, "\0AAAJBBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* LLL fills gaps only */
+ OVERLAP_STEP(11, "LLL", 3, "\0AAAJBBCCCLDL\0EEFFFGGHHI", 24);
+ /* MMM fills gap only */
+ OVERLAP_STEP(14, "MMM", 3, "\0AAAJBBCCCLDLMEEFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(18, "N", 1, "\0AAAJBBCCCLDLMEEFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(21, "O", 1, "\0AAAJBBCCCLDLMEEFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(22, "P", 1, "\0AAAJBBCCCLDLMEEFFFGGHHI", 24);
+ /* no replace of I */
+ OVERLAP_STEP(24, "QQ", 2, "\0AAAJBBCCCLDLMEEFFFGGHHIQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AAAJBBCCCLDLMEEFFFGGHHIQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapVISTABefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_VISTA);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AB\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JABJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JABJ\0\0\0LDL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JABJ\0\0\0LDLMEE", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapVISTASame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_VISTA);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "KKK", 3, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "LLLL", 4, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "CCCL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapVISTAAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_VISTA);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(17, "N", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUX(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LINUX);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* AA not overwritten, gap filled and B not overwritten */
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AAAJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* no-op, overlaps CCC which takes precedence */
+ OVERLAP_STEP(8, "KKK", 3, "\0AAAJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* LLL fills gaps and replaces as begins before */
+ OVERLAP_STEP(11, "LLL", 3, "\0AAAJJBCCCLLL\0EEFFFGGHHI", 24);
+ /* MMM fills gap and replaces EE as it begins before */
+ OVERLAP_STEP(14, "MMM", 3, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(18, "N", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(21, "O", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(22, "P", 1, "\0AAAJJBCCCLLLMMMFFFGGHHI", 24);
+ /* replaces of I as begins the same, ends after*/
+ OVERLAP_STEP(24, "QQ", 2, "\0AAAJJBCCCLLLMMMFFFGGHHQQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AAAJJBCCCLLLMMMFFFGGHHQQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXBefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LINUX);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AA\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JJJJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JJJJ\0\0\0LLL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JJJJ\0\0\0LLLMMM", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXSame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LINUX);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "KKK", 3, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "LLLL", 4, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LINUX);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(17, "N", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXOLD(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_OLD_LINUX);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* AA not overwritten as it starts before, gap filled and B overwritten */
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AAAJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* replace CCC */
+ OVERLAP_STEP(8, "KKK", 3, "\0AAAJJBKKK\0D\0\0EEFFFGGHHI", 24);
+ /* LLL fills gaps and replaces as begins before */
+ OVERLAP_STEP(11, "LLL", 3, "\0AAAJJBKKKLLL\0EEFFFGGHHI", 24);
+ /* MMM fills gap and replaces EE as it begins before */
+ OVERLAP_STEP(14, "MMM", 3, "\0AAAJJBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(18, "N", 1, "\0AAAJJBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(21, "O", 1, "\0AAAJJBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(22, "P", 1, "\0AAAJJBKKKLLLMMMFFFGGHHI", 24);
+ /* replaces of I as begins the same, ends after*/
+ OVERLAP_STEP(24, "QQ", 2, "\0AAAJJBKKKLLLMMMFFFGGHHQQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AAAJJBKKKLLLMMMFFFGGHHQQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXOLDBefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_OLD_LINUX);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AA\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JJJJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JJJJ\0\0\0LLL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JJJJ\0\0\0LLLMMM", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXOLDSame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_OLD_LINUX);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "KKK", 3, "KKK\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "LLLL", 4, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "LLLL\0\0\0\0\0\0\0\0\0\0QQII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapLINUXOLDAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_OLD_LINUX);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(17, "N", 1, "AAJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+
+ OVERLAP_END;
+}
+
+static int OverlapSOLARIS(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_SOLARIS);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AJJJBBCCC\0D\0\0EEFFFGGHHI", 24);
+ /* replace CCC */
+ OVERLAP_STEP(8, "KKK", 3, "\0AJJJBBKKK\0D\0\0EEFFFGGHHI", 24);
+ /* LLL fills gaps and replaces as begins before */
+ OVERLAP_STEP(11, "LLL", 3, "\0AJJJBBKKKLLL\0EEFFFGGHHI", 24);
+ /* MMM fills gap and replaces EE as it begins before */
+ OVERLAP_STEP(14, "MMM", 3, "\0AJJJBBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(18, "N", 1, "\0AJJJBBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(21, "O", 1, "\0AJJJBBKKKLLLMMMFFFGGHHI", 24);
+ /* no op */
+ OVERLAP_STEP(22, "P", 1, "\0AJJJBBKKKLLLMMMFFFGGHHI", 24);
+ /* replaces of I as begins the same, ends after*/
+ OVERLAP_STEP(24, "QQ", 2, "\0AJJJBBKKKLLLMMMFFFGGHHQQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AJJJBBKKKLLLMMMFFFGGHHQQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapSOLARISBefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_SOLARIS);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AA\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JJJJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JJJJ\0\0\0LLL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JJJJ\0\0\0LLLMMM", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapSOLARISSame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_SOLARIS);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "KKK", 3, "KKK\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "LLLL", 4, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "LLLL\0\0\0\0\0\0\0\0\0\0QQII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapSOLARISAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_SOLARIS);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(17, "N", 1, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+
+ OVERLAP_END;
+}
+
+static int OverlapLAST(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LAST);
+
+ OVERLAP_STEP(2, "AAA", 3, "\0AAA", 4);
+ OVERLAP_STEP(6, "BB", 2, "\0AAA\0BB", 7);
+ OVERLAP_STEP(8, "CCC", 3, "\0AAA\0BBCCC", 10);
+ OVERLAP_STEP(12, "D", 1, "\0AAA\0BBCCC\0D", 12);
+ OVERLAP_STEP(15, "EE", 2, "\0AAA\0BBCCC\0D\0\0EE", 16);
+ OVERLAP_STEP(17, "FFF", 3, "\0AAA\0BBCCC\0D\0\0EEFFF", 19);
+ OVERLAP_STEP(20, "GG", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGG", 21);
+ OVERLAP_STEP(22, "HH", 2, "\0AAA\0BBCCC\0D\0\0EEFFFGGHH", 23);
+ OVERLAP_STEP(24, "I", 1, "\0AAA\0BBCCC\0D\0\0EEFFFGGHHI", 24);
+ OVERLAP_STEP(3, "JJJJ", 4, "\0AJJJJBCCC\0D\0\0EEFFFGGHHI", 24);
+ OVERLAP_STEP(8, "KKK", 3, "\0AJJJJBKKK\0D\0\0EEFFFGGHHI", 24);
+ OVERLAP_STEP(11, "LLL", 3, "\0AJJJJBKKKLLL\0EEFFFGGHHI", 24);
+ OVERLAP_STEP(14, "MMM", 3, "\0AJJJJBKKKLLLMMMFFFGGHHI", 24);
+ OVERLAP_STEP(18, "N", 1, "\0AJJJJBKKKLLLMMMFNFGGHHI", 24);
+ OVERLAP_STEP(21, "O", 1, "\0AJJJJBKKKLLLMMMFNFGOHHI", 24);
+ OVERLAP_STEP(22, "P", 1, "\0AJJJJBKKKLLLMMMFNFGOPHI", 24);
+ OVERLAP_STEP(24, "QQ", 2, "\0AJJJJBKKKLLLMMMFNFGOPHQQ", 25);
+ OVERLAP_STEP(1, "0", 1, "0AJJJJBKKKLLLMMMFNFGOPHQQ", 25);
+
+ OVERLAP_END;
+}
+
+static int OverlapLASTBefore(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LAST);
+
+ OVERLAP_STEP(3, "B", 1, "\0\0B", 3);
+ OVERLAP_STEP(9, "D", 1, "\0\0B\0\0\0\0\0D", 9);
+ OVERLAP_STEP(12, "EE", 2, "\0\0B\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(2, "AA", 2, "\0AA\0\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(1, "JJJJ", 4, "JJJJ\0\0\0\0D\0\0EE", 13);
+ OVERLAP_STEP(8, "LLL", 3, "JJJJ\0\0\0LLL\0EE", 13);
+ OVERLAP_STEP(11,"MMM", 3, "JJJJ\0\0\0LLLMMM", 13);
+
+ OVERLAP_END;
+}
+
+static int OverlapLASTSame(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LAST);
+
+ OVERLAP_STEP(1, "CCC", 3, "CCC", 3);
+ OVERLAP_STEP(15, "HH", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HH", 16);
+ OVERLAP_STEP(17, "II", 2, "CCC\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "KKK", 3, "KKK\0\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(1, "LLLL", 4, "LLLL\0\0\0\0\0\0\0\0\0\0HHII", 18);
+ OVERLAP_STEP(15, "P", 1, "LLLL\0\0\0\0\0\0\0\0\0\0PHII", 18);
+ OVERLAP_STEP(15, "QQ", 2, "LLLL\0\0\0\0\0\0\0\0\0\0QQII", 18);
+
+ OVERLAP_END;
+}
+
+static int OverlapLASTAfter(uint32_t isn)
+{
+ OVERLAP_START(isn, OS_POLICY_LAST);
+
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(16, "FFF", 3, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFF", 18);
+ OVERLAP_STEP(19, "GG", 2, "AA\0\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(2, "JJ", 2, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGG", 20);
+ OVERLAP_STEP(20, "O", 1, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FFFGO", 20);
+ OVERLAP_STEP(17, "N", 1, "AJJ\0\0\0\0\0\0\0\0\0\0\0\0FNFGO", 20);
+
+ OVERLAP_END;
+}
+
+/** \test BSD policy
+ */
+static int StreamTcpReassembleTest01(void)
+{
+ FAIL_IF(OverlapBSD(0) == 0);
+ OverlapBSDBefore(0);
+ OverlapBSDSame(0);
+ OverlapBSDAfter(0);
+
+ OverlapBSD(1);
+ OverlapBSDBefore(1);
+ OverlapBSDSame(1);
+ OverlapBSDAfter(1);
+
+ OverlapBSD(UINT_MAX);
+ OverlapBSDBefore(UINT_MAX);
+ OverlapBSDSame(UINT_MAX);
+ OverlapBSDAfter(UINT_MAX);
+
+ OverlapBSD(UINT_MAX - 10);
+ OverlapBSDBefore(UINT_MAX - 10);
+ OverlapBSDSame(UINT_MAX - 10);
+ OverlapBSDAfter(UINT_MAX - 10);
+ return 1;
+}
+
+
+/** \test Vista Policy
+ */
+static int StreamTcpReassembleTest02(void)
+{
+ OverlapVISTA(0);
+ OverlapVISTABefore(0);
+ OverlapVISTASame(0);
+ OverlapVISTAAfter(0);
+
+ OverlapVISTA(1);
+ OverlapVISTABefore(1);
+ OverlapVISTASame(1);
+ OverlapVISTAAfter(1);
+
+ OverlapVISTA(UINT_MAX);
+ OverlapVISTABefore(UINT_MAX);
+ OverlapVISTASame(UINT_MAX);
+ OverlapVISTAAfter(UINT_MAX);
+
+ OverlapVISTA(UINT_MAX - 10);
+ OverlapVISTABefore(UINT_MAX - 10);
+ OverlapVISTASame(UINT_MAX - 10);
+ OverlapVISTAAfter(UINT_MAX - 10);
+ return 1;
+}
+
+
+/** \test Linux policy
+ */
+static int StreamTcpReassembleTest03(void)
+{
+ OverlapLINUX(0);
+ OverlapLINUXBefore(0);
+ OverlapLINUXSame(0);
+ OverlapLINUXAfter(0);
+
+ OverlapLINUX(1);
+ OverlapLINUXBefore(1);
+ OverlapLINUXSame(1);
+ OverlapLINUXAfter(1);
+
+ OverlapLINUX(UINT_MAX);
+ OverlapLINUXBefore(UINT_MAX);
+ OverlapLINUXSame(UINT_MAX);
+ OverlapLINUXAfter(UINT_MAX);
+
+ OverlapLINUX(UINT_MAX - 10);
+ OverlapLINUXBefore(UINT_MAX - 10);
+ OverlapLINUXSame(UINT_MAX - 10);
+ OverlapLINUXAfter(UINT_MAX - 10);
+ return 1;
+}
+
+/** \test policy Linux old
+ */
+static int StreamTcpReassembleTest04(void)
+{
+ OverlapLINUXOLD(0);
+ OverlapLINUXOLDBefore(0);
+ OverlapLINUXOLDSame(0);
+ OverlapLINUXOLDAfter(0);
+
+ OverlapLINUXOLD(1);
+ OverlapLINUXOLDBefore(1);
+ OverlapLINUXOLDSame(1);
+ OverlapLINUXOLDAfter(1);
+
+ OverlapLINUXOLD(UINT_MAX);
+ OverlapLINUXOLDBefore(UINT_MAX);
+ OverlapLINUXOLDSame(UINT_MAX);
+ OverlapLINUXOLDAfter(UINT_MAX);
+
+ OverlapLINUXOLD(UINT_MAX - 10);
+ OverlapLINUXOLDBefore(UINT_MAX - 10);
+ OverlapLINUXOLDSame(UINT_MAX - 10);
+ OverlapLINUXOLDAfter(UINT_MAX - 10);
+ return 1;
+}
+
+/** \test Solaris policy
+ */
+static int StreamTcpReassembleTest05(void)
+{
+ OverlapSOLARIS(0);
+ OverlapSOLARISBefore(0);
+ OverlapSOLARISSame(0);
+ OverlapSOLARISAfter(0);
+
+ OverlapSOLARIS(1);
+ OverlapSOLARISBefore(1);
+ OverlapSOLARISSame(1);
+ OverlapSOLARISAfter(1);
+
+ OverlapSOLARIS(UINT_MAX);
+ OverlapSOLARISBefore(UINT_MAX);
+ OverlapSOLARISSame(UINT_MAX);
+ OverlapSOLARISAfter(UINT_MAX);
+
+ OverlapSOLARIS(UINT_MAX - 10);
+ OverlapSOLARISBefore(UINT_MAX - 10);
+ OverlapSOLARISSame(UINT_MAX - 10);
+ OverlapSOLARISAfter(UINT_MAX - 10);
+ return 1;
+}
+
+/** \test policy 'last'
+ */
+static int StreamTcpReassembleTest06(void)
+{
+ OverlapLAST(0);
+ OverlapLASTBefore(0);
+ OverlapLASTSame(0);
+ OverlapLASTAfter(0);
+
+ OverlapLAST(1);
+ OverlapLASTBefore(1);
+ OverlapLASTSame(1);
+ OverlapLASTAfter(1);
+
+ OverlapLAST(UINT_MAX);
+ OverlapLASTBefore(UINT_MAX);
+ OverlapLASTSame(UINT_MAX);
+ OverlapLASTAfter(UINT_MAX);
+
+ OverlapLAST(UINT_MAX - 10);
+ OverlapLASTBefore(UINT_MAX - 10);
+ OverlapLASTSame(UINT_MAX - 10);
+ OverlapLASTAfter(UINT_MAX - 10);
+ return 1;
+}
+
+static int StreamTcpReassembleTest30 (void)
+{
+ OVERLAP_START(9, OS_POLICY_BSD);
+ OVERLAP_STEP(3, "BBB", 3, "\0\0BBB", 5);
+ OVERLAP_STEP(1, "AA", 2, "AABBB", 5);
+ OVERLAP_END;
+}
+
+static int StreamTcpReassembleTest31 (void)
+{
+ OVERLAP_START(9, OS_POLICY_BSD);
+ OVERLAP_STEP(1, "AA", 2, "AA", 2);
+ OVERLAP_STEP(3, "BBB", 3, "AABBB", 5);
+ OVERLAP_END;
+}
+
+static int StreamTcpReassembleTest32(void)
+{
+ OVERLAP_START(0, OS_POLICY_BSD);
+ OVERLAP_STEP(11, "AAAAAAAAAA", 10, "\0\0\0\0\0\0\0\0\0\0AAAAAAAAAA", 20);
+ OVERLAP_STEP(21, "BBBBBBBBBB", 10, "\0\0\0\0\0\0\0\0\0\0AAAAAAAAAABBBBBBBBBB", 30);
+ OVERLAP_STEP(41, "CCCCCCCCCC", 10, "\0\0\0\0\0\0\0\0\0\0AAAAAAAAAABBBBBBBBBB\0\0\0\0\0\0\0\0\0\0CCCCCCCCCC", 50);
+ OVERLAP_STEP(6, "aaaaaaaaaaaaaaaaaaaa", 20, "\0\0\0\0\0aaaaaaaaaaaaaaaaaaaaBBBBB\0\0\0\0\0\0\0\0\0\0CCCCCCCCCC", 50);
+ OVERLAP_STEP(1, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 50, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 50);
+ OVERLAP_END;
+}
+
+void StreamTcpListRegisterTests(void)
+{
+ UtRegisterTest("StreamTcpReassembleTest01 -- BSD policy",
+ StreamTcpReassembleTest01);
+ UtRegisterTest("StreamTcpReassembleTest02 -- VISTA policy",
+ StreamTcpReassembleTest02);
+ UtRegisterTest("StreamTcpReassembleTest03 -- LINUX policy",
+ StreamTcpReassembleTest03);
+ UtRegisterTest("StreamTcpReassembleTest04 -- LINUX-OLD policy",
+ StreamTcpReassembleTest04);
+ UtRegisterTest("StreamTcpReassembleTest05 -- SOLARIS policy",
+ StreamTcpReassembleTest05);
+ UtRegisterTest("StreamTcpReassembleTest06 -- LAST policy",
+ StreamTcpReassembleTest06);
+
+ UtRegisterTest("StreamTcpReassembleTest30",
+ StreamTcpReassembleTest30);
+ UtRegisterTest("StreamTcpReassembleTest31",
+ StreamTcpReassembleTest31);
+ UtRegisterTest("StreamTcpReassembleTest32",
+ StreamTcpReassembleTest32);
+
+}
diff --git a/src/tests/stream-tcp-reassemble.c b/src/tests/stream-tcp-reassemble.c
new file mode 100644
index 0000000..5f07f33
--- /dev/null
+++ b/src/tests/stream-tcp-reassemble.c
@@ -0,0 +1,209 @@
+/* Copyright (C) 2007-2021 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.
+ */
+
+#include "../suricata-common.h"
+#include "../stream-tcp-private.h"
+#include "../stream-tcp.h"
+#include "../stream-tcp-reassemble.h"
+#include "../stream-tcp-inline.h"
+#include "../stream-tcp-list.h"
+#include "../stream-tcp-util.h"
+#include "../util-streaming-buffer.h"
+#include "../util-print.h"
+#include "../util-unittest.h"
+
+struct TestReassembleRawCallbackData {
+ const uint8_t *expect_data;
+ const uint32_t expect_data_len;
+};
+
+static int TestReassembleRawCallback(
+ void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t offset)
+{
+ struct TestReassembleRawCallbackData *cb = cb_data;
+
+ SCLogNotice("have %u expect %u", data_len, cb->expect_data_len);
+
+ if (data_len == cb->expect_data_len &&
+ memcmp(data, cb->expect_data, data_len) == 0) {
+ return 1;
+ } else {
+ SCLogNotice("data mismatch. Expected:");
+ PrintRawDataFp(stdout, cb->expect_data, cb->expect_data_len);
+ SCLogNotice("Got:");
+ PrintRawDataFp(stdout, data, data_len);
+ return -1;
+ }
+}
+
+static int TestReassembleRawValidate(TcpSession *ssn, Packet *p,
+ const uint8_t *data, const uint32_t data_len)
+{
+ struct TestReassembleRawCallbackData cb = { data, data_len };
+ uint64_t progress = 0;
+ int r = StreamReassembleRaw(ssn, p, TestReassembleRawCallback, &cb, &progress, false);
+ if (r == 1) {
+ StreamReassembleRawUpdateProgress(ssn, p, progress);
+ }
+ SCLogNotice("r %d", r);
+ return r;
+}
+
+#define RAWREASSEMBLY_START(isn) \
+ TcpReassemblyThreadCtx *ra_ctx = NULL; \
+ TcpSession ssn; \
+ ThreadVars tv; \
+ memset(&tv, 0, sizeof(tv)); \
+ Packet *p = NULL; \
+ \
+ \
+ StreamTcpUTInit(&ra_ctx); \
+ StreamTcpUTInitInline(); \
+ stream_config.reassembly_toserver_chunk_size = 9; \
+ stream_config.reassembly_toclient_chunk_size = 9; \
+ StreamTcpUTSetupSession(&ssn); \
+ StreamTcpUTSetupStream(&ssn.server, (isn)); \
+ StreamTcpUTSetupStream(&ssn.client, (isn)); \
+ ssn.server.last_ack = (isn) + 1; \
+ ssn.client.last_ack = (isn) + 1; \
+ \
+ TcpStream *stream = &ssn.client;
+
+#define RAWREASSEMBLY_END \
+ StreamTcpUTClearSession(&ssn); \
+ StreamTcpUTDeinit(ra_ctx); \
+ PASS
+
+#define RAWREASSEMBLY_STEP(seq, seg, seglen, buf, buflen) \
+ p = PacketGetFromAlloc(); \
+ FAIL_IF_NULL(p); \
+ { \
+ SCLogNotice("SEQ %u block of %u", (seq), (seglen)); \
+ p->flowflags = FLOW_PKT_TOSERVER; \
+ TCPHdr tcphdr; \
+ memset(&tcphdr, 0, sizeof(tcphdr)); \
+ p->tcph = &tcphdr; \
+ p->tcph->th_seq = htonl((seq)); \
+ p->tcph->th_ack = htonl(10); \
+ p->payload_len = (seglen); \
+ \
+ FAIL_IF(StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)) != 0); \
+ p->flags |= PKT_STREAM_ADD; \
+ FAIL_IF(!(TestReassembleRawValidate(&ssn, p, (uint8_t *)(buf), (buflen)))); \
+ }\
+ PacketFree(p);
+
+#define RAWREASSEMBLY_STEP_WITH_PROGRESS(seq, seg, seglen, buf, buflen, lastack, progress) \
+ stream->last_ack = (lastack); \
+ RAWREASSEMBLY_STEP((seq),(seg),(seglen),(buf),(buflen)); \
+ FAIL_IF(STREAM_RAW_PROGRESS(stream) != (progress));
+
+static int StreamTcpReassembleRawTest01 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
+ RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
+ RAWREASSEMBLY_STEP(8, "CCC", 3, "AAABBBCCC", 9);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest02 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
+ RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
+ RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
+ RAWREASSEMBLY_STEP(8, "CCC", 3, "BBBCCCDDD", 9);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest03 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
+ RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
+ RAWREASSEMBLY_STEP(8, "CCC", 3, "CCCDDD", 6);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest04 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
+ RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
+ RAWREASSEMBLY_STEP(7, "BBB", 3, "AAABBBCCC", 9);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest05 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
+ RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
+ RAWREASSEMBLY_STEP(2, "EEEEEEEEEEEEE", 13, "AAAAAEEECCCCC", 13);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest06 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
+ RAWREASSEMBLY_STEP(16,"CCCCC", 5, "CCCCC", 5);
+ RAWREASSEMBLY_STEP(7, "BBBBBBBBB", 9, "ABBBBBBBBBC", 11);
+ RAWREASSEMBLY_STEP(21,"DDDDDDDDDD",10,"CCCDDDDDDDDDD", 13);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest07 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP(2, "AAAAAAA", 7, "AAAAAAA", 7);
+ RAWREASSEMBLY_STEP(9, "BBBBBBB", 7, "AAABBBBBBB", 10);
+ RAWREASSEMBLY_STEP(16,"C", 1, "ABBBBBBBC", 9);
+ RAWREASSEMBLY_STEP(17,"DDDDDDDD",8,"BBCDDDDDDDD", 11);
+ RAWREASSEMBLY_END;
+}
+
+static int StreamTcpReassembleRawTest08 (void)
+{
+ RAWREASSEMBLY_START(1);
+ RAWREASSEMBLY_STEP_WITH_PROGRESS(2, "AAA", 3, "AAA", 3, 3, 3);
+ RAWREASSEMBLY_STEP_WITH_PROGRESS(8, "CCC", 3, "CCC", 3, 3, 3);
+ // segment lost, last_ack updated
+ RAWREASSEMBLY_STEP_WITH_PROGRESS(11, "DDD", 3, "CCCDDD", 6, 8, 12);
+ RAWREASSEMBLY_END;
+}
+
+static void StreamTcpReassembleRawRegisterTests(void)
+{
+ UtRegisterTest("StreamTcpReassembleRawTest01",
+ StreamTcpReassembleRawTest01);
+ UtRegisterTest("StreamTcpReassembleRawTest02",
+ StreamTcpReassembleRawTest02);
+ UtRegisterTest("StreamTcpReassembleRawTest03",
+ StreamTcpReassembleRawTest03);
+ UtRegisterTest("StreamTcpReassembleRawTest04",
+ StreamTcpReassembleRawTest04);
+ UtRegisterTest("StreamTcpReassembleRawTest05",
+ StreamTcpReassembleRawTest05);
+ UtRegisterTest("StreamTcpReassembleRawTest06",
+ StreamTcpReassembleRawTest06);
+ UtRegisterTest("StreamTcpReassembleRawTest07",
+ StreamTcpReassembleRawTest07);
+ UtRegisterTest("StreamTcpReassembleRawTest08",
+ StreamTcpReassembleRawTest08);
+}
diff --git a/src/tests/stream-tcp.c b/src/tests/stream-tcp.c
new file mode 100644
index 0000000..32ccb73
--- /dev/null
+++ b/src/tests/stream-tcp.c
@@ -0,0 +1,3463 @@
+/* Copyright (C) 2007-2021 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.
+ */
+
+#include "../suricata-common.h"
+#include "../stream-tcp-private.h"
+#include "../stream-tcp.h"
+#include "../stream-tcp-reassemble.h"
+#include "../stream-tcp-inline.h"
+#include "../stream-tcp-list.h"
+#include "../stream-tcp-util.h"
+#include "../util-streaming-buffer.h"
+#include "../util-print.h"
+#include "../util-unittest.h"
+
+#define SET_ISN(stream, setseq) \
+ (stream)->isn = (setseq); \
+ (stream)->base_seq = (setseq) + 1
+
+/**
+ * \test Test the allocation of TCP session for a given packet from the
+ * ssn_pool.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest01(void)
+{
+ StreamTcpThread stt;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ memset(&f, 0, sizeof(Flow));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ StreamTcpUTInit(&stt.ra_ctx);
+ TcpSession *ssn = StreamTcpNewSession(NULL, &stt, p, 0);
+ FAIL_IF_NULL(ssn);
+ f.protoctx = ssn;
+ FAIL_IF_NOT_NULL(f.alparser);
+ FAIL_IF_NOT(ssn->state == 0);
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the deallocation of TCP session for a given packet and return
+ * the memory back to ssn_pool and corresponding segments to segment
+ * pool.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest02(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(pq));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+ // StreamTcpUTClearSession(p->flow->protoctx);
+
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the setting up a TCP session when we missed the initial
+ * SYN packet of the session. The session is setup only if midstream
+ * sessions are allowed to setup.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest03(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(pq));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_SYN | TH_ACK;
+ p->tcph = &tcph;
+ int ret = 0;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(19);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 20 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a TCP session when we missed the initial
+ * SYN/ACK packet of the session. The session is setup only if
+ * midstream sessions are allowed to setup.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest04(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(pq));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK;
+ p->tcph = &tcph;
+
+ int ret = 0;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(9);
+ p->tcph->th_ack = htonl(19);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 10 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 20)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a TCP session when we missed the initial
+ * 3WHS packet of the session. The session is setup only if
+ * midstream sessions are allowed to setup.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest05(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(13);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, 4); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(19);
+ p->tcph->th_ack = htonl(16);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, 4); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 16 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a TCP session when we have seen only the
+ * FIN, RST packets packet of the session. The session is setup only if
+ * midstream sessions are allowed to setup.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest06(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ TcpSession ssn;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&ssn, 0, sizeof(TcpSession));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_flags = TH_FIN;
+ p->tcph = &tcph;
+
+ /* StreamTcpPacket returns -1 on unsolicited FIN */
+ if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
+ printf("StreamTcpPacket failed: ");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx)) != NULL) {
+ printf("we have a ssn while we shouldn't: ");
+ goto end;
+ }
+
+ p->tcph->th_flags = TH_RST;
+ /* StreamTcpPacket returns -1 on unsolicited RST */
+ if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
+ printf("StreamTcpPacket failed (2): ");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx)) != NULL) {
+ printf("we have a ssn while we shouldn't (2): ");
+ goto end;
+ }
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the working on PAWS. The packet will be dropped by stream, as
+ * its timestamp is old, although the segment is in the window.
+ */
+
+static int StreamTcpTest07(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[1] = { 0x42 };
+ PacketQueueNoLock pq;
+
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.midstream = true;
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+
+ p->tcpvars.ts_set = true;
+ p->tcpvars.ts_val = 10;
+ p->tcpvars.ts_ecr = 11;
+
+ p->payload = payload;
+ p->payload_len = 1;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ p->tcpvars.ts_val = 2;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) != -1);
+
+ FAIL_IF(((TcpSession *)(p->flow->protoctx))->client.next_seq != 11);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the working on PAWS. The packet will be accepted by engine as
+ * the timestamp is valid and it is in window.
+ */
+
+static int StreamTcpTest08(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[1] = { 0x42 };
+
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.midstream = true;
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+
+ p->tcpvars.ts_set = true;
+ p->tcpvars.ts_val = 10;
+ p->tcpvars.ts_ecr = 11;
+
+ p->payload = payload;
+ p->payload_len = 1;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(20);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ p->tcpvars.ts_val = 12;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ FAIL_IF(((TcpSession *)(p->flow->protoctx))->client.next_seq != 12);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the working of No stream reassembly flag. The stream will not
+ * reassemble the segment if the flag is set.
+ */
+
+static int StreamTcpTest09(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[1] = { 0x42 };
+
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.midstream = true;
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+
+ p->payload = payload;
+ p->payload_len = 1;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(12);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ FAIL_IF(p->flow->protoctx == NULL);
+
+ StreamTcpSetSessionNoReassemblyFlag(((TcpSession *)(p->flow->protoctx)), 0);
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ TcpSession *ssn = p->flow->protoctx;
+ FAIL_IF_NULL(ssn);
+ TcpSegment *seg = RB_MIN(TCPSEG, &ssn->client.seg_tree);
+ FAIL_IF_NULL(seg);
+ FAIL_IF(TCPSEG_RB_NEXT(seg) != NULL);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the setting up a TCP session when we are seeing asynchronous
+ * stream, while we see all the packets in that stream from start.
+ */
+
+static int StreamTcpTest10(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.async_oneside = true;
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = 0;
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ /* spurious retransmission */
+ FAIL_IF_NOT(StreamTcpPacket(&tv, p, &stt, &pq) == 0);
+
+ FAIL_IF(((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED);
+
+ FAIL_IF(!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC));
+
+ FAIL_IF(((TcpSession *)(p->flow->protoctx))->client.last_ack != 6 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the setting up a TCP session when we are seeing asynchronous
+ * stream, while we missed the SYN packet of that stream.
+ */
+
+static int StreamTcpTest11(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.async_oneside = true;
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(1);
+ tcph.th_flags = TH_SYN | TH_ACK;
+ p->tcph = &tcph;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ FAIL_IF(StreamTcpPacket(&tv, p, &stt, &pq) == -1);
+
+ TcpSession *ssn = p->flow->protoctx;
+ FAIL_IF((ssn->flags & STREAMTCP_FLAG_ASYNC) == 0);
+ FAIL_IF(ssn->state != TCP_ESTABLISHED);
+
+ FAIL_IF(ssn->server.last_ack != 11);
+ FAIL_IF(ssn->client.next_seq != 14);
+
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ PASS;
+}
+
+/**
+ * \test Test the setting up a TCP session when we are seeing asynchronous
+ * stream, while we missed the SYN and SYN/ACK packets in that stream.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest12(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(11);
+ tcph.th_flags = TH_ACK;
+ p->tcph = &tcph;
+ int ret = 0;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(10);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.async_oneside) {
+ ret = 1;
+ goto end;
+ }
+
+ if (!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC)) {
+ printf("failed in setting asynchronous session\n");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
+ printf("failed in setting state\n");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->client.last_ack != 6 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 11) {
+ printf("failed in seq %" PRIu32 " match\n",
+ ((TcpSession *)(p->flow->protoctx))->client.last_ack);
+ goto end;
+ }
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a TCP session when we are seeing asynchronous
+ * stream, while we missed the SYN and SYN/ACK packets in that stream.
+ * Later, we start to receive the packet from other end stream too.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest13(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(11);
+ tcph.th_flags = TH_ACK;
+ p->tcph = &tcph;
+ int ret = 0;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(10);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.async_oneside) {
+ ret = 1;
+ goto end;
+ }
+
+ if (!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_ASYNC)) {
+ printf("failed in setting asynchronous session\n");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
+ printf("failed in setting state\n");
+ goto end;
+ }
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(9);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.last_ack != 9 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 14) {
+ printf("failed in seq %" PRIu32 " match\n",
+ ((TcpSession *)(p->flow->protoctx))->client.last_ack);
+ goto end;
+ }
+
+ StreamTcpSessionPktFree(p);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/* Dummy conf string to setup the OS policy for unit testing */
+static const char *dummy_conf_string = "%YAML 1.1\n"
+ "---\n"
+ "\n"
+ "default-log-dir: /var/log/eidps\n"
+ "\n"
+ "logging:\n"
+ "\n"
+ " default-log-level: debug\n"
+ "\n"
+ " default-format: \"<%t> - <%l>\"\n"
+ "\n"
+ " default-startup-message: Your IDS has started.\n"
+ "\n"
+ " default-output-filter:\n"
+ "\n"
+ "host-os-policy:\n"
+ "\n"
+ " windows: 192.168.0.1\n"
+ "\n"
+ " linux: 192.168.0.2\n"
+ "\n";
+/* Dummy conf string to setup the OS policy for unit testing */
+static const char *dummy_conf_string1 = "%YAML 1.1\n"
+ "---\n"
+ "\n"
+ "default-log-dir: /var/log/eidps\n"
+ "\n"
+ "logging:\n"
+ "\n"
+ " default-log-level: debug\n"
+ "\n"
+ " default-format: \"<%t> - <%l>\"\n"
+ "\n"
+ " default-startup-message: Your IDS has started.\n"
+ "\n"
+ " default-output-filter:\n"
+ "\n"
+ "host-os-policy:\n"
+ "\n"
+ " windows: 192.168.0.0/24,"
+ "192.168.1.1\n"
+ "\n"
+ " linux: 192.168.1.0/24,"
+ "192.168.0.1\n"
+ "\n";
+
+/**
+ * \brief Function to parse the dummy conf string and get the value of IP
+ * address for the corresponding OS policy type.
+ *
+ * \param conf_val_name Name of the OS policy type
+ * \retval returns IP address as string on success and NULL on failure
+ */
+static const char *StreamTcpParseOSPolicy(char *conf_var_name)
+{
+ SCEnter();
+ char conf_var_type_name[15] = "host-os-policy";
+ char *conf_var_full_name = NULL;
+ const char *conf_var_value = NULL;
+
+ if (conf_var_name == NULL)
+ goto end;
+
+ /* the + 2 is for the '.' and the string termination character '\0' */
+ conf_var_full_name = (char *)SCMalloc(strlen(conf_var_type_name) + strlen(conf_var_name) + 2);
+ if (conf_var_full_name == NULL)
+ goto end;
+
+ if (snprintf(conf_var_full_name, strlen(conf_var_type_name) + strlen(conf_var_name) + 2,
+ "%s.%s", conf_var_type_name, conf_var_name) < 0) {
+ SCLogError("Error in making the conf full name");
+ goto end;
+ }
+
+ if (ConfGet(conf_var_full_name, &conf_var_value) != 1) {
+ SCLogError("Error in getting conf value for conf name %s", conf_var_full_name);
+ goto end;
+ }
+
+ SCLogDebug("Value obtained from the yaml conf file, for the var "
+ "\"%s\" is \"%s\"",
+ conf_var_name, conf_var_value);
+
+end:
+ if (conf_var_full_name != NULL)
+ SCFree(conf_var_full_name);
+ SCReturnCharPtr(conf_var_value);
+}
+/**
+ * \test Test the setting up a OS policy. Te OS policy values are defined in
+ * the config string "dummy_conf_string"
+ *
+ * \retval On success it returns 1 and on failure 0
+ */
+
+static int StreamTcpTest14(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ struct in_addr addr;
+ IPV4Hdr ipv4h;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&addr, 0, sizeof(addr));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ addr.s_addr = inet_addr("192.168.0.1");
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+ p->dst.family = AF_INET;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ p->ip4h = &ipv4h;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(15);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(14);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ addr.s_addr = inet_addr("192.168.0.2");
+ p->tcph->th_seq = htonl(25);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(24);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
+ printf("failed in next_seq match client.next_seq %" PRIu32 ""
+ " server.next_seq %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.next_seq,
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->client.os_policy != OS_POLICY_WINDOWS &&
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy != OS_POLICY_LINUX) {
+ printf("failed in setting up OS policy, client.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 " and server.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_WINDOWS,
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy, (uint8_t)OS_POLICY_LINUX);
+ goto end;
+ }
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a TCP session using the 4WHS:
+ * SYN, SYN, SYN/ACK, ACK
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcp4WHSTest01(void)
+{
+ int ret = 0;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = 0;
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = 0;
+ p->tcph->th_flags = TH_SYN;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
+ printf("STREAMTCP_FLAG_4WHS flag not set: ");
+ goto end;
+ }
+
+ p->tcph->th_seq = htonl(10);
+ p->tcph->th_ack = htonl(21); /* the SYN/ACK uses the SEQ from the first SYN pkt */
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(21);
+ p->tcph->th_ack = htonl(10);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
+ printf("state is not ESTABLISHED: ");
+ goto end;
+ }
+
+ ret = 1;
+end:
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test set up a TCP session using the 4WHS:
+ * SYN, SYN, SYN/ACK, ACK, but the SYN/ACK does
+ * not have the right SEQ
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcp4WHSTest02(void)
+{
+ int ret = 0;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = 0;
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = 0;
+ p->tcph->th_flags = TH_SYN;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
+ printf("STREAMTCP_FLAG_4WHS flag not set: ");
+ goto end;
+ }
+
+ p->tcph->th_seq = htonl(30);
+ p->tcph->th_ack = htonl(21); /* the SYN/ACK uses the SEQ from the first SYN pkt */
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) != -1) {
+ printf("SYN/ACK pkt not rejected but it should have: ");
+ goto end;
+ }
+
+ ret = 1;
+end:
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test set up a TCP session using the 4WHS:
+ * SYN, SYN, SYN/ACK, ACK: however the SYN/ACK and ACK
+ * are part of a normal 3WHS
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcp4WHSTest03(void)
+{
+ int ret = 0;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = 0;
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = 0;
+ p->tcph->th_flags = TH_SYN;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if ((!(((TcpSession *)(p->flow->protoctx))->flags & STREAMTCP_FLAG_4WHS))) {
+ printf("STREAMTCP_FLAG_4WHS flag not set: ");
+ goto end;
+ }
+
+ p->tcph->th_seq = htonl(30);
+ p->tcph->th_ack = htonl(11);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(11);
+ p->tcph->th_ack = htonl(31);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED) {
+ printf("state is not ESTABLISHED: ");
+ goto end;
+ }
+
+ ret = 1;
+end:
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a OS policy. Te OS policy values are defined in
+ * the config string "dummy_conf_string1"
+ *
+ * \retval On success it returns 1 and on failure 0
+ */
+
+static int StreamTcpTest15(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ struct in_addr addr;
+ IPV4Hdr ipv4h;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&addr, 0, sizeof(addr));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ addr.s_addr = inet_addr("192.168.0.20");
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+ p->dst.family = AF_INET;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ p->ip4h = &ipv4h;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(15);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(14);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ addr.s_addr = inet_addr("192.168.1.20");
+ p->tcph->th_seq = htonl(25);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(24);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
+ printf("failed in next_seq match client.next_seq %" PRIu32 ""
+ " server.next_seq %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.next_seq,
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->client.os_policy != OS_POLICY_WINDOWS &&
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy != OS_POLICY_LINUX) {
+ printf("failed in setting up OS policy, client.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 " and server.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_WINDOWS,
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy, (uint8_t)OS_POLICY_LINUX);
+ goto end;
+ }
+ StreamTcpSessionPktFree(p);
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a OS policy. Te OS policy values are defined in
+ * the config string "dummy_conf_string1"
+ *
+ * \retval On success it returns 1 and on failure 0
+ */
+
+static int StreamTcpTest16(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ struct in_addr addr;
+ IPV4Hdr ipv4h;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&addr, 0, sizeof(addr));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ addr.s_addr = inet_addr("192.168.0.1");
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+ p->dst.family = AF_INET;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ p->ip4h = &ipv4h;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(15);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(14);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ addr.s_addr = inet_addr("192.168.1.1");
+ p->tcph->th_seq = htonl(25);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(24);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
+ printf("failed in next_seq match client.next_seq %" PRIu32 ""
+ " server.next_seq %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.next_seq,
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->client.os_policy != OS_POLICY_LINUX &&
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy != OS_POLICY_WINDOWS) {
+ printf("failed in setting up OS policy, client.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 " and server.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_LINUX,
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy, (uint8_t)OS_POLICY_WINDOWS);
+ goto end;
+ }
+ StreamTcpSessionPktFree(p);
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the setting up a OS policy. Te OS policy values are defined in
+ * the config string "dummy_conf_string1". To check the setting of
+ * Default os policy
+ *
+ * \retval On success it returns 1 and on failure 0
+ */
+
+static int StreamTcpTest17(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ uint8_t payload[4];
+ struct in_addr addr;
+ IPV4Hdr ipv4h;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&addr, 0, sizeof(addr));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name));
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+ addr.s_addr = inet_addr("192.168.0.1");
+ tcph.th_win = htons(5480);
+ tcph.th_seq = htonl(10);
+ tcph.th_ack = htonl(20);
+ tcph.th_flags = TH_ACK | TH_PUSH;
+ p->tcph = &tcph;
+ p->dst.family = AF_INET;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ p->ip4h = &ipv4h;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, sizeof(payload)); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(20);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, sizeof(payload)); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(15);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(14);
+ p->tcph->th_ack = htonl(23);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x43, 3, sizeof(payload)); /*CCC*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ addr.s_addr = inet_addr("10.1.1.1");
+ p->tcph->th_seq = htonl(25);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_seq = htonl(24);
+ p->tcph->th_ack = htonl(13);
+ p->tcph->th_flags = TH_ACK | TH_PUSH;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x44, 3, sizeof(payload)); /*DDD*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ if (!stream_config.midstream) {
+ ret = 1;
+ goto end;
+ }
+ if (((TcpSession *)(p->flow->protoctx))->state != TCP_ESTABLISHED)
+ goto end;
+
+ if (((TcpSession *)(p->flow->protoctx))->client.next_seq != 13 &&
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq != 23) {
+ printf("failed in next_seq match client.next_seq %" PRIu32 ""
+ " server.next_seq %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.next_seq,
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->client.os_policy != OS_POLICY_LINUX &&
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy != OS_POLICY_DEFAULT) {
+ printf("failed in setting up OS policy, client.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 " and server.os_policy: %" PRIu8 ""
+ " should be %" PRIu8 "\n",
+ ((TcpSession *)(p->flow->protoctx))->client.os_policy, (uint8_t)OS_POLICY_LINUX,
+ ((TcpSession *)(p->flow->protoctx))->server.os_policy, (uint8_t)OS_POLICY_DEFAULT);
+ goto end;
+ }
+ StreamTcpSessionPktFree(p);
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test Test the various OS policies based on different IP addresses from
+ configuration defined in 'dummy_conf_string1' */
+static int StreamTcpTest18(void)
+{
+ StreamTcpThread stt;
+ struct in_addr addr;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ TcpStream stream;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ IPV4Hdr ipv4h;
+ int ret = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&stream, 0, sizeof(stream));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ SCHInfoCleanResources();
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+
+ p->dst.family = AF_INET;
+ p->ip4h = &ipv4h;
+ addr.s_addr = inet_addr("192.168.1.1");
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ StreamTcpSetOSPolicy(&stream, p);
+
+ if (stream.os_policy != OS_POLICY_WINDOWS)
+ goto end;
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+/** \test Test the various OS policies based on different IP addresses from
+ configuration defined in 'dummy_conf_string1' */
+static int StreamTcpTest19(void)
+{
+ StreamTcpThread stt;
+ struct in_addr addr;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ TcpStream stream;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ IPV4Hdr ipv4h;
+ int ret = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&stream, 0, sizeof(stream));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ SCHInfoCleanResources();
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+
+ p->dst.family = AF_INET;
+ p->ip4h = &ipv4h;
+ addr.s_addr = inet_addr("192.168.0.30");
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ StreamTcpSetOSPolicy(&stream, p);
+
+ if (stream.os_policy != OS_POLICY_WINDOWS) {
+ printf("expected os_policy: %" PRIu8 " but received %" PRIu8 ": ",
+ (uint8_t)OS_POLICY_WINDOWS, stream.os_policy);
+ goto end;
+ }
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+/** \test Test the various OS policies based on different IP addresses from
+ configuration defined in 'dummy_conf_string1' */
+static int StreamTcpTest20(void)
+{
+ StreamTcpThread stt;
+ struct in_addr addr;
+ char os_policy_name[10] = "linux";
+ const char *ip_addr;
+ TcpStream stream;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ IPV4Hdr ipv4h;
+ int ret = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&stream, 0, sizeof(stream));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ SCHInfoCleanResources();
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+
+ p->dst.family = AF_INET;
+ p->ip4h = &ipv4h;
+ addr.s_addr = inet_addr("192.168.0.1");
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ StreamTcpSetOSPolicy(&stream, p);
+
+ if (stream.os_policy != OS_POLICY_LINUX) {
+ printf("expected os_policy: %" PRIu8 " but received %" PRIu8 "\n", (uint8_t)OS_POLICY_LINUX,
+ stream.os_policy);
+ goto end;
+ }
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+/** \test Test the various OS policies based on different IP addresses from
+ configuration defined in 'dummy_conf_string1' */
+static int StreamTcpTest21(void)
+{
+ StreamTcpThread stt;
+ struct in_addr addr;
+ char os_policy_name[10] = "linux";
+ const char *ip_addr;
+ TcpStream stream;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ IPV4Hdr ipv4h;
+ int ret = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&stream, 0, sizeof(stream));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ SCHInfoCleanResources();
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+
+ p->dst.family = AF_INET;
+ p->ip4h = &ipv4h;
+ addr.s_addr = inet_addr("192.168.1.30");
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ StreamTcpSetOSPolicy(&stream, p);
+
+ if (stream.os_policy != OS_POLICY_LINUX) {
+ printf("expected os_policy: %" PRIu8 " but received %" PRIu8 "\n", (uint8_t)OS_POLICY_LINUX,
+ stream.os_policy);
+ goto end;
+ }
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+/** \test Test the various OS policies based on different IP addresses from
+ configuration defined in 'dummy_conf_string1' */
+static int StreamTcpTest22(void)
+{
+ StreamTcpThread stt;
+ struct in_addr addr;
+ char os_policy_name[10] = "windows";
+ const char *ip_addr;
+ TcpStream stream;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ IPV4Hdr ipv4h;
+ int ret = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&stream, 0, sizeof(stream));
+ memset(&ipv4h, 0, sizeof(ipv4h));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ SCHInfoCleanResources();
+
+ /* Load the config string into parser */
+ ConfCreateContextBackup();
+ ConfInit();
+ ConfYamlLoadString(dummy_conf_string1, strlen(dummy_conf_string1));
+
+ /* Get the IP address as string and add it to Host info tree for lookups */
+ ip_addr = StreamTcpParseOSPolicy(os_policy_name);
+ SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1);
+
+ p->dst.family = AF_INET;
+ p->ip4h = &ipv4h;
+ addr.s_addr = inet_addr("123.231.2.1");
+ p->dst.address.address_un_data32[0] = addr.s_addr;
+ StreamTcpSetOSPolicy(&stream, p);
+
+ if (stream.os_policy != OS_POLICY_DEFAULT) {
+ printf("expected os_policy: %" PRIu8 " but received %" PRIu8 "\n",
+ (uint8_t)OS_POLICY_DEFAULT, stream.os_policy);
+ goto end;
+ }
+
+ ret = 1;
+end:
+ ConfDeInit();
+ ConfRestoreContextBackup();
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test Test the stream mem leaks conditions. */
+static int StreamTcpTest23(void)
+{
+ StreamTcpThread stt;
+ TcpSession ssn;
+ Flow f;
+ TCPHdr tcph;
+ uint8_t packet[1460] = "";
+ ThreadVars tv;
+
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(p == NULL);
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&tv, 0, sizeof(ThreadVars));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ StreamTcpUTSetupSession(&ssn);
+ FLOW_INITIALIZE(&f);
+ ssn.client.os_policy = OS_POLICY_BSD;
+ f.protoctx = &ssn;
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->proto = IPPROTO_TCP;
+ p->flow = &f;
+ tcph.th_win = 5480;
+ tcph.th_flags = TH_PUSH | TH_ACK;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+ p->payload = packet;
+ SET_ISN(&ssn.client, 3184324452UL);
+
+ p->tcph->th_seq = htonl(3184324453UL);
+ p->tcph->th_ack = htonl(3373419609UL);
+ p->payload_len = 2;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ p->tcph->th_seq = htonl(3184324455UL);
+ p->tcph->th_ack = htonl(3373419621UL);
+ p->payload_len = 2;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ p->tcph->th_seq = htonl(3184324453UL);
+ p->tcph->th_ack = htonl(3373419621UL);
+ p->payload_len = 6;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ TcpSegment *seg = RB_MAX(TCPSEG, &ssn.client.seg_tree);
+ FAIL_IF_NULL(seg);
+ FAIL_IF(TCP_SEG_LEN(seg) != 2);
+
+ StreamTcpUTClearSession(&ssn);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ FAIL_IF(SC_ATOMIC_GET(st_memuse) > 0);
+ PASS;
+}
+
+/** \test Test the stream mem leaks conditions. */
+static int StreamTcpTest24(void)
+{
+ StreamTcpThread stt;
+ TcpSession ssn;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF(p == NULL);
+ Flow f;
+ TCPHdr tcph;
+ uint8_t packet[1460] = "";
+ ThreadVars tv;
+ memset(&tv, 0, sizeof(ThreadVars));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ StreamTcpUTSetupSession(&ssn);
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ FLOW_INITIALIZE(&f);
+ ssn.client.os_policy = OS_POLICY_BSD;
+ f.protoctx = &ssn;
+ p->src.family = AF_INET;
+ p->dst.family = AF_INET;
+ p->proto = IPPROTO_TCP;
+ p->flow = &f;
+ tcph.th_win = 5480;
+ tcph.th_flags = TH_PUSH | TH_ACK;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+ p->payload = packet;
+ // ssn.client.ra_app_base_seq = ssn.client.ra_raw_base_seq = ssn.client.last_ack = 3184324453UL;
+ SET_ISN(&ssn.client, 3184324453UL);
+
+ p->tcph->th_seq = htonl(3184324455UL);
+ p->tcph->th_ack = htonl(3373419621UL);
+ p->payload_len = 4;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ p->tcph->th_seq = htonl(3184324459UL);
+ p->tcph->th_ack = htonl(3373419633UL);
+ p->payload_len = 2;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ p->tcph->th_seq = htonl(3184324459UL);
+ p->tcph->th_ack = htonl(3373419657UL);
+ p->payload_len = 4;
+
+ FAIL_IF(StreamTcpReassembleHandleSegment(&tv, stt.ra_ctx, &ssn, &ssn.client, p) == -1);
+
+ TcpSegment *seg = RB_MAX(TCPSEG, &ssn.client.seg_tree);
+ FAIL_IF_NULL(seg);
+ FAIL_IF(TCP_SEG_LEN(seg) != 4);
+
+ StreamTcpUTClearSession(&ssn);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ FAIL_IF(SC_ATOMIC_GET(st_memuse) > 0);
+ PASS;
+}
+
+/**
+ * \test Test the initialization of tcp streams with congestion flags
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+static int StreamTcpTest25(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ int ret = 0;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN | TH_CWR;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the initialization of tcp streams with congestion flags
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+static int StreamTcpTest26(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ int ret = 0;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN | TH_ECN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the initialization of tcp streams with congestion flags
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+static int StreamTcpTest27(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ int ret = 0;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN | TH_CWR | TH_ECN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(6);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x42, 3, 4); /*BBB*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ p->flowflags = FLOW_PKT_TOCLIENT;
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL)
+ goto end;
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test Test the memcap incrementing/decrementing and memcap check */
+static int StreamTcpTest28(void)
+{
+ StreamTcpThread stt;
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ uint32_t memuse = SC_ATOMIC_GET(st_memuse);
+
+ StreamTcpIncrMemuse(500);
+ FAIL_IF(SC_ATOMIC_GET(st_memuse) != (memuse + 500));
+
+ StreamTcpDecrMemuse(500);
+ FAIL_IF(SC_ATOMIC_GET(st_memuse) != memuse);
+
+ FAIL_IF(StreamTcpCheckMemcap(500) != 1);
+
+ FAIL_IF(StreamTcpCheckMemcap((memuse + SC_ATOMIC_GET(stream_config.memcap))) != 0);
+
+ StreamTcpUTDeinit(stt.ra_ctx);
+
+ FAIL_IF(SC_ATOMIC_GET(st_memuse) != 0);
+ PASS;
+}
+
+/**
+ * \test Test the processing of out of order FIN packets in tcp session.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+static int StreamTcpTest37(void)
+{
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ int ret = 0;
+ PacketQueueNoLock pq;
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ FLOW_INITIALIZE(&f);
+
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ if (((TcpSession *)p->flow->protoctx)->state != TCP_ESTABLISHED) {
+ printf("the TCP state should be TCP_ESTABLISHED\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(2);
+ p->tcph->th_seq = htonl(4);
+ p->tcph->th_flags = TH_ACK | TH_FIN;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ if (((TcpSession *)p->flow->protoctx)->state != TCP_CLOSE_WAIT) {
+ printf("the TCP state should be TCP_CLOSE_WAIT\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(4);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_ACK;
+ p->payload_len = 0;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1 || (TcpSession *)p->flow->protoctx == NULL) {
+ printf("failed in processing packet\n");
+ goto end;
+ }
+
+ TcpStream *stream = &(((TcpSession *)p->flow->protoctx)->client);
+ FAIL_IF(STREAM_RAW_PROGRESS(stream) != 0); // no detect no progress update
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the validation of the ACK number before setting up the
+ * stream.last_ack.
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest38(void)
+{
+ int ret = 0;
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[128];
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(29847);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ /* last_ack value should be 1 as the previous sent ACK value is out of
+ window */
+ if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 1) {
+ printf("the server.last_ack should be 1, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.last_ack);
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 127, 128); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 127;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 128) {
+ printf("the server.next_seq should be 128, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(256); // in window, but beyond next_seq
+ p->tcph->th_seq = htonl(5);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ /* last_ack value should be 256, as the previous sent ACK value
+ is inside window */
+ if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 256) {
+ printf("the server.last_ack should be 1, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.last_ack);
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(128);
+ p->tcph->th_seq = htonl(8);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ /* last_ack value should be 256 as the previous sent ACK value is inside
+ window */
+ if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 256) {
+ printf("the server.last_ack should be 256, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.last_ack);
+ goto end;
+ }
+
+ ret = 1;
+
+end:
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/**
+ * \test Test the validation of the ACK number before setting up the
+ * stream.last_ack and update the next_seq after loosing the .
+ *
+ * \retval On success it returns 1 and on failure 0.
+ */
+
+static int StreamTcpTest39(void)
+{
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ uint8_t payload[4];
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+
+ FLOW_INITIALIZE(&f);
+ p->flow = &f;
+ tcph.th_win = htons(5480);
+ tcph.th_flags = TH_SYN;
+ p->tcph = &tcph;
+ p->flowflags = FLOW_PKT_TOSERVER;
+ int ret = 0;
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(1);
+ p->tcph->th_seq = htonl(1);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 4) {
+ printf("the server.next_seq should be 4, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ p->tcph->th_ack = htonl(4);
+ p->tcph->th_seq = htonl(2);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ /* last_ack value should be 4 as the previous sent ACK value is inside
+ window */
+ if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 4) {
+ printf("the server.last_ack should be 4, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.last_ack);
+ goto end;
+ }
+
+ p->tcph->th_seq = htonl(4);
+ p->tcph->th_ack = htonl(5);
+ p->tcph->th_flags = TH_PUSH | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
+ p->payload = payload;
+ p->payload_len = 3;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
+ printf("failed in processing packet in StreamTcpPacket\n");
+ goto end;
+ }
+
+ /* next_seq value should be 2987 as the previous sent ACK value is inside
+ window */
+ if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 7) {
+ printf("the server.next_seq should be 7, but it is %" PRIu32 "\n",
+ ((TcpSession *)(p->flow->protoctx))->server.next_seq);
+ goto end;
+ }
+
+ ret = 1;
+
+end:
+ StreamTcpSessionClear(p->flow->protoctx);
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test multiple different SYN/ACK, pick first */
+static int StreamTcpTest42(void)
+{
+ int ret = 0;
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ TcpSession *ssn;
+
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ FLOW_INITIALIZE(&f);
+ p->tcph = &tcph;
+ tcph.th_win = htons(5480);
+ p->flow = &f;
+
+ /* SYN pkt */
+ tcph.th_flags = TH_SYN;
+ tcph.th_seq = htonl(100);
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(500);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(1000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* ACK */
+ p->tcph->th_ack = htonl(501);
+ p->tcph->th_seq = htonl(101);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ ssn = p->flow->protoctx;
+
+ if (ssn->state != TCP_ESTABLISHED) {
+ printf("state not TCP_ESTABLISHED: ");
+ goto end;
+ }
+
+ if (ssn->server.isn != 500) {
+ SCLogDebug("ssn->server.isn %" PRIu32 " != %" PRIu32 "", ssn->server.isn, 500);
+ goto end;
+ }
+ if (ssn->client.isn != 100) {
+ SCLogDebug("ssn->client.isn %" PRIu32 " != %" PRIu32 "", ssn->client.isn, 100);
+ goto end;
+ }
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test multiple different SYN/ACK, pick second */
+static int StreamTcpTest43(void)
+{
+ int ret = 0;
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ TcpSession *ssn;
+
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ FLOW_INITIALIZE(&f);
+ p->tcph = &tcph;
+ tcph.th_win = htons(5480);
+ p->flow = &f;
+
+ /* SYN pkt */
+ tcph.th_flags = TH_SYN;
+ tcph.th_seq = htonl(100);
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(500);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(1000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* ACK */
+ p->tcph->th_ack = htonl(1001);
+ p->tcph->th_seq = htonl(101);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ ssn = p->flow->protoctx;
+
+ if (ssn->state != TCP_ESTABLISHED) {
+ printf("state not TCP_ESTABLISHED: ");
+ goto end;
+ }
+
+ if (ssn->server.isn != 1000) {
+ SCLogDebug("ssn->server.isn %" PRIu32 " != %" PRIu32 "", ssn->server.isn, 1000);
+ goto end;
+ }
+ if (ssn->client.isn != 100) {
+ SCLogDebug("ssn->client.isn %" PRIu32 " != %" PRIu32 "", ssn->client.isn, 100);
+ goto end;
+ }
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test multiple different SYN/ACK, pick neither */
+static int StreamTcpTest44(void)
+{
+ int ret = 0;
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ TcpSession *ssn;
+
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+
+ FLOW_INITIALIZE(&f);
+ p->tcph = &tcph;
+ tcph.th_win = htons(5480);
+ p->flow = &f;
+
+ /* SYN pkt */
+ tcph.th_flags = TH_SYN;
+ tcph.th_seq = htonl(100);
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(500);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(1000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* ACK */
+ p->tcph->th_ack = htonl(3001);
+ p->tcph->th_seq = htonl(101);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) != -1)
+ goto end;
+
+ ssn = p->flow->protoctx;
+
+ if (ssn->state != TCP_SYN_RECV) {
+ SCLogDebug("state not TCP_SYN_RECV");
+ goto end;
+ }
+
+ if (ssn->client.isn != 100) {
+ SCLogDebug("ssn->client.isn %" PRIu32 " != %" PRIu32 "", ssn->client.isn, 100);
+ goto end;
+ }
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ FLOW_DESTROY(&f);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+/** \test multiple different SYN/ACK, over the limit */
+static int StreamTcpTest45(void)
+{
+ int ret = 0;
+ Flow f;
+ ThreadVars tv;
+ StreamTcpThread stt;
+ TCPHdr tcph;
+ PacketQueueNoLock pq;
+ Packet *p = PacketGetFromAlloc();
+ FAIL_IF_NULL(p);
+ TcpSession *ssn;
+
+ memset(&pq, 0, sizeof(PacketQueueNoLock));
+ memset(&f, 0, sizeof(Flow));
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&stt, 0, sizeof(StreamTcpThread));
+ memset(&tcph, 0, sizeof(TCPHdr));
+
+ StreamTcpUTInit(&stt.ra_ctx);
+ stream_config.max_synack_queued = 2;
+
+ FLOW_INITIALIZE(&f);
+ p->tcph = &tcph;
+ tcph.th_win = htons(5480);
+ p->flow = &f;
+
+ /* SYN pkt */
+ tcph.th_flags = TH_SYN;
+ tcph.th_seq = htonl(100);
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(500);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(1000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(2000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ /* SYN/ACK */
+ p->tcph->th_seq = htonl(3000);
+ p->tcph->th_ack = htonl(101);
+ p->tcph->th_flags = TH_SYN | TH_ACK;
+ p->flowflags = FLOW_PKT_TOCLIENT;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) != -1)
+ goto end;
+
+ /* ACK */
+ p->tcph->th_ack = htonl(1001);
+ p->tcph->th_seq = htonl(101);
+ p->tcph->th_flags = TH_ACK;
+ p->flowflags = FLOW_PKT_TOSERVER;
+
+ if (StreamTcpPacket(&tv, p, &stt, &pq) == -1)
+ goto end;
+
+ ssn = p->flow->protoctx;
+
+ if (ssn->state != TCP_ESTABLISHED) {
+ printf("state not TCP_ESTABLISHED: ");
+ goto end;
+ }
+
+ if (ssn->server.isn != 1000) {
+ SCLogDebug("ssn->server.isn %" PRIu32 " != %" PRIu32 "", ssn->server.isn, 1000);
+ goto end;
+ }
+ if (ssn->client.isn != 100) {
+ SCLogDebug("ssn->client.isn %" PRIu32 " != %" PRIu32 "", ssn->client.isn, 100);
+ goto end;
+ }
+
+ StreamTcpSessionClear(p->flow->protoctx);
+
+ ret = 1;
+end:
+ SCFree(p);
+ StreamTcpUTDeinit(stt.ra_ctx);
+ return ret;
+}
+
+void StreamTcpRegisterTests(void)
+{
+ UtRegisterTest("StreamTcpTest01 -- TCP session allocation", StreamTcpTest01);
+ UtRegisterTest("StreamTcpTest02 -- TCP session deallocation", StreamTcpTest02);
+ UtRegisterTest("StreamTcpTest03 -- SYN missed MidStream session", StreamTcpTest03);
+ UtRegisterTest("StreamTcpTest04 -- SYN/ACK missed MidStream session", StreamTcpTest04);
+ UtRegisterTest("StreamTcpTest05 -- 3WHS missed MidStream session", StreamTcpTest05);
+ UtRegisterTest("StreamTcpTest06 -- FIN, RST message MidStream session", StreamTcpTest06);
+ UtRegisterTest("StreamTcpTest07 -- PAWS invalid timestamp", StreamTcpTest07);
+ UtRegisterTest("StreamTcpTest08 -- PAWS valid timestamp", StreamTcpTest08);
+ UtRegisterTest("StreamTcpTest09 -- No Client Reassembly", StreamTcpTest09);
+ UtRegisterTest("StreamTcpTest10 -- No missed packet Async stream", StreamTcpTest10);
+ UtRegisterTest("StreamTcpTest11 -- SYN missed Async stream", StreamTcpTest11);
+ UtRegisterTest("StreamTcpTest12 -- SYN/ACK missed Async stream", StreamTcpTest12);
+ UtRegisterTest("StreamTcpTest13 -- opposite stream packets for Async "
+ "stream",
+ StreamTcpTest13);
+ UtRegisterTest("StreamTcp4WHSTest01", StreamTcp4WHSTest01);
+ UtRegisterTest("StreamTcp4WHSTest02", StreamTcp4WHSTest02);
+ UtRegisterTest("StreamTcp4WHSTest03", StreamTcp4WHSTest03);
+ UtRegisterTest("StreamTcpTest14 -- setup OS policy", StreamTcpTest14);
+ UtRegisterTest("StreamTcpTest15 -- setup OS policy", StreamTcpTest15);
+ UtRegisterTest("StreamTcpTest16 -- setup OS policy", StreamTcpTest16);
+ UtRegisterTest("StreamTcpTest17 -- setup OS policy", StreamTcpTest17);
+ UtRegisterTest("StreamTcpTest18 -- setup OS policy", StreamTcpTest18);
+ UtRegisterTest("StreamTcpTest19 -- setup OS policy", StreamTcpTest19);
+ UtRegisterTest("StreamTcpTest20 -- setup OS policy", StreamTcpTest20);
+ UtRegisterTest("StreamTcpTest21 -- setup OS policy", StreamTcpTest21);
+ UtRegisterTest("StreamTcpTest22 -- setup OS policy", StreamTcpTest22);
+ UtRegisterTest("StreamTcpTest23 -- stream memory leaks", StreamTcpTest23);
+ UtRegisterTest("StreamTcpTest24 -- stream memory leaks", StreamTcpTest24);
+ UtRegisterTest("StreamTcpTest25 -- test ecn/cwr sessions", StreamTcpTest25);
+ UtRegisterTest("StreamTcpTest26 -- test ecn/cwr sessions", StreamTcpTest26);
+ UtRegisterTest("StreamTcpTest27 -- test ecn/cwr sessions", StreamTcpTest27);
+ UtRegisterTest("StreamTcpTest28 -- Memcap Test", StreamTcpTest28);
+
+#if 0 /* VJ 2010/09/01 disabled since they blow up on Fedora and Fedora is \
+ * right about blowing up. The checksum functions are not used properly \
+ * in the tests. */
+ UtRegisterTest("StreamTcpTest29 -- Badchecksum Reset Test", StreamTcpTest29, 1);
+ UtRegisterTest("StreamTcpTest30 -- Badchecksum Overlap Test", StreamTcpTest30, 1);
+ UtRegisterTest("StreamTcpTest31 -- MultipleSyns Test", StreamTcpTest31, 1);
+ UtRegisterTest("StreamTcpTest32 -- Bogus CWR Test", StreamTcpTest32, 1);
+ UtRegisterTest("StreamTcpTest33 -- RST-SYN Again Test", StreamTcpTest33, 1);
+ UtRegisterTest("StreamTcpTest34 -- SYN-PUSH Test", StreamTcpTest34, 1);
+ UtRegisterTest("StreamTcpTest35 -- SYN-URG Test", StreamTcpTest35, 1);
+ UtRegisterTest("StreamTcpTest36 -- PUSH-URG Test", StreamTcpTest36, 1);
+#endif
+ UtRegisterTest("StreamTcpTest37 -- Out of order FIN Test", StreamTcpTest37);
+
+ UtRegisterTest("StreamTcpTest38 -- validate ACK", StreamTcpTest38);
+ UtRegisterTest("StreamTcpTest39 -- update next_seq", StreamTcpTest39);
+
+ UtRegisterTest("StreamTcpTest42 -- SYN/ACK queue", StreamTcpTest42);
+ UtRegisterTest("StreamTcpTest43 -- SYN/ACK queue", StreamTcpTest43);
+ UtRegisterTest("StreamTcpTest44 -- SYN/ACK queue", StreamTcpTest44);
+ UtRegisterTest("StreamTcpTest45 -- SYN/ACK queue", StreamTcpTest45);
+
+ /* set up the reassembly tests as well */
+ StreamTcpReassembleRegisterTests();
+
+ StreamTcpSackRegisterTests();
+}