From 8f1998e35fc5e58b701f3973f68d9cf0804b1a73 Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Mon, 11 May 2015 19:48:32 +0200 Subject: [PATCH] hsbd: inspect buffer depending on the engine mode Currently, data is buffered up to response-body-minimal size and response-body-inspect-window before being inspected. With this, in IPS mode, inspect data as it comes in up. The sliding window concept is used here, some data chunks are copied into the window (buffer) then it's inspected. --- src/detect-engine-hsbd.c | 1419 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 1365 insertions(+), 54 deletions(-) diff --git a/src/detect-engine-hsbd.c b/src/detect-engine-hsbd.c index e7ef0bbd4a..77e33b958a 100644 --- a/src/detect-engine-hsbd.c +++ b/src/detect-engine-hsbd.c @@ -89,6 +89,123 @@ static inline int HSBDCreateSpace(DetectEngineThreadCtx *det_ctx, uint16_t size) return 0; } +static void HSBDGetBufferForTXInIDSMode(DetectEngineThreadCtx *det_ctx, + HtpState *htp_state, HtpBodyChunk *cur, + HtpTxUserData *htud, int index) +{ + int first = 1; + while (cur != NULL) { + /* see if we can filter out chunks */ + if (htud->response_body.body_inspected > 0) { + if (cur->stream_offset < htud->response_body.body_inspected) { + if ((htud->response_body.body_inspected - cur->stream_offset) > htp_state->cfg->response_inspect_window) { + cur = cur->next; + continue; + } else { + /* include this one */ + } + } else { + /* include this one */ + } + } + + if (first) { + det_ctx->hsbd[index].offset = cur->stream_offset; + first = 0; + } + + /* see if we need to grow the buffer */ + if (det_ctx->hsbd[index].buffer == NULL || (det_ctx->hsbd[index].buffer_len + cur->len) > det_ctx->hsbd[index].buffer_size) { + void *ptmp; + det_ctx->hsbd[index].buffer_size += cur->len * 2; + + if ((ptmp = SCRealloc(det_ctx->hsbd[index].buffer, det_ctx->hsbd[index].buffer_size)) == NULL) { + SCFree(det_ctx->hsbd[index].buffer); + det_ctx->hsbd[index].buffer = NULL; + det_ctx->hsbd[index].buffer_size = 0; + det_ctx->hsbd[index].buffer_len = 0; + return; + } + det_ctx->hsbd[index].buffer = ptmp; + } + memcpy(det_ctx->hsbd[index].buffer + det_ctx->hsbd[index].buffer_len, cur->data, cur->len); + det_ctx->hsbd[index].buffer_len += cur->len; + + cur = cur->next; + } + + /* update inspected tracker */ + htud->response_body.body_inspected = htud->response_body.last->stream_offset + htud->response_body.last->len; +} + +static void HSBDGetBufferForTXInIPSMode(DetectEngineThreadCtx *det_ctx, + HtpState *htp_state, HtpBodyChunk *cur, + HtpTxUserData *htud, int index) +{ + uint32_t window_size = 0; + uint32_t extra_size = 0; + int resize = 0; + + if (htud->response_body.content_len_so_far <= htp_state->cfg->response_inspect_min_size) { + resize = 1; + window_size = htp_state->cfg->response_inspect_min_size; + } else { + resize = 1; + window_size = htp_state->cfg->response_inspect_window; + } + + int first = 1; + while (cur != NULL) { + /* see if we need to grow the buffer */ + if (cur->len > window_size) { + extra_size = window_size * 0.25; + window_size = cur->len; + resize = 1; + } else if (cur->len == window_size) { + window_size = window_size * 1.25; + resize = 1; + } + + if (det_ctx->hsbd[index].buffer == NULL || resize) { + void *ptmp; + + if ((ptmp = SCRealloc(det_ctx->hsbd[index].buffer, window_size + extra_size)) == NULL) { + SCFree(det_ctx->hsbd[index].buffer); + det_ctx->hsbd[index].buffer = NULL; + det_ctx->hsbd[index].buffer_size = 0; + det_ctx->hsbd[index].buffer_len = 0; + return; + } + det_ctx->hsbd[index].buffer = ptmp; + resize = 0; + } + + if (first) { + det_ctx->hsbd[index].offset = cur->stream_offset; + first = 0; + } + + /* + * Copy a part of the previous buffer before the current chunk on. + * For example, let's have the chunks [123], [456]. + * When the current chunk is [456], this copy [3] before. + */ + if (det_ctx->hsbd[index].buffer_len + cur->len > window_size + extra_size) { + uint32_t offset = (det_ctx->hsbd[index].buffer_len + cur->len) - (window_size + extra_size); + /* we use memmove to avoid memory overlap */ + memmove(det_ctx->hsbd[index].buffer, det_ctx->hsbd[index].buffer + offset, det_ctx->hsbd[index].buffer_len - offset); + det_ctx->hsbd[index].buffer_len -= offset; + det_ctx->hsbd[index].offset += offset; + } + memcpy(det_ctx->hsbd[index].buffer + det_ctx->hsbd[index].buffer_len, cur->data, cur->len); + det_ctx->hsbd[index].buffer_len += cur->len; + + cur = cur->next; + } + + /* update inspected tracker */ + htud->response_body.body_inspected = htud->response_body.last->stream_offset + htud->response_body.last->len; +} static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, DetectEngineCtx *de_ctx, @@ -158,63 +275,24 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, flags & STREAM_EOF ? "true" : "false", (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) ? "true" : "false"); - /* inspect the body if the transfer is complete or we have hit - * our body size limit */ - if ((htp_state->cfg->response_body_limit == 0 || - htud->response_body.content_len_so_far < htp_state->cfg->response_body_limit) && - htud->response_body.content_len_so_far < htp_state->cfg->response_inspect_min_size && - !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) && - !(flags & STREAM_EOF)) { - SCLogDebug("we still haven't seen the entire response body. " - "Let's defer body inspection till we see the " - "entire body."); - goto end; - } - - int first = 1; - while (cur != NULL) { - /* see if we can filter out chunks */ - if (htud->response_body.body_inspected > 0) { - if (cur->stream_offset < htud->response_body.body_inspected) { - if ((htud->response_body.body_inspected - cur->stream_offset) > htp_state->cfg->response_inspect_window) { - cur = cur->next; - continue; - } else { - /* include this one */ - } - } else { - /* include this one */ - } - } - - if (first) { - det_ctx->hsbd[index].offset = cur->stream_offset; - first = 0; - } - - /* see if we need to grow the buffer */ - if (det_ctx->hsbd[index].buffer == NULL || (det_ctx->hsbd[index].buffer_len + cur->len) > det_ctx->hsbd[index].buffer_size) { - void *ptmp; - det_ctx->hsbd[index].buffer_size += cur->len * 2; - - if ((ptmp = SCRealloc(det_ctx->hsbd[index].buffer, det_ctx->hsbd[index].buffer_size)) == NULL) { - SCFree(det_ctx->hsbd[index].buffer); - det_ctx->hsbd[index].buffer = NULL; - det_ctx->hsbd[index].buffer_size = 0; - det_ctx->hsbd[index].buffer_len = 0; - goto end; - } - det_ctx->hsbd[index].buffer = ptmp; + if (!htp_state->cfg->http_body_inline) { + /* inspect the body if the transfer is complete or we have hit + * our body size limit */ + if ((htp_state->cfg->response_body_limit == 0 || + htud->response_body.content_len_so_far < htp_state->cfg->response_body_limit) && + htud->response_body.content_len_so_far < htp_state->cfg->response_inspect_min_size && + !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) && + !(flags & STREAM_EOF)) { + SCLogDebug("we still haven't seen the entire response body. " + "Let's defer body inspection till we see the " + "entire body."); + goto end; } - memcpy(det_ctx->hsbd[index].buffer + det_ctx->hsbd[index].buffer_len, cur->data, cur->len); - det_ctx->hsbd[index].buffer_len += cur->len; - - cur = cur->next; + HSBDGetBufferForTXInIDSMode(det_ctx, htp_state, cur, htud, index); + } else { + HSBDGetBufferForTXInIPSMode(det_ctx, htp_state, cur, htud, index); } - /* update inspected tracker */ - htud->response_body.body_inspected = htud->response_body.last->stream_offset + htud->response_body.last->len; - buffer = det_ctx->hsbd[index].buffer; *buffer_len = det_ctx->hsbd[index].buffer_len; *stream_start_offset = det_ctx->hsbd[index].offset; @@ -3631,6 +3709,1227 @@ end: return result; } +/* + * Tests buffer inspection like in ips mode, + * here all chunks size are smaller than the window_size. + + * in: buffer: + * [ab] [ab] + * [cd] [abcd] + * [ef] [cdef] +*/ +static int DetectEngineHttpServerBodyFileDataTest04(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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" + "ab"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "cd"; + uint32_t http_len3 = sizeof(http_buf3) - 1; + uint8_t http_buf4[] = "ef"; + 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_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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"ab\"; sid:1;)"))) + goto end; + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"bc\"; sid:2;)"))) + goto end; + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"cdef\"; sid:3;)"))) + goto end; + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"ef\"; sid:4;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 2)) { + printf("sid 2 did not match but should have: "); + goto end; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf4, http_len4); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 3)) { + printf("sid 3 did not match but should have: "); + goto end; + } + + if (!PacketAlertCheck(p2, 4)) { + printf("sid 4 did not 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); + EngineModeSetIDS(); + ConfDeInit(); + ConfRestoreContextBackup(); + return result; +} + +/* + * Tests buffer inspection like in ips mode, + * here the last chunk size is greater than the window size. + + * in: buffer: + * [ab] [ab] + * [cd] [abcd] + * [12345678] [d12345678] +*/ +static int DetectEngineHttpServerBodyFileDataTest05(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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: 12\r\n" + "\r\n" + "ab"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "cd"; + uint32_t http_len3 = sizeof(http_buf3) - 1; + uint8_t http_buf4[] = "12345678"; + 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_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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"ab\"; sid:1;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"abcd\"; sid:2;)"))) + goto end; + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"d12345678\"; sid:3;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 2)) { + printf("sid 2 did not match but should have: "); + goto end; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf4, http_len4); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 3)) { + printf("sid 3 did not 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); + EngineModeSetIDS(); + HTPFreeConfig(); + ConfDeInit(); + ConfRestoreContextBackup(); + HtpConfigRestoreBackup(); + return result; +} + +/** + * in: buffer: + * [123] [123] + * [456] [3456] + */ +static int DetectEngineHttpServerBodyFileDataTest06(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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" + "123"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "456"; + 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_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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"123\"; sid:1;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"3456\"; sid:2;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + 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) + 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); + EngineModeSetIDS(); + HTPFreeConfig(); + ConfDeInit(); + ConfRestoreContextBackup(); + HtpConfigRestoreBackup(); + return result; +} + +/** + * in: buffer: + * [ab] [ab] + * [c] [abc] + * [de] [bcde] + */ +static int DetectEngineHttpServerBodyFileDataTest07(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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: 5\r\n" + "\r\n" + "ab"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "c"; + uint32_t http_len3 = sizeof(http_buf3) - 1; + uint8_t http_buf4[] = "de"; + 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_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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"ab\"; sid:1;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"abc\"; sid:2;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"bcde\"; sid:3;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 2)) { + printf("sid 2 did not match but should have: "); + goto end; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf4, http_len4); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 3)) { + 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) + 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); + EngineModeSetIDS(); + HTPFreeConfig(); + ConfDeInit(); + ConfRestoreContextBackup(); + HtpConfigRestoreBackup(); + return result; +} + +/** + * in: buffer: + * [abcd] [abcd] + * [efgh] [defgh] + */ +static int DetectEngineHttpServerBodyFileDataTest08(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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: 8\r\n" + "\r\n" + "abcd"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "efgh"; + 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_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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"abcd\"; sid:1;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"defgh\"; sid:2;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + 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) + 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); + EngineModeSetIDS(); + HTPFreeConfig(); + ConfDeInit(); + ConfRestoreContextBackup(); + HtpConfigRestoreBackup(); + return result; +} + +/** + * in: buffer: + * [a] [a] + * [b] [ab] + * [c] [abc] + * [d] [abcd] + * [efghijklm] [defghijklm] + */ +static int DetectEngineHttpServerBodyFileDataTest09(void) +{ + + char input[] = "\ +%YAML 1.1\n\ +---\n\ +libhtp:\n\ +\n\ + default-config:\n\ +\n\ + http-body-inline: yes\n\ + response-body-minimal-inspect-size: 1\n\ + response-body-inspect-window: 4\n\ +"; + + ConfCreateContextBackup(); + ConfInit(); + HtpConfigCreateBackup(); + + ConfYamlLoadString(input, strlen(input)); + HTPConfigure(); + EngineModeSetIPS(); + 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: 13\r\n" + "\r\n" + "a"; + uint32_t http_len2 = sizeof(http_buf2) - 1; + uint8_t http_buf3[] = "b"; + uint32_t http_len3 = sizeof(http_buf3) - 1; + uint8_t http_buf4[] = "c"; + uint32_t http_len4 = sizeof(http_buf4) - 1; + uint8_t http_buf5[] = "d"; + uint32_t http_len5 = sizeof(http_buf5) - 1; + uint8_t http_buf6[] = "efghijklm"; + uint32_t http_len6 = sizeof(http_buf6) - 1; + + 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_HTTP; + + 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:\"http server body test\"; " + "file_data; content:\"abcd\"; sid:1;)"))) + goto end; + + if (!(DetectEngineAppendSig(de_ctx, "alert http any any -> any any " + "(msg:\"http server body test\"; " + "file_data; content:\"defghijklm\"; sid:2;)"))) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SCMutexLock(&f.m); + int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_len1); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf2, http_len2); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf3, http_len3); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf4, http_len4); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf5, http_len5); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* 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; + } + + SCMutexLock(&f.m); + r = AppLayerParserParse(alp_tctx, &f, ALPROTO_HTTP, STREAM_TOCLIENT, http_buf6, http_len6); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r); + result = 0; + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); + + /* do detect */ + SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); + + if (!PacketAlertCheck(p2, 2)) { + 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) + 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); + EngineModeSetIDS(); + HTPFreeConfig(); + ConfDeInit(); + ConfRestoreContextBackup(); + HtpConfigRestoreBackup(); + return result; +} #endif /* UNITTESTS */ void DetectEngineHttpServerBodyRegisterTests(void) @@ -3688,6 +4987,18 @@ void DetectEngineHttpServerBodyRegisterTests(void) DetectEngineHttpServerBodyFileDataTest02, 1); UtRegisterTest("DetectEngineHttpServerBodyFileDataTest03", DetectEngineHttpServerBodyFileDataTest03, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest04", + DetectEngineHttpServerBodyFileDataTest04, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest05", + DetectEngineHttpServerBodyFileDataTest05, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest06", + DetectEngineHttpServerBodyFileDataTest06, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest07", + DetectEngineHttpServerBodyFileDataTest07, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest08", + DetectEngineHttpServerBodyFileDataTest08, 1); + UtRegisterTest("DetectEngineHttpServerBodyFileDataTest09", + DetectEngineHttpServerBodyFileDataTest09, 1); #endif /* UNITTESTS */ return; -- 2.47.2