From d511b3889e0d5f4b27492f8feee34070b9d97d73 Mon Sep 17 00:00:00 2001 From: Jeff Lucovsky Date: Wed, 13 Jan 2021 13:43:52 -0500 Subject: [PATCH] lua/test: Test cases using SC prefix This commit adds paired test cases to ensure that the SC variant of the entry points are tested. (cherry picked from commit 1c68f4aed66dceed79ce04d0f9cd14ca2fe72589) --- src/detect-lua.c | 1192 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 1035 insertions(+), 157 deletions(-) diff --git a/src/detect-lua.c b/src/detect-lua.c index 337dcefd90..2bed7cf277 100644 --- a/src/detect-lua.c +++ b/src/detect-lua.c @@ -1319,38 +1319,880 @@ end: return result; } +static int LuaMatchTest01a(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowvar\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " a = SCFlowvarGet(0)\n" + " if a then\n" + " a = tostring(tonumber(a)+1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " else\n" + " a = tostring(1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " end\n" + " \n" + " print (\"pre check: \" .. (a))\n" + " if tonumber(a) == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + ut_script = script; + + 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; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + FLOWLOCK_WRLOCK(&f); + int r = AppLayerParserParse( + NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + HtpState *http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect for p1 */ + SCLogDebug("inspecting p1"); + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match on p1 but should have: "); + goto end; + } + + FLOWLOCK_WRLOCK(&f); + r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + /* do detect for p2 */ + SCLogDebug("inspecting p2"); + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_str.value_len != 1) { + printf("%u != %u: ", fv->data.fv_str.value_len, 1); + goto end; + } + + if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { + PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); + + printf("buffer mismatch: "); + 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 payload buffer */ static int LuaMatchTest02(void) { - const char script[] = - "function init (args)\n" - " local needs = {}\n" - " needs[\"payload\"] = tostring(true)\n" - " needs[\"flowvar\"] = {\"cnt\"}\n" - " return needs\n" - "end\n" - "\n" - "function match(args)\n" - " a = ScFlowvarGet(0)\n" - " if a then\n" - " a = tostring(tonumber(a)+1)\n" - " print (a)\n" - " ScFlowvarSet(0, a, #a)\n" - " else\n" - " a = tostring(1)\n" - " print (a)\n" - " ScFlowvarSet(0, a, #a)\n" - " end\n" - " \n" - " print (\"pre check: \" .. (a))\n" - " if tonumber(a) == 2 then\n" - " print \"match\"\n" - " return 1\n" - " end\n" - " return 0\n" - "end\n" - "return 0\n"; - char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"payload\"] = tostring(true)\n" + " needs[\"flowvar\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " a = ScFlowvarGet(0)\n" + " if a then\n" + " a = tostring(tonumber(a)+1)\n" + " print (a)\n" + " ScFlowvarSet(0, a, #a)\n" + " else\n" + " a = tostring(1)\n" + " print (a)\n" + " ScFlowvarSet(0, a, #a)\n" + " end\n" + " \n" + " print (\"pre check: \" .. (a))\n" + " if tonumber(a) == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + ut_script = script; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); + p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.proto = IPPROTO_TCP; + f.flags |= FLOW_IPV4; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* do detect for p1 */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match on p1 but should have: "); + goto end; + } + + /* do detect for p2 */ + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_str.value_len != 1) { + printf("%u != %u: ", fv->data.fv_str.value_len, 1); + goto end; + } + + if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { + PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); + + printf("buffer mismatch: "); + 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; +} + +/** \test payload buffer */ +static int LuaMatchTest02a(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"payload\"] = tostring(true)\n" + " needs[\"flowvar\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " a = SCFlowvarGet(0)\n" + " if a then\n" + " a = tostring(tonumber(a)+1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " else\n" + " a = tostring(1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " end\n" + " \n" + " print (\"pre check: \" .. (a))\n" + " if tonumber(a) == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + ut_script = script; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); + p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.proto = IPPROTO_TCP; + f.flags |= FLOW_IPV4; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* do detect for p1 */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match on p1 but should have: "); + goto end; + } + + /* do detect for p2 */ + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_str.value_len != 1) { + printf("%u != %u: ", fv->data.fv_str.value_len, 1); + goto end; + } + + if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { + PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); + + printf("buffer mismatch: "); + 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; +} + +/** \test packet buffer */ +static int LuaMatchTest03(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"packet\"] = tostring(true)\n" + " needs[\"flowvar\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " a = ScFlowvarGet(0)\n" + " if a then\n" + " a = tostring(tonumber(a)+1)\n" + " print (a)\n" + " ScFlowvarSet(0, a, #a)\n" + " else\n" + " a = tostring(1)\n" + " print (a)\n" + " ScFlowvarSet(0, a, #a)\n" + " end\n" + " \n" + " print (\"pre check: \" .. (a))\n" + " if tonumber(a) == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + ut_script = script; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); + p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.proto = IPPROTO_TCP; + f.flags |= FLOW_IPV4; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* do detect for p1 */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match on p1 but should have: "); + goto end; + } + + /* do detect for p2 */ + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_str.value_len != 1) { + printf("%u != %u: ", fv->data.fv_str.value_len, 1); + goto end; + } + + if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { + PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); + + printf("buffer mismatch: "); + 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; +} + +/** \test packet buffer */ +static int LuaMatchTest03a(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"packet\"] = tostring(true)\n" + " needs[\"flowvar\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " a = SCFlowvarGet(0)\n" + " if a then\n" + " a = tostring(tonumber(a)+1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " else\n" + " a = tostring(1)\n" + " print (a)\n" + " SCFlowvarSet(0, a, #a)\n" + " end\n" + " \n" + " print (\"pre check: \" .. (a))\n" + " if tonumber(a) == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + ut_script = script; + + memset(&th_v, 0, sizeof(th_v)); + memset(&f, 0, sizeof(f)); + memset(&ssn, 0, sizeof(ssn)); + + p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); + p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.proto = IPPROTO_TCP; + f.flags |= FLOW_IPV4; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + /* do detect for p1 */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if ((PacketAlertCheck(p1, 1))) { + printf("sid 1 didn't match on p1 but should have: "); + goto end; + } + + /* do detect for p2 */ + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_str.value_len != 1) { + printf("%u != %u: ", fv->data.fv_str.value_len, 1); + goto end; + } + + if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { + PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); + + printf("buffer mismatch: "); + 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; +} + +/** \test http buffer, flowints */ +static int LuaMatchTest04(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = ScFlowintGet(0)\n" + " if a then\n" + " ScFlowintSet(0, a + 1)\n" + " else\n" + " ScFlowintSet(0, 1)\n" + " end\n" + " \n" + " a = ScFlowintGet(0)\n" + " if a == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + int result = 0; + uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" + "Host: www.emergingthreats.net\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n" + "Host: www.openinfosecfoundation.org\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + TcpSession ssn; + Packet *p1 = NULL; + Packet *p2 = NULL; + Flow f; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + + ut_script = script; + + 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; + f.alproto = ALPROTO_HTTP; + + 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; + + StreamTcpInitConfig(TRUE); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->flags |= DE_QUIET; + + s = DetectEngineAppendSig(de_ctx, sig); + if (s == NULL) { + printf("sig parse failed: "); + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + FLOWLOCK_WRLOCK(&f); + int r = AppLayerParserParse( + NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + HtpState *http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect for p1 */ + SCLogInfo("p1"); + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched on p1 but should not have: "); + goto end; + } + + FLOWLOCK_WRLOCK(&f); + r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + /* do detect for p2 */ + SCLogInfo("p2"); + 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; + } + + FlowVar *fv = FlowVarGet(&f, 1); + if (fv == NULL) { + printf("no flowvar: "); + goto end; + } + + if (fv->data.fv_int.value != 2) { + printf("%u != %u: ", fv->data.fv_int.value, 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(&p1, 1); + UTHFreePackets(&p2, 1); + return result; +} + +/** \test http buffer, flowints */ +static int LuaMatchTest04a(void) +{ + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = SCFlowintGet(0)\n" + " if a then\n" + " SCFlowintSet(0, a + 1)\n" + " else\n" + " SCFlowintSet(0, 1)\n" + " end\n" + " \n" + " a = SCFlowintGet(0)\n" + " if a == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; int result = 0; uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" @@ -1368,14 +2210,16 @@ static int LuaMatchTest02(void) ThreadVars th_v; DetectEngineThreadCtx *det_ctx; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + ut_script = script; memset(&th_v, 0, sizeof(th_v)); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); - p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); - p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -1387,6 +2231,7 @@ static int LuaMatchTest02(void) 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; @@ -1409,15 +2254,40 @@ static int LuaMatchTest02(void) SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + FLOWLOCK_WRLOCK(&f); + int r = AppLayerParserParse( + NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + HtpState *http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + /* do detect for p1 */ + SCLogInfo("p1"); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); - if ((PacketAlertCheck(p1, 1))) { - printf("sid 1 didn't match on p1 but should have: "); + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched on p1 but should not have: "); goto end; } + FLOWLOCK_WRLOCK(&f); + r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); /* do detect for p2 */ + SCLogInfo("p2"); SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); if (!(PacketAlertCheck(p2, 1))) { @@ -1431,20 +2301,15 @@ static int LuaMatchTest02(void) goto end; } - if (fv->data.fv_str.value_len != 1) { - printf("%u != %u: ", fv->data.fv_str.value_len, 1); - goto end; - } - - if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { - PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); - - printf("buffer mismatch: "); + if (fv->data.fv_int.value != 2) { + printf("%u != %u: ", fv->data.fv_int.value, 2); goto end; } result = 1; end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); @@ -1455,38 +2320,27 @@ end: return result; } -/** \test packet buffer */ -static int LuaMatchTest03(void) +/** \test http buffer, flowints */ +static int LuaMatchTest05(void) { - const char script[] = - "function init (args)\n" - " local needs = {}\n" - " needs[\"packet\"] = tostring(true)\n" - " needs[\"flowvar\"] = {\"cnt\"}\n" - " return needs\n" - "end\n" - "\n" - "function match(args)\n" - " a = ScFlowvarGet(0)\n" - " if a then\n" - " a = tostring(tonumber(a)+1)\n" - " print (a)\n" - " ScFlowvarSet(0, a, #a)\n" - " else\n" - " a = tostring(1)\n" - " print (a)\n" - " ScFlowvarSet(0, a, #a)\n" - " end\n" - " \n" - " print (\"pre check: \" .. (a))\n" - " if tonumber(a) == 2 then\n" - " print \"match\"\n" - " return 1\n" - " end\n" - " return 0\n" - "end\n" - "return 0\n"; - char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)"; + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = ScFlowintIncr(0)\n" + " if a == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; + char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; int result = 0; uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n" @@ -1504,14 +2358,16 @@ static int LuaMatchTest03(void) ThreadVars th_v; DetectEngineThreadCtx *det_ctx; + AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); + ut_script = script; memset(&th_v, 0, sizeof(th_v)); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); - p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP); - p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP); + p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); + p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; @@ -1523,6 +2379,7 @@ static int LuaMatchTest03(void) 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; @@ -1545,15 +2402,40 @@ static int LuaMatchTest03(void) SigGroupBuild(de_ctx); DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + FLOWLOCK_WRLOCK(&f); + int r = AppLayerParserParse( + NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); + HtpState *http_state = f.alstate; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + /* do detect for p1 */ + SCLogInfo("p1"); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); - if ((PacketAlertCheck(p1, 1))) { - printf("sid 1 didn't match on p1 but should have: "); + if (PacketAlertCheck(p1, 1)) { + printf("sid 1 matched on p1 but should not have: "); goto end; } + FLOWLOCK_WRLOCK(&f); + r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2); + if (r != 0) { + printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); + FLOWLOCK_UNLOCK(&f); + goto end; + } + FLOWLOCK_UNLOCK(&f); /* do detect for p2 */ + SCLogInfo("p2"); SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); if (!(PacketAlertCheck(p2, 1))) { @@ -1567,20 +2449,15 @@ static int LuaMatchTest03(void) goto end; } - if (fv->data.fv_str.value_len != 1) { - printf("%u != %u: ", fv->data.fv_str.value_len, 1); - goto end; - } - - if (memcmp(fv->data.fv_str.value, "2", 1) != 0) { - PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len); - - printf("buffer mismatch: "); + if (fv->data.fv_int.value != 2) { + printf("%u != %u: ", fv->data.fv_int.value, 2); goto end; } result = 1; end: + if (alp_tctx != NULL) + AppLayerParserThreadCtxFree(alp_tctx); if (de_ctx != NULL) DetectEngineCtxFree(de_ctx); @@ -1592,33 +2469,25 @@ end: } /** \test http buffer, flowints */ -static int LuaMatchTest04(void) +static int LuaMatchTest05a(void) { - const char script[] = - "function init (args)\n" - " local needs = {}\n" - " needs[\"http.request_headers\"] = tostring(true)\n" - " needs[\"flowint\"] = {\"cnt\"}\n" - " return needs\n" - "end\n" - "\n" - "function match(args)\n" - " print \"inspecting\"" - " a = ScFlowintGet(0)\n" - " if a then\n" - " ScFlowintSet(0, a + 1)\n" - " else\n" - " ScFlowintSet(0, 1)\n" - " end\n" - " \n" - " a = ScFlowintGet(0)\n" - " if a == 2 then\n" - " print \"match\"\n" - " return 1\n" - " end\n" - " return 0\n" - "end\n" - "return 0\n"; + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = SCFlowintIncr(0)\n" + " if a == 2 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; int result = 0; uint8_t httpbuf1[] = @@ -1749,26 +2618,30 @@ end: } /** \test http buffer, flowints */ -static int LuaMatchTest05(void) +static int LuaMatchTest06(void) { - const char script[] = - "function init (args)\n" - " local needs = {}\n" - " needs[\"http.request_headers\"] = tostring(true)\n" - " needs[\"flowint\"] = {\"cnt\"}\n" - " return needs\n" - "end\n" - "\n" - "function match(args)\n" - " print \"inspecting\"" - " a = ScFlowintIncr(0)\n" - " if a == 2 then\n" - " print \"match\"\n" - " return 1\n" - " end\n" - " return 0\n" - "end\n" - "return 0\n"; + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = ScFlowintGet(0)\n" + " if a == nil then\n" + " print \"new var set to 2\"" + " ScFlowintSet(0, 2)\n" + " end\n" + " a = ScFlowintDecr(0)\n" + " if a == 0 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; int result = 0; uint8_t httpbuf1[] = @@ -1879,8 +2752,8 @@ static int LuaMatchTest05(void) goto end; } - if (fv->data.fv_int.value != 2) { - printf("%u != %u: ", fv->data.fv_int.value, 2); + if (fv->data.fv_int.value != 0) { + printf("%u != %u: ", fv->data.fv_int.value, 0); goto end; } @@ -1899,31 +2772,30 @@ end: } /** \test http buffer, flowints */ -static int LuaMatchTest06(void) +static int LuaMatchTest06a(void) { - const char script[] = - "function init (args)\n" - " local needs = {}\n" - " needs[\"http.request_headers\"] = tostring(true)\n" - " needs[\"flowint\"] = {\"cnt\"}\n" - " return needs\n" - "end\n" - "\n" - "function match(args)\n" - " print \"inspecting\"" - " a = ScFlowintGet(0)\n" - " if a == nil then\n" - " print \"new var set to 2\"" - " ScFlowintSet(0, 2)\n" - " end\n" - " a = ScFlowintDecr(0)\n" - " if a == 0 then\n" - " print \"match\"\n" - " return 1\n" - " end\n" - " return 0\n" - "end\n" - "return 0\n"; + const char script[] = "function init (args)\n" + " local needs = {}\n" + " needs[\"http.request_headers\"] = tostring(true)\n" + " needs[\"flowint\"] = {\"cnt\"}\n" + " return needs\n" + "end\n" + "\n" + "function match(args)\n" + " print \"inspecting\"" + " a = SCFlowintGet(0)\n" + " if a == nil then\n" + " print \"new var set to 2\"" + " SCFlowintSet(0, 2)\n" + " end\n" + " a = SCFlowintDecr(0)\n" + " if a == 0 then\n" + " print \"match\"\n" + " return 1\n" + " end\n" + " return 0\n" + "end\n" + "return 0\n"; char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)"; int result = 0; uint8_t httpbuf1[] = @@ -2056,11 +2928,17 @@ end: void DetectLuaRegisterTests(void) { UtRegisterTest("LuaMatchTest01", LuaMatchTest01); + UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a); UtRegisterTest("LuaMatchTest02", LuaMatchTest02); + UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a); UtRegisterTest("LuaMatchTest03", LuaMatchTest03); + UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a); UtRegisterTest("LuaMatchTest04", LuaMatchTest04); + UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a); UtRegisterTest("LuaMatchTest05", LuaMatchTest05); + UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a); UtRegisterTest("LuaMatchTest06", LuaMatchTest06); + UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a); } #endif #endif /* HAVE_LUAJIT */ \ No newline at end of file -- 2.47.2