detect/http_stat_code: move tests into tests/

pull/3632/head
Victor Julien 6 years ago
parent 382fa2e81d
commit 2f342da048

@ -135,7 +135,6 @@ detect-engine-hcbd.c detect-engine-hcbd.h \
detect-engine-hcd.c detect-engine-hcd.h \
detect-engine-hrhd.c detect-engine-hrhd.h \
detect-engine-hsbd.c detect-engine-hsbd.h \
detect-engine-hscd.c detect-engine-hscd.h \
detect-engine-iponly.c detect-engine-iponly.h \
detect-engine-loader.c detect-engine-loader.h \
detect-engine-mpm.c detect-engine-mpm.h \

@ -1,28 +0,0 @@
/* Copyright (C) 2007-2016 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/** \file
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
#ifndef __DETECT_ENGINE_HSCD_H__
#define __DETECT_ENGINE_HSCD_H__
void DetectEngineHttpStatCodeRegisterTests(void);
#endif /* __DETECT_ENGINE_HSCD_H__ */

@ -52,7 +52,6 @@
#include "detect-engine-payload.h"
#include "detect-engine-hrhd.h"
#include "detect-engine-hcd.h"
#include "detect-engine-hscd.h"
#include "detect-engine-hcbd.h"
#include "detect-engine-hsbd.h"
#include "detect-engine-dns.h"

@ -157,7 +157,6 @@
#include "detect-engine-hsbd.h"
#include "detect-engine-hrhd.h"
#include "detect-engine-hcd.h"
#include "detect-engine-hscd.h"
#include "detect-byte-extract.h"
#include "detect-file-data.h"
#include "detect-pkt-data.h"

