@ -567,60 +567,77 @@ int DetectPcreALDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *
if ( htp_state = = NULL ) {
SCLogDebug ( " No htp state, no match at http body data " ) ;
goto unlock ;
} else if ( htp_state - > body . nchunks = = 0 ) {
SCLogDebug ( " No body data to inspect " ) ;
goto unlock ;
} else {
pcreret = 0 ;
int wspace [ 255 ] ;
int flags = PCRE_PARTIAL ;
}
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 ;
HtpBodyChunk * cur = htp_state - > body . first ;
if ( cur = = NULL ) {
SCLogDebug ( " No body chunks to inspect " ) ;
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 body data to inspect " ) ;
goto unlock ;
}
htp_state - > body . pcre_flags | = HTP_PCRE_DONE ;
} else {
pcreret = 0 ;
int wspace [ 255 ] ;
int flags = PCRE_PARTIAL ;
while ( cur ! = NULL ) {
if ( SCLogDebugEnabled ( ) ) {
printf ( " \n " ) ;
PrintRawUriFp ( stdout , ( uint8_t * ) cur - > data , cur - > len ) ;
printf ( " \n " ) ;
if ( cur = = NULL ) {
SCLogDebug ( " No body chunks to inspect " ) ;
goto unlock ;
}
pcreret = pcre_dfa_exec ( pe - > re , NULL , ( char * ) cur - > data , cur - > len , 0 ,
flags | PCRE_DFA_SHORTEST , ov , MAX_SUBSTRINGS ,
wspace , MAX_SUBSTRINGS ) ;
cur = cur - > next ;
SCLogDebug ( " Pcre Ret %d " , pcreret ) ;
switch ( pcreret ) {
case PCRE_ERROR_PARTIAL :
/* make pcre to use the working space of the last partial
* match , ( match over multiple chunks )
*/
SCLogDebug ( " partial match " ) ;
flags | = PCRE_DFA_RESTART ;
htp_state - > body . pcre_flags | = HTP_PCRE_HAS_MATCH ;
break ;
case PCRE_ERROR_NOMATCH :
SCLogDebug ( " no match " ) ;
flags = PCRE_PARTIAL ;
break ;
case 0 :
SCLogDebug ( " Perfect Match! " ) ;
ret = 1 ;
goto unlock ;
break ;
default :
if ( pcreret > 0 ) {
SCLogDebug ( " Match with captured data " ) ;
htud - > body . pcre_flags | = HTP_PCRE_DONE ;
while ( cur ! = NULL ) {
if ( SCLogDebugEnabled ( ) ) {
printf ( " \n " ) ;
PrintRawUriFp ( stdout , ( uint8_t * ) cur - > data , cur - > len ) ;
printf ( " \n " ) ;
}
pcreret = pcre_dfa_exec ( pe - > re , NULL , ( char * ) cur - > data , cur - > len , 0 ,
flags | PCRE_DFA_SHORTEST , ov , MAX_SUBSTRINGS ,
wspace , MAX_SUBSTRINGS ) ;
cur = cur - > next ;
SCLogDebug ( " Pcre Ret %d " , pcreret ) ;
switch ( pcreret ) {
case PCRE_ERROR_PARTIAL :
/* make pcre to use the working space of the last partial
* match , ( match over multiple chunks )
*/
SCLogDebug ( " partial match " ) ;
flags | = PCRE_DFA_RESTART ;
htud - > body . pcre_flags | = HTP_PCRE_HAS_MATCH ;
break ;
case PCRE_ERROR_NOMATCH :
SCLogDebug ( " no match " ) ;
flags = PCRE_PARTIAL ;
break ;
case 0 :
SCLogDebug ( " Perfect Match! " ) ;
ret = 1 ;
} else {
SCLogDebug ( " No match, pcre failed " ) ;
ret = 0 ;
}
goto unlock ;
goto unlock ;
break ;
default :
if ( pcreret > 0 ) {
SCLogDebug ( " Match with captured data " ) ;
ret = 1 ;
} else {
SCLogDebug ( " No match, pcre failed " ) ;
ret = 0 ;
}
goto unlock ;
}
}
}
}
@ -2189,13 +2206,6 @@ static int DetectPcreModifPTest05(void) {
/* do detect for p1 */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf2 , httplen2 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
HtpState * http_state = f . aldata [ AlpGetStateIdx ( ALPROTO_HTTP ) ] ;
if ( http_state = = NULL ) {
printf ( " no http state: " ) ;
@ -2203,9 +2213,6 @@ static int DetectPcreModifPTest05(void) {
goto end ;
}
/* do detect for p2 */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
if ( ! ( PacketAlertCheck ( p1 , 1 ) ) ) {
printf ( " sid 1 didn't match on p1 but should have: " ) ;
goto end ;
@ -2217,6 +2224,16 @@ static int DetectPcreModifPTest05(void) {
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf2 , httplen2 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
/* do detect for p2 */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p2 ) ;
if ( ( PacketAlertCheck ( p2 , 1 ) ) ) {
printf ( " sid 1 did match on p2 but should have: " ) ;
goto end ;
@ -2842,6 +2859,572 @@ end:
return result ;
}
/** \test Test tracking of body chunks per transactions (on requests)
*/
static int DetectPcreTxBodyChunksTest01 ( void ) {
int result = 0 ;
Flow f ;
TcpSession ssn ;
Packet * p = NULL ;
uint8_t httpbuf1 [ ] = " GET / 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 ( & 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 ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
FlowL7DataPtrInit ( & f ) ;
AppLayerHtpEnableRequestBodyCallback ( ) ;
int r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER | STREAM_START , httpbuf1 , httplen1 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf2 , httplen2 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 2 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf3 , httplen3 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 3 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
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 ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf5 , httplen5 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 5 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf6 , httplen6 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 6 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
r = AppLayerParse ( & f , ALPROTO_HTTP , STREAM_TOSERVER , httpbuf7 , httplen7 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 7 returned % " PRId32 " , expected 0: " , r ) ;
goto end ;
}
/* Now we should have 2 transactions, each with it's own list
* of request body chunks ( let ' s test it ) */
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 ) ;
if ( htud = = NULL ) {
printf ( " No body data in t1 (it should be removed only when the tx is destroyed): " ) ;
goto end ;
}
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 ;
}
FlowL7DataPtrFree ( & f ) ;
result = 1 ;
end :
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePacket ( p ) ;
return result ;
}
/** \test test pcre P modifier with multiple pipelined http transactions */
static int DetectPcreTxBodyChunksTest02 ( 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 ;
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; pcre: \" /one/P \" ; 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; pcre: \" /two/P \" ; 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 ;
}
/** \test multiple http transactions and body chunks of request handling */
static int DetectPcreTxBodyChunksTest03 ( 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 ;
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; pcre: \" /one/P \" ; 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; pcre: \" /two/P \" ; 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 ;
}
# endif /* UNITTESTS */
/**
@ -2880,6 +3463,9 @@ void DetectPcreRegisterTests(void) {
UtRegisterTest ( " DetectPcreTestSig12 -- negated Method modifier " , DetectPcreTestSig12 , 1 ) ;
UtRegisterTest ( " DetectPcreTestSig13 -- Header modifier " , DetectPcreTestSig13 , 1 ) ;
UtRegisterTest ( " DetectPcreTestSig14 -- negated Header modifier " , DetectPcreTestSig14 , 1 ) ;
UtRegisterTest ( " DetectPcreTxBodyChunksTest01 " , DetectPcreTxBodyChunksTest01 , 1 ) ;
UtRegisterTest ( " DetectPcreTxBodyChunksTest02 -- modifier P, body chunks per tx " , DetectPcreTxBodyChunksTest02 , 1 ) ;
UtRegisterTest ( " DetectPcreTxBodyChunksTest03 -- modifier P, body chunks per tx " , DetectPcreTxBodyChunksTest03 , 1 ) ;
# endif /* UNITTESTS */
}