http_headers: mpm prefilter engines

Register for both regular headers and trailers.
pull/2310/head
Victor Julien 9 years ago
parent 9cab3ea2cd
commit 9b6fd6bb48

@ -41,6 +41,7 @@
#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"
@ -214,62 +215,102 @@ static uint8_t *DetectEngineHHDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
return headers_buffer;
}
/**
* \brief Http header match -- searches for one pattern per signature.
*
* \param det_ctx Detection engine thread ctx.
* \param headers Headers to inspect.
* \param headers_len Headers length.
/** \brief HTTP Headers Mpm prefilter callback
*
* \retval ret Number of matches.
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static inline uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *det_ctx,
const uint8_t *headers, const uint32_t headers_len,
const uint8_t flags)
static void PrefilterTxHttpRequestHeaders(DetectEngineThreadCtx *det_ctx,
const void *pectx,
Packet *p, Flow *f, void *txv,
const uint64_t idx, const uint8_t flags)
{
SCEnter();
uint32_t ret = 0;
const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
htp_tx_t *tx = (htp_tx_t *)txv;
if (flags & STREAM_TOSERVER) {
DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hhd_ctx_ts == NULL);
if (tx->request_headers == NULL)
return;
if (headers_len >= det_ctx->sgh->mpm_hhd_ctx_ts->minlen) {
ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_ts->mpm_type].
Search(det_ctx->sgh->mpm_hhd_ctx_ts, &det_ctx->mtcu,
&det_ctx->pmq, headers, headers_len);
}
} else {
DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hhd_ctx_tc == NULL);
HtpState *htp_state = f->alstate;
uint32_t buffer_len = 0;
const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx,
NULL, det_ctx,
f, htp_state,
flags,
&buffer_len);
if (headers_len >= det_ctx->sgh->mpm_hhd_ctx_tc->minlen) {
ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_tc->mpm_type].
Search(det_ctx->sgh->mpm_hhd_ctx_tc, &det_ctx->mtcu,
&det_ctx->pmq, headers, headers_len);
}
if (buffer_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
&det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
}
}
SCReturnUInt(ret);
int PrefilterTxHttpRequestHeadersRegister(SigGroupHead *sgh, MpmCtx *mpm_ctx)
{
SCEnter();
int r = PrefilterAppendTxEngine(sgh, PrefilterTxHttpRequestHeaders,
ALPROTO_HTTP, HTP_REQUEST_HEADERS,
mpm_ctx, NULL);
if (r != 0)
return r;
return PrefilterAppendTxEngine(sgh, PrefilterTxHttpRequestHeaders,
ALPROTO_HTTP, HTP_REQUEST_TRAILER,
mpm_ctx, NULL);
}
int DetectEngineRunHttpHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
HtpState *htp_state, uint8_t flags,
void *tx, uint64_t idx)
/** \brief HTTP Headers Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxHttpResponseHeaders(DetectEngineThreadCtx *det_ctx,
const void *pectx,
Packet *p, Flow *f, void *txv,
const uint64_t idx, const uint8_t flags)
{
uint32_t cnt = 0;
SCEnter();
const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->response_headers == NULL)
return;
HtpState *htp_state = f->alstate;
uint32_t buffer_len = 0;
uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx,
const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx,
NULL, det_ctx,
f, htp_state,
flags,
&buffer_len);
if (buffer_len == 0)
goto end;
cnt = HttpHeaderPatternSearch(det_ctx, buffer, buffer_len, flags);
if (buffer_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
&det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
}
}
end:
return cnt;
int PrefilterTxHttpResponseHeadersRegister(SigGroupHead *sgh, MpmCtx *mpm_ctx)
{
SCEnter();
int r = PrefilterAppendTxEngine(sgh, PrefilterTxHttpResponseHeaders,
ALPROTO_HTTP, HTP_RESPONSE_HEADERS,
mpm_ctx, NULL);
if (r != 0)
return r;
return PrefilterAppendTxEngine(sgh, PrefilterTxHttpResponseHeaders,
ALPROTO_HTTP, HTP_RESPONSE_TRAILER,
mpm_ctx, NULL);
}
int DetectEngineInspectHttpHeader(ThreadVars *tv,
@ -1979,156 +2020,6 @@ end:
return result;
}
/**
*\test Test that the http_header content matches against a http request
* which holds the content.
*/
static int DetectEngineHttpHeaderTest18(void)
{
TcpSession ssn;
Packet *p = NULL;
ThreadVars th_v;
DetectEngineCtx *de_ctx = NULL;
DetectEngineThreadCtx *det_ctx = NULL;
Flow f;
uint8_t http_buf[] =
"Host: www.onetwothreefourfivesixsevenfive.org\r\n\r\n";
uint32_t http_len = sizeof(http_buf) - 1;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOSERVER;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
"(msg:\"http header test\"; "
"content:\"one\"; http_header; content:\"five\"; http_header; "
"sid:1;)");
if (de_ctx->sig_list == NULL)
goto end;
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
/* start the search phase */
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
uint32_t r = HttpHeaderPatternSearch(det_ctx, http_buf, http_len, STREAM_TOSERVER);
if (r < 1) {
printf("expected result >= 1, got %"PRIu32": ", r);
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
SigGroupCleanup(de_ctx);
if (de_ctx != NULL)
SigCleanSignatures(de_ctx);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
UTHFreePackets(&p, 1);
return result;
}
/**
*\test Test that the http_header content matches against a http request
* which holds the content.
*/
static int DetectEngineHttpHeaderTest19(void)
{
TcpSession ssn;
Packet *p = NULL;
ThreadVars th_v;
DetectEngineCtx *de_ctx = NULL;
DetectEngineThreadCtx *det_ctx = NULL;
Flow f;
uint8_t http_buf[] =
"Host: www.onetwothreefourfivesixsevenfive.org\r\n\r\n";
uint32_t http_len = sizeof(http_buf) - 1;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flowflags |= FLOW_PKT_TOSERVER;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_HTTP;
StreamTcpInitConfig(TRUE);
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
"(msg:\"http header test\"; "
"content:\"one\"; http_header; fast_pattern; content:\"five\"; http_header; "
"sid:1;)");
if (de_ctx->sig_list == NULL)
goto end;
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
/* start the search phase */
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
uint32_t r = HttpHeaderPatternSearch(det_ctx, http_buf, http_len, STREAM_TOSERVER);
if (r != 1) {
printf("expected result 1, got %"PRIu32": ", r);
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
SigGroupCleanup(de_ctx);
if (de_ctx != NULL)
SigCleanSignatures(de_ctx);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
UTHFreePackets(&p, 1);
return result;
}
static int DetectEngineHttpHeaderTest20(void)
{
TcpSession ssn;
@ -3939,10 +3830,6 @@ void DetectEngineHttpHeaderRegisterTests(void)
DetectEngineHttpHeaderTest16);
UtRegisterTest("DetectEngineHttpHeaderTest17",
DetectEngineHttpHeaderTest17);
UtRegisterTest("DetectEngineHttpHeaderTest18",
DetectEngineHttpHeaderTest18);
UtRegisterTest("DetectEngineHttpHeaderTest19",
DetectEngineHttpHeaderTest19);
UtRegisterTest("DetectEngineHttpHeaderTest20",
DetectEngineHttpHeaderTest20);
UtRegisterTest("DetectEngineHttpHeaderTest21",

@ -25,15 +25,15 @@
#include "app-layer-htp.h"
int PrefilterTxHttpRequestHeadersRegister(SigGroupHead *sgh, MpmCtx *mpm_ctx);
int PrefilterTxHttpResponseHeadersRegister(SigGroupHead *sgh, MpmCtx *mpm_ctx);
int DetectEngineInspectHttpHeader(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *s, Flow *f, uint8_t flags,
void *alstate,
void *tx, uint64_t tx_id);
int DetectEngineRunHttpHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
HtpState *htp_state, uint8_t flags,
void *tx, uint64_t idx);
void DetectEngineCleanHHDBuffers(DetectEngineThreadCtx *det_ctx);
void DetectEngineHttpHeaderRegisterTests(void);