@ -60,14 +60,14 @@
#include "app-layer-htp.h"
#include "detect-http-stat-code.h"
#include "detect-engine-hscd.h"
#include "stream-tcp-private.h"
#include "stream-tcp.h"
static int DetectHttpStatCodeSetup(DetectEngineCtx *, Signature *, const char *);
#ifdef UNITTESTS
static void DetectHttpStatCodeRegisterTests(void);
#endif
static int g_http_stat_code_buffer_id = 0;
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f,
const uint8_t _flow_flags, void *txv, const int list_id);
@ -81,8 +81,9 @@ void DetectHttpStatCodeRegister (void)
sigmatch_table[DETECT_AL_HTTP_STAT_CODE].desc = "content modifier to match only on HTTP stat-code-buffer";
sigmatch_table[DETECT_AL_HTTP_STAT_CODE].url = DOC_URL DOC_VERSION "/rules/http-keywords.html#http-stat-code";
sigmatch_table[DETECT_AL_HTTP_STAT_CODE].Setup = DetectHttpStatCodeSetup;
#ifdef UNITTESTS
sigmatch_table[DETECT_AL_HTTP_STAT_CODE].RegisterTests = DetectHttpStatCodeRegisterTests;
#endif
sigmatch_table[DETECT_AL_HTTP_STAT_CODE].flags |= SIGMATCH_NOOPT;
DetectAppLayerInspectEngineRegister2("http_stat_code", ALPROTO_HTTP,
@ -142,583 +143,8 @@ static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
}
#ifdef UNITTESTS
/**
* \test Checks if a http_stat_code is registered in a Signature, if content is not
* specified in the signature or rawbyes is specified or fast_pattern is
* provided in the signature.
*/
static int DetectHttpStatCodeTest01(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if ((de_ctx = DetectEngineCtxInit()) == NULL) {
printf("DetectEngineCtxInit failed: ");
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; http_stat_code; sid:1;)");
if (de_ctx->sig_list != NULL) {
printf("sid 1 parse failed to error out: ");
goto end;
}
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"|FF F1|\";"
" rawbytes; http_stat_code; sid:2;)");
if (de_ctx->sig_list != NULL) {
printf("sid 2 parse failed to error out: ");
goto end;
}
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"100\";"
"fast_pattern; http_stat_code; sid:3;)");
if (de_ctx->sig_list == NULL) {
printf("sid 3 parse failed: ");
goto end;
}
if (!(((DetectContentData *)de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id]->ctx)->flags &
DETECT_CONTENT_FAST_PATTERN))
{
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Checks if a http_stat_code is registered in a Signature and also checks
* the nocase
*/
static int DetectHttpStatCodeTest02(void)
{
SigMatch *sm = NULL;
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if ( (de_ctx = DetectEngineCtxInit()) == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"one\"; "
"http_stat_code; content:\"200\"; http_stat_code; "
"content:\"two hundred\"; nocase; http_stat_code; "
"sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
result = 0;
sm = de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id];
if (sm == NULL) {
printf("no sigmatch(es): ");
goto end;
}
SigMatch *prev = NULL;
while (sm != NULL) {
if (sm->type == DETECT_CONTENT) {
result = 1;
} else {
printf("expected DETECT_CONTENT for http_stat_code, got %d: ", sm->type);
goto end;
}
prev = sm;
sm = sm->next;
}
if (! (((DetectContentData *)prev->ctx)->flags &
DETECT_CONTENT_NOCASE))
{
result = 0;
}
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched . */
static int DetectHttpStatCodeSigTest01(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
printf("DetectEngineCtxInit failed: ");
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"200\"; http_stat_code; sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is not matched . */
static int DetectHttpStatCodeSigTest02(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"no\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code\"; content:\"100\";"
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sid 1 matched but shouldn't: ");
goto end;
}
if ((PacketAlertCheck(p, 2))) {
printf("sid 2 match but shouldn't have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched for
* for nocase or not */
static int DetectHttpStatCodeSigTest03(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 FAIL OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"FAIL\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code nocase\"; content:\"fail\"; nocase; "
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
if (!(PacketAlertCheck(p, 2))) {
printf("sid 2 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched for
* for negatoin or not */
static int DetectHttpStatCodeSigTest04(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"200\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code negation\"; content:!\"100\"; nocase; "
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
if (!(PacketAlertCheck(p, 2))) {
printf("sid 2 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
#endif /* UNITTESTS */
/**
* \brief Register the UNITTESTS for the http_stat_code keyword
*/
void DetectHttpStatCodeRegisterTests (void)
{
#ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest("DetectHttpStatCodeTest01", DetectHttpStatCodeTest01);
UtRegisterTest("DetectHttpStatCodeTest02", DetectHttpStatCodeTest02);
UtRegisterTest("DetectHttpStatCodeSigTest01", DetectHttpStatCodeSigTest01);
UtRegisterTest("DetectHttpStatCodeSigTest02", DetectHttpStatCodeSigTest02);
UtRegisterTest("DetectHttpStatCodeSigTest03", DetectHttpStatCodeSigTest03);
UtRegisterTest("DetectHttpStatCodeSigTest04", DetectHttpStatCodeSigTest04);
#include "tests/detect-http-stat-code.c"
#endif /* UNITTESTS */
}
/**
* @}

@ -40,7 +40,6 @@
#include "detect-engine-hsbd.h"
#include "detect-engine-hrhd.h"
#include "detect-engine-hcd.h"
#include "detect-engine-hscd.h"
#include "detect-engine-state.h"
#include "detect-engine-tag.h"
#include "detect-engine-modbus.h"
@ -197,7 +196,6 @@ static void RegisterUnittests(void)
DetectEngineHttpServerBodyRegisterTests();
DetectEngineHttpRawHeaderRegisterTests();
DetectEngineHttpCookieRegisterTests();
DetectEngineHttpStatCodeRegisterTests();
DetectEngineInspectModbusRegisterTests();
DetectEngineRegisterTests();
DetectEngineSMTPFiledataRegisterTests();

@ -28,41 +28,19 @@
* \author Victor Julien <victor@inliniac.net>
*/
#include "suricata-common.h"
#include "suricata.h"
#include "decode.h"
#include "detect.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-hscd.h"
#include "detect-parse.h"
#include "detect-engine-state.h"
#include "detect-engine-content-inspection.h"
#include "detect-engine-prefilter.h"
#include "flow-util.h"
#include "util-debug.h"
#include "util-print.h"
#include "flow.h"
#include "stream-tcp.h"
#include "app-layer-parser.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "app-layer.h"
#include "app-layer-htp.h"
#include "app-layer-protos.h"
#include "util-validate.h"
/***********************************Unittests**********************************/
#ifdef UNITTESTS
#include "../suricata-common.h"
#include "../suricata.h"
#include "../flow-util.h"
#include "../flow.h"
#include "../app-layer-parser.h"
#include "../util-unittest.h"
#include "../util-unittest-helper.h"
#include "../app-layer.h"
#include "../app-layer-htp.h"
#include "../app-layer-protos.h"
static int DetectEngineHttpStatCodeTest01(void)
{
{
TcpSession ssn;
Packet *p1 = NULL;
Packet *p2 = NULL;
@ -1957,12 +1935,569 @@ end:
return result;
}
#endif /* UNITTESTS */
/**
* \test Checks if a http_stat_code is registered in a Signature, if content is not
* specified in the signature or rawbyes is specified or fast_pattern is
* provided in the signature.
*/
static int DetectHttpStatCodeTest01(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if ((de_ctx = DetectEngineCtxInit()) == NULL) {
printf("DetectEngineCtxInit failed: ");
goto end;
}
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; http_stat_code; sid:1;)");
if (de_ctx->sig_list != NULL) {
printf("sid 1 parse failed to error out: ");
goto end;
}
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"|FF F1|\";"
" rawbytes; http_stat_code; sid:2;)");
if (de_ctx->sig_list != NULL) {
printf("sid 2 parse failed to error out: ");
goto end;
}
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"100\";"
"fast_pattern; http_stat_code; sid:3;)");
if (de_ctx->sig_list == NULL) {
printf("sid 3 parse failed: ");
goto end;
}
if (!(((DetectContentData *)de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id]->ctx)->flags &
DETECT_CONTENT_FAST_PATTERN))
{
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
void DetectEngineHttpStatCodeRegisterTests(void)
/**
* \test Checks if a http_stat_code is registered in a Signature and also checks
* the nocase
*/
static int DetectHttpStatCodeTest02(void)
{
SigMatch *sm = NULL;
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if ( (de_ctx = DetectEngineCtxInit()) == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(msg:\"Testing http_stat_code\"; content:\"one\"; "
"http_stat_code; content:\"200\"; http_stat_code; "
"content:\"two hundred\"; nocase; http_stat_code; "
"sid:1;)");
if (de_ctx->sig_list == NULL) {
printf("sig parse failed: ");
goto end;
}
#ifdef UNITTESTS
result = 0;
sm = de_ctx->sig_list->sm_lists[g_http_stat_code_buffer_id];
if (sm == NULL) {
printf("no sigmatch(es): ");
goto end;
}
SigMatch *prev = NULL;
while (sm != NULL) {
if (sm->type == DETECT_CONTENT) {
result = 1;
} else {
printf("expected DETECT_CONTENT for http_stat_code, got %d: ", sm->type);
goto end;
}
prev = sm;
sm = sm->next;
}
if (! (((DetectContentData *)prev->ctx)->flags &
DETECT_CONTENT_NOCASE))
{
result = 0;
}
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched . */
static int DetectHttpStatCodeSigTest01(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
printf("DetectEngineCtxInit failed: ");
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"200\"; http_stat_code; sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is not matched . */
static int DetectHttpStatCodeSigTest02(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"no\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code\"; content:\"100\";"
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sid 1 matched but shouldn't: ");
goto end;
}
if ((PacketAlertCheck(p, 2))) {
printf("sid 2 match but shouldn't have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched for
* for nocase or not */
static int DetectHttpStatCodeSigTest03(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 FAIL OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"FAIL\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code nocase\"; content:\"fail\"; nocase; "
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
if (!(PacketAlertCheck(p, 2))) {
printf("sid 2 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when http_stat_code is matched for
* for negatoin or not */
static int DetectHttpStatCodeSigTest04(void)
{
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOCLIENT;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP status code\"; content:\"200\"; "
"http_stat_code; sid:1;)");
if (s == NULL) {
goto end;
}
s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\"HTTP "
"Status code negation\"; content:!\"100\"; nocase; "
"http_stat_code; sid:2;)");
if (s->next == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOCLIENT, httpbuf2, httplen2);
if (r != 0) {
printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
http_state = f.alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sid 1 didn't match but should have: ");
goto end;
}
if (!(PacketAlertCheck(p, 2))) {
printf("sid 2 didn't match but should have: ");
goto end;
}
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/**
* \brief Register the UNITTESTS for the http_stat_code keyword
*/
void DetectHttpStatCodeRegisterTests (void)
{
UtRegisterTest("DetectEngineHttpStatCodeTest01",
DetectEngineHttpStatCodeTest01);
UtRegisterTest("DetectEngineHttpStatCodeTest02",
@ -1993,9 +2528,13 @@ void DetectEngineHttpStatCodeRegisterTests(void)
DetectEngineHttpStatCodeTest14);
UtRegisterTest("DetectEngineHttpStatCodeTest15",
DetectEngineHttpStatCodeTest15);
#endif /* UNITTESTS */
return;
UtRegisterTest("DetectHttpStatCodeTest01", DetectHttpStatCodeTest01);
UtRegisterTest("DetectHttpStatCodeTest02", DetectHttpStatCodeTest02);
UtRegisterTest("DetectHttpStatCodeSigTest01", DetectHttpStatCodeSigTest01);
UtRegisterTest("DetectHttpStatCodeSigTest02", DetectHttpStatCodeSigTest02);
UtRegisterTest("DetectHttpStatCodeSigTest03", DetectHttpStatCodeSigTest03);
UtRegisterTest("DetectHttpStatCodeSigTest04", DetectHttpStatCodeSigTest04);
}
/**
Loading…
Cancel
Save