/* Copyright (C) 2007-2010 Open Information Security Foundation
*
* You can copy , redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA .
*/
/**
* \ file
*
* \ author Anoop Saldanha < poonaatsoc @ gmail . com >
*
* Implements support for the http_client_body keyword
*/
# include "suricata-common.h"
# include "threads.h"
# include "decode.h"
# include "detect.h"
# include "detect-parse.h"
# include "detect-engine.h"
# include "detect-engine-mpm.h"
# include "detect-engine-state.h"
# include "detect-content.h"
# include "flow.h"
# include "flow-var.h"
# include "flow-util.h"
# include "util-debug.h"
# include "util-unittest.h"
# include "util-unittest-helper.h"
# include "util-spm.h"
# include "app-layer.h"
# include <htp/htp.h>
# include "app-layer-htp.h"
# include "detect-http-client-body.h"
# include "stream-tcp.h"
int DetectHttpClientBodyMatch ( ThreadVars * t , DetectEngineThreadCtx * det_ctx ,
Flow * f , uint8_t flags , void * state , Signature * s ,
SigMatch * m ) ;
int DetectHttpClientBodySetup ( DetectEngineCtx * , Signature * , char * ) ;
void DetectHttpClientBodyRegisterTests ( void ) ;
void DetectHttpClientBodyFree ( void * ) ;
/**
* \ brief Registers the keyword handlers for the " http_client_body " keyword .
*/
void DetectHttpClientBodyRegister ( void )
{
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . name = " http_client_body " ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . Match = NULL ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . AppLayerMatch = DetectHttpClientBodyMatch ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . alproto = ALPROTO_HTTP ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . Setup = DetectHttpClientBodySetup ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . Free = DetectHttpClientBodyFree ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . RegisterTests = DetectHttpClientBodyRegisterTests ;
sigmatch_table [ DETECT_AL_HTTP_CLIENT_BODY ] . flags | = SIGMATCH_PAYLOAD ;
}
/**
* \ brief App layer match function for the " http_client_body " keyword .
*
* \ param t Pointer to the ThreadVars instance .
* \ param det_ctx Pointer to the DetectEngineThreadCtx .
* \ param f Pointer to the flow .
* \ param flags Pointer to the flags indicating the flow direction .
* \ param state Pointer to the app layer state data .
* \ param s Pointer to the Signature instance .
* \ param m Pointer to the SigMatch .
*
* \ retval 1 On Match .
* \ retval 0 On no match .
*/
int DetectHttpClientBodyMatch ( ThreadVars * t , DetectEngineThreadCtx * det_ctx ,
Flow * f , uint8_t flags , void * state , Signature * s ,
SigMatch * m )
{
int result = 0 ;
DetectHttpClientBodyData * hcbd = ( DetectHttpClientBodyData * ) m - > ctx ;
HtpState * htp_state = ( HtpState * ) state ;
SCMutexLock ( & f - > m ) ;
if ( htp_state = = NULL ) {
SCLogDebug ( " No htp state, no match at http body data " ) ;
goto end ;
}
htp_tx_t * tx = NULL ;
size_t idx = 0 ;
for ( idx = 0 ; //hs->new_in_tx_index;
idx < list_size ( htp_state - > connp - > conn - > transactions ) ; idx + + )
{
tx = list_get ( htp_state - > connp - > conn - > transactions , idx ) ;
if ( tx = = NULL )
continue ;
SCHtpTxUserData * htud = ( SCHtpTxUserData * ) htp_tx_get_user_data ( tx ) ;
if ( htud = = NULL )
continue ;
HtpBodyChunk * cur = htud - > body . first ;
if ( htud - > body . nchunks = = 0 ) {
SCLogDebug ( " No http chunks to inspect " ) ;
goto end ;
} else {
/* no chunks?!! get out of here */
if ( cur = = NULL ) {
SCLogDebug ( " No http chunks to inspect " ) ;
goto end ;
}
/* this applies only for the client request body like the keyword name says */
if ( htud - > body . operation ! = HTP_BODY_REQUEST ) {
SCLogDebug ( " htp chunk not a request chunk " ) ;
goto end ;
}
/* this is not how we do it now. We can rather hold the PM state from
* the previous chunk that was matched , and continue right from where
* we left off . We need to devise a scheme to do that , not just for
* this keyword , but other keywords need it as well */
uint8_t * chunks_buffer = NULL ;
uint32_t total_chunks_len = 0 ;
/* club all the chunks into one whole buffer and call the SPM on the buffer */
while ( cur ! = NULL ) {
total_chunks_len + = cur - > len ;
if ( ( chunks_buffer = SCRealloc ( chunks_buffer , total_chunks_len ) ) = = NULL ) {
return 0 ;
}
memcpy ( chunks_buffer + total_chunks_len - cur - > len , cur - > data , cur - > len ) ;
cur = cur - > next ;
}
/* call the case insensitive version if nocase has been specified in the sig */
if ( hcbd - > flags & DETECT_AL_HTTP_CLIENT_BODY_NOCASE ) {
result = ( BoyerMooreNocase ( hcbd - > content , hcbd - > content_len , chunks_buffer ,
total_chunks_len , hcbd - > bm_ctx - > bmGs ,
hcbd - > bm_ctx - > bmBc ) ! = NULL ) ;
/* call the case sensitive version if nocase has been specified in the sig */
} else {
result = ( BoyerMoore ( hcbd - > content , hcbd - > content_len , chunks_buffer ,
total_chunks_len , hcbd - > bm_ctx - > bmGs ,
hcbd - > bm_ctx - > bmBc ) ! = NULL ) ;
}
SCFree ( chunks_buffer ) ;
}
}
SCMutexUnlock ( & f - > m ) ;
return result ^ ( ( hcbd - > flags & DETECT_AL_HTTP_CLIENT_BODY_NEGATED ) ? 1 : 0 ) ;
end :
SCMutexUnlock ( & f - > m ) ;
return result ;
}
/**
* \ brief The setup function for the http_client_body keyword for a signature .
*
* \ param de_ctx Pointer to the detection engine context .
* \ param s Pointer to signature for the current Signature being parsed
* from the rules .
* \ param m Pointer to the head of the SigMatchs for the current rule
* being parsed .
* \ param arg Pointer to the string holding the keyword value .
*
* \ retval 0 On success
* \ retval - 1 On failure
*/
int DetectHttpClientBodySetup ( DetectEngineCtx * de_ctx , Signature * s , char * arg )
{
/* http_client_body_data (hcbd) */
DetectHttpClientBodyData * hcbd = NULL ;
SigMatch * nm = NULL ;
SigMatch * sm = NULL ;
if ( arg ! = NULL & & strcmp ( arg , " " ) ! = 0 ) {
SCLogError ( SC_ERR_INVALID_ARGUMENT , " http_client_body supplied with no "
" args " ) ;
return - 1 ;
}
if ( s - > pmatch_tail = = NULL ) {
SCLogError ( SC_ERR_INVALID_SIGNATURE , " http_client_body found inside the "
" rule, without any preceding content keywords " ) ;
return - 1 ;
}
sm = DetectContentGetLastPattern ( s - > pmatch_tail ) ;
/* if still we are unable to find any content previous keywords, it is an
* invalid rule */
if ( sm = = NULL ) {
SCLogError ( SC_ERR_INVALID_SIGNATURE , " \" http_client_body \" keyword "
" found inside the rule without a content context. "
" Please use a \" content \" keyword before using the "
" \" http_client_body \" keyword " ) ;
return - 1 ;
}
if ( ( ( DetectContentData * ) sm - > ctx ) - > flags & DETECT_CONTENT_FAST_PATTERN )
{
SCLogWarning ( SC_WARN_COMPATIBILITY ,
" http_client_body cannot be used with \" fast_pattern \" currently. "
" Unsetting fast_pattern on this modifier. Signature ==> %s " , s - > sig_str ) ;
( ( DetectContentData * ) sm - > ctx ) - > flags & = ~ DETECT_CONTENT_FAST_PATTERN ;
}
/* http_client_body should not be used with the rawbytes rule */
if ( ( ( DetectContentData * ) sm - > ctx ) - > flags & DETECT_CONTENT_RAWBYTES ) {
SCLogError ( SC_ERR_INVALID_SIGNATURE , " http_client_body rule can not "
" be used with the rawbytes rule keyword " ) ;
return - 1 ;
}
if ( s - > alproto ! = ALPROTO_UNKNOWN & & s - > alproto ! = ALPROTO_HTTP ) {
SCLogError ( SC_ERR_CONFLICTING_RULE_KEYWORDS , " rule contains conflicting keywords " ) ;
goto error ;
}
/* setup the HttpClientBodyData's data from content data structure's data */
hcbd = SCMalloc ( sizeof ( DetectHttpClientBodyData ) ) ;
if ( hcbd = = NULL )
goto error ;
memset ( hcbd , 0 , sizeof ( DetectHttpClientBodyData ) ) ;
/* transfer the pattern details from the content struct to the clientbody struct */
hcbd - > content = ( ( DetectContentData * ) sm - > ctx ) - > content ;
hcbd - > content_len = ( ( DetectContentData * ) sm - > ctx ) - > content_len ;
hcbd - > flags | = ( ( ( DetectContentData * ) sm - > ctx ) - > flags & DETECT_CONTENT_NOCASE ) ?
DETECT_AL_HTTP_CLIENT_BODY_NOCASE : 0 ;
hcbd - > flags | = ( ( ( DetectContentData * ) sm - > ctx ) - > flags & DETECT_CONTENT_NEGATED ) ?
DETECT_AL_HTTP_CLIENT_BODY_NEGATED : 0 ;
//hcbd->id = ((DetectContentData *)sm->ctx)->id;
hcbd - > id = DetectPatternGetId ( de_ctx - > mpm_pattern_id_store , hcbd , DETECT_AL_HTTP_CLIENT_BODY ) ;
hcbd - > bm_ctx = ( ( DetectContentData * ) sm - > ctx ) - > bm_ctx ;
nm = SigMatchAlloc ( ) ;
if ( nm = = NULL ) {
SCLogError ( SC_ERR_MEM_ALLOC , " Error allocating memory " ) ;
goto error ;
}
nm - > type = DETECT_AL_HTTP_CLIENT_BODY ;
nm - > ctx = ( void * ) hcbd ;
/* pull the previous content from the pmatch list, append
* the new match to the match list */
SigMatchReplaceContent ( s , sm , nm ) ;
/* free the old content sigmatch, the content pattern memory
* is taken over by the new sigmatch */
SCFree ( sm - > ctx ) ;
SCFree ( sm ) ;
/* flag the signature to indicate that we scan the app layer data */
s - > flags | = SIG_FLAG_APPLAYER ;
s - > alproto = ALPROTO_HTTP ;
/* enable http request body callback in the http app layer parser */
AppLayerHtpEnableRequestBodyCallback ( ) ;
return 0 ;
error :
if ( hcbd ! = NULL )
DetectHttpClientBodyFree ( hcbd ) ;
if ( nm ! = NULL )
SCFree ( nm ) ;
return - 1 ;
}
/**
* \ brief The function to free the http_client_body data .
*
* \ param ptr Pointer to the http_client_body .
*/
void DetectHttpClientBodyFree ( void * ptr )
{
SCEnter ( ) ;
DetectHttpClientBodyData * hcbd = ( DetectHttpClientBodyData * ) ptr ;
if ( hcbd = = NULL )
SCReturn ;
if ( hcbd - > content ! = NULL )
SCFree ( hcbd - > content ) ;
BoyerMooreCtxDeInit ( hcbd - > bm_ctx ) ;
SCFree ( hcbd ) ;
SCReturn ;
}
/************************************Unittests*********************************/
# ifdef UNITTESTS
# include "stream-tcp-reassemble.h"
/**
* \ test Test that a signature containting a http_client_body is correctly parsed
* and the keyword is registered .
*/
static int DetectHttpClientBodyTest01 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
SigMatch * sm = NULL ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing http_client_body \" ; "
" content:one; http_client_body; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 1 ;
} else {
goto end ;
}
sm = de_ctx - > sig_list - > match ;
if ( sm ! = NULL ) {
result & = ( sm - > type = = DETECT_AL_HTTP_CLIENT_BODY ) ;
result & = ( sm - > next = = NULL ) ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test that a signature containing an valid http_client_body entry is
* parsed .
*/
static int DetectHttpClientBodyTest02 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing http_client_body \" ; "
" content:one; http_client_body:; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL )
result = 1 ;
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test that an invalid signature containing no content but a http_client_body
* is invalidated .
*/
static int DetectHttpClientBodyTest03 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing http_client_body \" ; "
" http_client_body; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
result = 1 ;
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test that an invalid signature containing a rawbytes along with a
* http_client_body is invalidated .
*/
static int DetectHttpClientBodyTest04 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing http_client_body \" ; "
" content:one; rawbytes; http_client_body; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
result = 1 ;
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test that an invalid signature containing a rawbytes along with a
* http_client_body is invalidated .
*/
static int DetectHttpClientBodyTest05 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing http_client_body \" ; "
" content:one; http_client_body; nocase; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL )
result = 1 ;
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* which holds the content .
*/
static int DetectHttpClientBodyTest06 ( void )
{
TcpSession ssn ;
Packet * p = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 26 \r \n "
" \r \n "
" This is dummy message body \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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:message; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf , http_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: \n " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sid 1 didn't match but should have \n " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p , 1 ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* which holds the content .
*/
static int DetectHttpClientBodyTest07 ( void )
{
TcpSession ssn ;
Packet * p1 = NULL ;
Packet * p2 = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http1_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 67 \r \n "
" \r \n "
" This is dummy message body1 " ;
uint8_t http2_buf [ ] =
" This is dummy message body2 \r \n " ;
uint32_t http1_len = sizeof ( http1_buf ) - 1 ;
uint32_t http2_len = sizeof ( http2_buf ) - 1 ;
int result = 0 ;
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOSERVER ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content: \" message \" ; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http1_buf , http1_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( ! ( PacketAlertCheck ( p1 , 1 ) ) ) {
printf ( " sid 1 didn't match on p1 but should have: " ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http2_buf , http2_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
/* VJ right now we won't inspect the body another time if it
already matched once . Later we will take care of that .
if ( ! ( PacketAlertCheck ( p2 , 1 ) ) ) {
printf ( " sid 1 didn't match on p2 but should have: " ) ;
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 ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* which holds the content .
*/
static int DetectHttpClientBodyTest08 ( void )
{
TcpSession ssn ;
Packet * p1 = NULL ;
Packet * p2 = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http1_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 67 \r \n "
" \r \n "
" This is dummy body1 " ;
uint8_t http2_buf [ ] =
" This is dummy message body2 \r \n " ;
uint32_t http1_len = sizeof ( http1_buf ) - 1 ;
uint32_t http2_len = sizeof ( http2_buf ) - 1 ;
int result = 0 ;
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOSERVER ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:message; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http1_buf , http1_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( ( PacketAlertCheck ( p1 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http2_buf , http2_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
if ( ! ( PacketAlertCheck ( p2 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* which holds the content , against a cross boundary present pattern .
*/
static int DetectHttpClientBodyTest09 ( void )
{
TcpSession ssn ;
Packet * p1 = NULL ;
Packet * p2 = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http1_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 67 \r \n "
" \r \n "
" This is dummy body1 " ;
uint8_t http2_buf [ ] =
" This is dummy message body2 \r \n " ;
uint32_t http1_len = sizeof ( http1_buf ) - 1 ;
uint32_t http2_len = sizeof ( http2_buf ) - 1 ;
int result = 0 ;
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOSERVER ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:body1This; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http1_buf , http1_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( ( PacketAlertCheck ( p1 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http2_buf , http2_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
if ( ! ( PacketAlertCheck ( p2 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* against a case insensitive pattern .
*/
static int DetectHttpClientBodyTest10 ( void )
{
TcpSession ssn ;
Packet * p1 = NULL ;
Packet * p2 = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http1_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 67 \r \n "
" \r \n "
" This is dummy bodY1 " ;
uint8_t http2_buf [ ] =
" This is dummy message body2 \r \n " ;
uint32_t http1_len = sizeof ( http1_buf ) - 1 ;
uint32_t http2_len = sizeof ( http2_buf ) - 1 ;
int result = 0 ;
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOSERVER ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:body1This; http_client_body; nocase; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http1_buf , http1_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: \n " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( ( PacketAlertCheck ( p1 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have \n " ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http2_buf , http2_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: \n " , r ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
if ( ! ( PacketAlertCheck ( p2 , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
/**
* \ test Test that the negated http_client_body content matches against a
* http request which doesn ' t hold the content .
*/
static int DetectHttpClientBodyTest11 ( void )
{
TcpSession ssn ;
Packet * p = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 26 \r \n "
" \r \n "
" This is dummy message body \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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:!message1; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf , http_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p , 1 ) ;
return result ;
}
/**
* \ test Negative test that the negated http_client_body content matches against a
* http request which holds hold the content .
*/
static int DetectHttpClientBodyTest12 ( void )
{
TcpSession ssn ;
Packet * p = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 26 \r \n "
" \r \n "
" This is dummy message body \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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:!message; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf , http_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p , 1 ) ;
return result ;
}
/**
* \ test Test that the http_client_body content matches against a http request
* which holds the content .
*/
static int DetectHttpClientBodyTest13 ( void )
{
TcpSession ssn ;
Packet * p = NULL ;
ThreadVars th_v ;
DetectEngineCtx * de_ctx = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
HtpState * http_state = NULL ;
Flow f ;
uint8_t http_buf [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 100 \r \n "
" \r \n "
" longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend \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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http client body test \" ; "
" content:abcdefghijklmnopqrstuvwxyz0123456789; http_client_body; "
" sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL )
goto end ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf , http_len ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sid 1 didn't match but should have " ) ;
goto end ;
}
result = 1 ;
end :
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p , 1 ) ;
return result ;
}
/** \test multiple http transactions and body chunks of request handling */
static int DetectHttpClientBodyTest14 ( void ) {
int result = 0 ;
Signature * s = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
ThreadVars th_v ;
Flow f ;
TcpSession ssn ;
Packet * p = NULL ;
uint8_t httpbuf1 [ ] = " POST / HTTP/1.1 \r \n " ;
uint8_t httpbuf2 [ ] = " User-Agent: Mozilla/1.0 \r \n Content-Length: 10 \r \n " ;
uint8_t httpbuf3 [ ] = " Cookie: dummy \r \n \r \n " ;
uint8_t httpbuf4 [ ] = " Body one!! " ;
uint32_t httplen1 = sizeof ( httpbuf1 ) - 1 ; /* minus the \0 */
uint32_t httplen2 = sizeof ( httpbuf2 ) - 1 ; /* minus the \0 */
uint32_t httplen3 = sizeof ( httpbuf3 ) - 1 ; /* minus the \0 */
uint32_t httplen4 = sizeof ( httpbuf4 ) - 1 ; /* minus the \0 */
uint8_t httpbuf5 [ ] = " GET /?var=val HTTP/1.1 \r \n " ;
uint8_t httpbuf6 [ ] = " User-Agent: Firefox/1.0 \r \n " ;
uint8_t httpbuf7 [ ] = " Cookie: dummy2 \r \n Content-Length: 10 \r \n \r \n Body two!! " ;
uint32_t httplen5 = sizeof ( httpbuf5 ) - 1 ; /* minus the \0 */
uint32_t httplen6 = sizeof ( httpbuf6 ) - 1 ; /* minus the \0 */
uint32_t httplen7 = sizeof ( httpbuf7 ) - 1 ; /* minus the \0 */
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL ) {
goto end ;
}
de_ctx - > flags | = DE_QUIET ;
s = DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any (content: \" POST \" ; http_method; content: \" Mozilla \" ; http_header; content: \" dummy \" ; http_cookie; content: \" one \" ; http_client_body; sid:1; rev:1;) " ) ;
if ( s = = NULL ) {
printf ( " sig parse failed: " ) ;
goto end ;
}
s = DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any (content: \" GET \" ; http_method; content: \" Firefox \" ; http_header; content: \" dummy2 \" ; http_cookie; content: \" two \" ; http_client_body; sid:2; rev:1;) " ) ;
if ( s = = NULL ) {
printf ( " sig2 parse failed: " ) ;
goto end ;
}
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf1 , httplen1 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf2 , httplen2 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 2 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted (2): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf3 , httplen3 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 3 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " signature matched, but shouldn't have: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf4 , httplen4 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 4 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sig 1 didn't alert: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf5 , httplen5 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 5 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted (5): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf6 , httplen6 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 6 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ( PacketAlertCheck ( p , 1 ) ) | | ( PacketAlertCheck ( p , 2 ) ) ) {
printf ( " sig 1 alerted (request 2, chunk 6): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
SCLogDebug ( " sending data chunk 7 " ) ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf7 , httplen7 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 7 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 2 ) ) ) {
printf ( " signature 2 didn't match, but should have: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
HtpState * htp_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( htp_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
if ( list_size ( htp_state - > connp - > conn - > transactions ) ! = 2 ) {
printf ( " The http app layer doesn't have 2 transactions, but it should: " ) ;
goto end ;
}
result = 1 ;
end :
if ( det_ctx ! = NULL ) {
DetectEngineThreadCtxDeinit ( & th_v , ( void * ) det_ctx ) ;
}
if ( de_ctx ! = NULL ) {
SigGroupCleanup ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
}
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePacket ( p ) ;
return result ;
}
/** \test multiple http transactions and body chunks of request handling */
static int DetectHttpClientBodyTest15 ( void ) {
int result = 0 ;
Signature * s = NULL ;
DetectEngineThreadCtx * det_ctx = NULL ;
ThreadVars th_v ;
Flow f ;
TcpSession ssn ;
Packet * p = NULL ;
uint8_t httpbuf1 [ ] = " POST / HTTP/1.1 \r \n " ;
uint8_t httpbuf2 [ ] = " User-Agent: Mozilla/1.0 \r \n Content-Length: 10 \r \n " ;
uint8_t httpbuf3 [ ] = " Cookie: dummy \r \n \r \n " ;
uint8_t httpbuf4 [ ] = " Body one!! " ;
uint32_t httplen1 = sizeof ( httpbuf1 ) - 1 ; /* minus the \0 */
uint32_t httplen2 = sizeof ( httpbuf2 ) - 1 ; /* minus the \0 */
uint32_t httplen3 = sizeof ( httpbuf3 ) - 1 ; /* minus the \0 */
uint32_t httplen4 = sizeof ( httpbuf4 ) - 1 ; /* minus the \0 */
uint8_t httpbuf5 [ ] = " GET /?var=val HTTP/1.1 \r \n " ;
uint8_t httpbuf6 [ ] = " User-Agent: Firefox/1.0 \r \n " ;
uint8_t httpbuf7 [ ] = " Cookie: dummy2 \r \n Content-Length: 10 \r \n \r \n Body two!! " ;
uint32_t httplen5 = sizeof ( httpbuf5 ) - 1 ; /* minus the \0 */
uint32_t httplen6 = sizeof ( httpbuf6 ) - 1 ; /* minus the \0 */
uint32_t httplen7 = sizeof ( httpbuf7 ) - 1 ; /* minus the \0 */
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 . src . family = AF_INET ;
f . dst . family = AF_INET ;
p - > flow = & f ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flags | = PKT_HAS_FLOW ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL ) {
goto end ;
}
de_ctx - > flags | = DE_QUIET ;
s = DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any (content: \" POST \" ; http_method; content: \" Mozilla \" ; http_header; content: \" dummy \" ; http_cookie; content: \" one \" ; http_client_body; sid:1; rev:1;) " ) ;
if ( s = = NULL ) {
printf ( " sig parse failed: " ) ;
goto end ;
}
s = DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any (content: \" GET \" ; http_method; content: \" Firefox \" ; http_header; content: \" dummy2 \" ; http_cookie; content: \" two \" ; http_client_body; sid:2; rev:1;) " ) ;
if ( s = = NULL ) {
printf ( " sig2 parse failed: " ) ;
goto end ;
}
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf1 , httplen1 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf2 , httplen2 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 2 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted (2): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf3 , httplen3 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 3 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " signature matched, but shouldn't have: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf4 , httplen4 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 4 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 1 ) ) ) {
printf ( " sig 1 didn't alert: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf5 , httplen5 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 5 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ) {
printf ( " sig 1 alerted (5): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf6 , httplen6 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 6 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ( PacketAlertCheck ( p , 1 ) ) | | ( PacketAlertCheck ( p , 2 ) ) ) {
printf ( " sig 1 alerted (request 2, chunk 6): " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
SCLogDebug ( " sending data chunk 7 " ) ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf7 , httplen7 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 7 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( ! ( PacketAlertCheck ( p , 2 ) ) ) {
printf ( " signature 2 didn't match, but should have: " ) ;
goto end ;
}
p - > alerts . cnt = 0 ;
HtpState * htp_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( htp_state = = NULL ) {
printf ( " no http state: " ) ;
result = 0 ;
goto end ;
}
/* hardcoded check of the transactions and it's client body chunks */
if ( list_size ( htp_state - > connp - > conn - > transactions ) ! = 2 ) {
printf ( " The http app layer doesn't have 2 transactions, but it should: " ) ;
goto end ;
}
htp_tx_t * t1 = list_get ( htp_state - > connp - > conn - > transactions , 0 ) ;
htp_tx_t * t2 = list_get ( htp_state - > connp - > conn - > transactions , 1 ) ;
SCHtpTxUserData * htud = ( SCHtpTxUserData * ) htp_tx_get_user_data ( t1 ) ;
HtpBodyChunk * cur = htud - > body . first ;
if ( htud - > body . nchunks = = 0 ) {
SCLogDebug ( " No body data in t1 (it should be removed only when the tx is destroyed): " ) ;
goto end ;
}
if ( memcmp ( cur - > data , " Body one!! " , strlen ( " Body one!! " ) ) ! = 0 ) {
SCLogDebug ( " Body data in t1 is not correctly set: " ) ;
goto end ;
}
htud = ( SCHtpTxUserData * ) htp_tx_get_user_data ( t2 ) ;
cur = htud - > body . first ;
if ( htud - > body . nchunks = = 0 ) {
SCLogDebug ( " No body data in t1 (it should be removed only when the tx is destroyed): " ) ;
goto end ;
}
if ( memcmp ( cur - > data , " Body two!! " , strlen ( " Body two!! " ) ) ! = 0 ) {
SCLogDebug ( " Body data in t1 is not correctly set: " ) ;
goto end ;
}
result = 1 ;
end :
if ( det_ctx ! = NULL ) {
DetectEngineThreadCtxDeinit ( & th_v , ( void * ) det_ctx ) ;
}
if ( de_ctx ! = NULL ) {
SigGroupCleanup ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
}
FlowL7DataPtrFree ( & f ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePacket ( p ) ;
return result ;
}
int DetectHttpClientBodyTest16 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; content:one; http_client_body; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd = de_ctx - > sig_list - > amatch_tail - > ctx ;
if ( cd - > id = = hcbd - > id )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
int DetectHttpClientBodyTest17 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; http_client_body; content:one; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd = de_ctx - > sig_list - > amatch_tail - > ctx ;
if ( cd - > id = = hcbd - > id )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
int DetectHttpClientBodyTest18 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; content:one; content:one; http_client_body; content:one; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd = de_ctx - > sig_list - > amatch_tail - > ctx ;
if ( cd - > id ! = 0 | | hcbd - > id ! = 1 )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
int DetectHttpClientBodyTest19 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; http_client_body; content:one; content:one; content:one; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd = de_ctx - > sig_list - > amatch_tail - > ctx ;
if ( cd - > id ! = 1 | | hcbd - > id ! = 0 )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
int DetectHttpClientBodyTest20 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; http_client_body; "
" content:one; content:one; http_client_body; content:one; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd1 = de_ctx - > sig_list - > amatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd2 = de_ctx - > sig_list - > amatch_tail - > prev - > ctx ;
if ( cd - > id ! = 1 | | hcbd1 - > id ! = 0 | | hcbd2 - > id ! = 0 )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
int DetectHttpClientBodyTest21 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 0 ;
if ( ( de_ctx = DetectEngineCtxInit ( ) ) = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert icmp any any -> any any "
" (content:one; http_client_body; "
" content:one; content:one; http_client_body; content:two; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > pmatch = = NULL ) {
printf ( " de_ctx->sig_list->pmatch == NULL \n " ) ;
goto end ;
}
if ( de_ctx - > sig_list - > amatch = = NULL ) {
printf ( " de_ctx->sig_list->amatch == NULL \n " ) ;
goto end ;
}
DetectContentData * cd = de_ctx - > sig_list - > pmatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd1 = de_ctx - > sig_list - > amatch_tail - > ctx ;
DetectHttpClientBodyData * hcbd2 = de_ctx - > sig_list - > amatch_tail - > prev - > ctx ;
if ( cd - > id ! = 2 | | hcbd1 - > id ! = 0 | | hcbd2 - > id ! = 0 )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
# endif /* UNITTESTS */
void DetectHttpClientBodyRegisterTests ( void )
{
# ifdef UNITTESTS
UtRegisterTest ( " DetectHttpClientBodyTest01 " , DetectHttpClientBodyTest01 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest02 " , DetectHttpClientBodyTest02 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest03 " , DetectHttpClientBodyTest03 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest04 " , DetectHttpClientBodyTest04 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest05 " , DetectHttpClientBodyTest05 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest06 " , DetectHttpClientBodyTest06 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest07 " , DetectHttpClientBodyTest07 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest08 " , DetectHttpClientBodyTest08 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest09 " , DetectHttpClientBodyTest09 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest10 " , DetectHttpClientBodyTest10 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest11 " , DetectHttpClientBodyTest11 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest12 " , DetectHttpClientBodyTest12 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest13 " , DetectHttpClientBodyTest13 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest14 " , DetectHttpClientBodyTest14 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest15 " , DetectHttpClientBodyTest15 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest16 " , DetectHttpClientBodyTest16 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest17 " , DetectHttpClientBodyTest17 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest18 " , DetectHttpClientBodyTest18 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest19 " , DetectHttpClientBodyTest19 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest20 " , DetectHttpClientBodyTest20 , 1 ) ;
UtRegisterTest ( " DetectHttpClientBodyTest21 " , DetectHttpClientBodyTest21 , 1 ) ;
# endif /* UNITTESTS */
return ;
}