@ -52,6 +52,7 @@
#include "detect-engine-uri.h"
#include "detect-engine-hrud.h"
#include "detect-engine-hmd.h"
#include "detect-engine-hhd.h"
#include "detect-engine-hcd.h"
#include "detect-engine-hua.h"
#include "detect-engine-hhhd.h"
@ -96,8 +97,10 @@ AppLayerMpms app_mpms[] = {
{ "http_raw_uri", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HRUDMATCH,
SIG_GROUP_HEAD_MPM_HRUD, PrefilterTxRawUriRegister, 1 },
{ "http_header", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HHDMATCH, SIG_GROUP_HEAD_MPM_HHD, NULL, 2},
{ "http_header", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HHDMATCH, SIG_GROUP_HEAD_MPM_HHD, NULL, 3},
{ "http_header", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HHDMATCH,
SIG_GROUP_HEAD_MPM_HHD, PrefilterTxHttpRequestHeadersRegister, 2},
{ "http_header", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HHDMATCH,
SIG_GROUP_HEAD_MPM_HHD, PrefilterTxHttpRequestHeadersRegister, 3},
{ "http_user_agent", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HUADMATCH,
SIG_GROUP_HEAD_MPM_HUAD, PrefilterTxUARegister, 4},

@ -902,14 +902,6 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx,
if (p->flowflags & FLOW_PKT_TOSERVER) {
tx_progress = AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags);
if (tx_progress >= HTP_REQUEST_HEADERS) {
if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HHD) {
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HHD);
DetectEngineRunHttpHeaderMpm(det_ctx, p->flow, alstate, flags, tx, idx);
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_MPM_HHD);
}
}
if (tx_progress > HTP_REQUEST_HEADERS) {
if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HRHD) {
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HRHD);
@ -928,14 +920,6 @@ static inline void DetectMpmPrefilter(DetectEngineCtx *de_ctx,
} else { /* implied FLOW_PKT_TOCLIENT */
tx_progress = AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags);
if (tx_progress >= HTP_RESPONSE_HEADERS) {
if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HHD) {
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HHD);
DetectEngineRunHttpHeaderMpm(det_ctx, p->flow, alstate, flags, tx, idx);
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_MPM_HHD);
}
}
if (tx_progress > HTP_RESPONSE_HEADERS) {
if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_HRHD) {
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_HRHD);

Loading…
Cancel
Save