@ -56,6 +56,9 @@
# include "app-layer-htp.h"
# include "app-layer-protos.h"
# include "conf.h"
# include "conf-yaml-loader.h"
# define BUFFER_STEP 50
static inline int HSBDCreateSpace ( DetectEngineThreadCtx * det_ctx , uint16_t size )
@ -84,11 +87,13 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
DetectEngineThreadCtx * det_ctx ,
Flow * f , HtpState * htp_state ,
uint8_t flags ,
uint32_t * buffer_len )
uint32_t * buffer_len ,
uint32_t * stream_start_offset )
{
int index = 0 ;
uint8_t * buffer = NULL ;
* buffer_len = 0 ;
* stream_start_offset = 0 ;
if ( det_ctx - > hsbd_buffers_list_len = = 0 ) {
if ( HSBDCreateSpace ( det_ctx , 1 ) < 0 )
@ -103,6 +108,7 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
if ( ( tx_id - det_ctx - > hsbd_start_tx_id ) < det_ctx - > hsbd_buffers_list_len ) {
if ( det_ctx - > hsbd [ ( tx_id - det_ctx - > hsbd_start_tx_id ) ] . buffer_len ! = 0 ) {
* buffer_len = det_ctx - > hsbd [ ( tx_id - det_ctx - > hsbd_start_tx_id ) ] . buffer_len ;
* stream_start_offset = det_ctx - > hsbd [ ( tx_id - det_ctx - > hsbd_start_tx_id ) ] . offset ;
return det_ctx - > hsbd [ ( tx_id - det_ctx - > hsbd_start_tx_id ) ] . buffer ;
}
} else {
@ -217,6 +223,7 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id,
buffer = det_ctx - > hsbd [ index ] . buffer ;
* buffer_len = det_ctx - > hsbd [ index ] . buffer_len ;
* stream_start_offset = det_ctx - > hsbd [ index ] . offset ;
end :
return buffer ;
}
@ -228,11 +235,13 @@ int DetectEngineRunHttpServerBodyMpm(DetectEngineCtx *de_ctx,
{
uint32_t cnt = 0 ;
uint32_t buffer_len = 0 ;
uint32_t stream_start_offset = 0 ;
uint8_t * buffer = DetectEngineHSBDGetBufferForTX ( tx , idx ,
de_ctx , det_ctx ,
f , htp_state ,
flags ,
& buffer_len ) ;
& buffer_len ,
& stream_start_offset ) ;
if ( buffer_len = = 0 )
goto end ;
@ -251,11 +260,13 @@ int DetectEngineInspectHttpServerBody(ThreadVars *tv,
{
HtpState * htp_state = ( HtpState * ) alstate ;
uint32_t buffer_len = 0 ;
uint32_t stream_start_offset = 0 ;
uint8_t * buffer = DetectEngineHSBDGetBufferForTX ( tx , tx_id ,
de_ctx , det_ctx ,
f , htp_state ,
flags ,
& buffer_len ) ;
& buffer_len ,
& stream_start_offset ) ;
if ( buffer_len = = 0 )
goto end ;
@ -266,6 +277,7 @@ int DetectEngineInspectHttpServerBody(ThreadVars *tv,
f ,
buffer ,
buffer_len ,
stream_start_offset ,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSBD , NULL ) ;
if ( r = = 1 )
return DETECT_ENGINE_INSPECT_SIG_MATCH ;
@ -2067,6 +2079,330 @@ end:
return result ;
}
static int DetectEngineHttpServerBodyTest16 ( void )
{
char input [ ] = " \
% YAML 1.1 \ n \
- - - \ n \
libhtp : \ n \
\ n \
default - config : \ n \
personality : IDS \ n \
request - body - limit : 0 \ n \
response - body - limit : 0 \ n \
\ n \
request - body - inspect - window : 0 \ n \
response - body - inspect - window : 0 \ n \
request - body - minimal - inspect - size : 0 \ n \
response - body - minimal - inspect - size : 0 \ n \
" ;
ConfCreateContextBackup ( ) ;
ConfInit ( ) ;
HtpConfigCreateBackup ( ) ;
ConfYamlLoadString ( input , strlen ( input ) ) ;
HTPConfigure ( ) ;
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 ;
int result = 0 ;
uint8_t http_buf1 [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" \r \n " ;
uint32_t http_len1 = sizeof ( http_buf1 ) - 1 ;
uint8_t http_buf2 [ ] =
" HTTP/1.0 200 ok \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 17 \r \n "
" \r \n "
" 1234567 " ;
uint32_t http_len2 = sizeof ( http_buf2 ) - 1 ;
uint8_t http_buf3 [ ] =
" 8901234ABC " ;
uint32_t http_len3 = sizeof ( http_buf3 ) - 1 ;
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 . flags | = FLOW_IPV4 ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW | PKT_STREAM_EST ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOCLIENT ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW | PKT_STREAM_EST ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http server body test \" ; "
" content: \" 890 \" ; within:3; http_server_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 ( NULL , & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf1 , http_len1 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . alstate ;
if ( http_state = = NULL ) {
printf ( " no http state: \n " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( PacketAlertCheck ( p1 , 1 ) ) {
printf ( " sid 1 matched but shouldn't have \n " ) ;
goto end ;
}
r = AppLayerParse ( NULL , & f , ALPROTO_HTTP , STREAM_TOCLIENT , http_buf2 , http_len2 ) ;
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 matched but shouldn't have \n " ) ;
goto end ;
}
r = AppLayerParse ( NULL , & f , ALPROTO_HTTP , STREAM_TOCLIENT , http_buf3 , http_len3 ) ;
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 matched but shouldn't have \n " ) ;
goto end ;
}
result = 1 ;
end :
HtpConfigRestoreBackup ( ) ;
ConfRestoreContextBackup ( ) ;
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
static int DetectEngineHttpServerBodyTest17 ( void )
{
char input [ ] = " \
% YAML 1.1 \ n \
- - - \ n \
libhtp : \ n \
\ n \
default - config : \ n \
personality : IDS \ n \
request - body - limit : 0 \ n \
response - body - limit : 0 \ n \
\ n \
request - body - inspect - window : 0 \ n \
response - body - inspect - window : 0 \ n \
request - body - minimal - inspect - size : 0 \ n \
response - body - minimal - inspect - size : 0 \ n \
" ;
ConfCreateContextBackup ( ) ;
ConfInit ( ) ;
HtpConfigCreateBackup ( ) ;
ConfYamlLoadString ( input , strlen ( input ) ) ;
HTPConfigure ( ) ;
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 ;
int result = 0 ;
uint8_t http_buf1 [ ] =
" GET /index.html HTTP/1.0 \r \n "
" Host: www.openinfosecfoundation.org \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 \r \n "
" \r \n " ;
uint32_t http_len1 = sizeof ( http_buf1 ) - 1 ;
uint8_t http_buf2 [ ] =
" HTTP/1.0 200 ok \r \n "
" Content-Type: text/html \r \n "
" Content-Length: 17 \r \n "
" \r \n "
" 1234567 " ;
uint32_t http_len2 = sizeof ( http_buf2 ) - 1 ;
uint8_t http_buf3 [ ] =
" 8901234ABC " ;
uint32_t http_len3 = sizeof ( http_buf3 ) - 1 ;
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 . flags | = FLOW_IPV4 ;
p1 - > flow = & f ;
p1 - > flowflags | = FLOW_PKT_TOSERVER ;
p1 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p1 - > flags | = PKT_HAS_FLOW | PKT_STREAM_EST ;
p2 - > flow = & f ;
p2 - > flowflags | = FLOW_PKT_TOCLIENT ;
p2 - > flowflags | = FLOW_PKT_ESTABLISHED ;
p2 - > flags | = PKT_HAS_FLOW | PKT_STREAM_EST ;
f . alproto = ALPROTO_HTTP ;
StreamTcpInitConfig ( TRUE ) ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , " alert http any any -> any any "
" (msg: \" http server body test \" ; "
" content: \" 890 \" ; depth:3; http_server_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 ( NULL , & f , ALPROTO_HTTP , STREAM_TOSERVER , http_buf1 , http_len1 ) ;
if ( r ! = 0 ) {
printf ( " toserver chunk 1 returned % " PRId32 " , expected 0: " , r ) ;
result = 0 ;
goto end ;
}
http_state = f . alstate ;
if ( http_state = = NULL ) {
printf ( " no http state: \n " ) ;
result = 0 ;
goto end ;
}
/* do detect */
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p1 ) ;
if ( PacketAlertCheck ( p1 , 1 ) ) {
printf ( " sid 1 matched but shouldn't have \n " ) ;
goto end ;
}
r = AppLayerParse ( NULL , & f , ALPROTO_HTTP , STREAM_TOCLIENT , http_buf2 , http_len2 ) ;
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 matched but shouldn't have \n " ) ;
goto end ;
}
r = AppLayerParse ( NULL , & f , ALPROTO_HTTP , STREAM_TOCLIENT , http_buf3 , http_len3 ) ;
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 matched but shouldn't have \n " ) ;
goto end ;
}
result = 1 ;
end :
HtpConfigRestoreBackup ( ) ;
ConfRestoreContextBackup ( ) ;
if ( de_ctx ! = NULL )
SigGroupCleanup ( de_ctx ) ;
if ( de_ctx ! = NULL )
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
StreamTcpFreeConfig ( TRUE ) ;
FLOW_DESTROY ( & f ) ;
UTHFreePackets ( & p1 , 1 ) ;
UTHFreePackets ( & p2 , 1 ) ;
return result ;
}
static int DetectEngineHttpServerBodyFileDataTest01 ( void )
{
TcpSession ssn ;
@ -2341,6 +2677,10 @@ void DetectEngineHttpServerBodyRegisterTests(void)
DetectEngineHttpServerBodyTest14 , 1 ) ;
UtRegisterTest ( " DetectEngineHttpServerBodyTest15 " ,
DetectEngineHttpServerBodyTest15 , 1 ) ;
UtRegisterTest ( " DetectEngineHttpServerBodyTest16 " ,
DetectEngineHttpServerBodyTest16 , 1 ) ;
UtRegisterTest ( " DetectEngineHttpServerBodyTest17 " ,
DetectEngineHttpServerBodyTest17 , 1 ) ;
UtRegisterTest ( " DetectEngineHttpServerBodyFileDataTest01 " ,
DetectEngineHttpServerBodyFileDataTest01 , 1 ) ;