/* Copyright (C) 2007-2022 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 Victor Julien < victor @ inliniac . net >
*
* Simple content match part of the detection engine .
*/
# include "suricata-common.h"
# include "decode.h"
# include "detect.h"
# include "detect-content.h"
# include "detect-uricontent.h"
# include "detect-engine-mpm.h"
# include "detect-engine.h"
# include "detect-engine-build.h"
# include "detect-engine-state.h"
# include "detect-parse.h"
# include "detect-pcre.h"
# include "util-mpm.h"
# include "flow.h"
# include "flow-util.h"
# include "flow-var.h"
# include "detect-flow.h"
# include "app-layer.h"
# include "util-unittest.h"
# include "util-print.h"
# include "util-debug.h"
# include "util-spm.h"
# include "threads.h"
# include "util-unittest-helper.h"
# include "pkt-var.h"
# include "host.h"
# include "util-profiling.h"
# include "detect-dsize.h"
# ifdef UNITTESTS
static void DetectContentRegisterTests ( void ) ;
# endif
void DetectContentRegister ( void )
{
sigmatch_table [ DETECT_CONTENT ] . name = " content " ;
sigmatch_table [ DETECT_CONTENT ] . desc = " match on payload content " ;
sigmatch_table [ DETECT_CONTENT ] . url = " /rules/payload-keywords.html#content " ;
sigmatch_table [ DETECT_CONTENT ] . Match = NULL ;
sigmatch_table [ DETECT_CONTENT ] . Setup = DetectContentSetup ;
sigmatch_table [ DETECT_CONTENT ] . Free = DetectContentFree ;
# ifdef UNITTESTS
sigmatch_table [ DETECT_CONTENT ] . RegisterTests = DetectContentRegisterTests ;
# endif
sigmatch_table [ DETECT_CONTENT ] . flags = ( SIGMATCH_QUOTES_MANDATORY | SIGMATCH_HANDLE_NEGATION ) ;
}
/**
* \ brief Parse a content string , ie " abc|DE|fgh "
*
* \ param content_str null terminated string containing the content
* \ param result result pointer to pass the fully parsed byte array
* \ param result_len size of the resulted data
* \ param flags flags to be set by this parsing function
*
* \ retval - 1 error
* \ retval 0 ok
*/
int DetectContentDataParse ( const char * keyword , const char * contentstr ,
uint8_t * * pstr , uint16_t * plen )
{
char * str = NULL ;
size_t slen = 0 ;
slen = strlen ( contentstr ) ;
if ( slen = = 0 ) {
return - 1 ;
}
uint8_t buffer [ slen + 1 ] ;
strlcpy ( ( char * ) & buffer , contentstr , slen + 1 ) ;
str = ( char * ) buffer ;
SCLogDebug ( " \" %s \" , len % " PRIuMAX , str , ( uintmax_t ) slen ) ;
//SCLogDebug("DetectContentParse: \"%s\", len %" PRIu32 "", str, len);
char converted = 0 ;
{
size_t i , x ;
uint8_t bin = 0 ;
uint8_t escape = 0 ;
uint8_t binstr [ 3 ] = " " ;
uint8_t binpos = 0 ;
uint16_t bin_count = 0 ;
for ( i = 0 , x = 0 ; i < slen ; i + + ) {
// SCLogDebug("str[%02u]: %c", i, str[i]);
if ( str [ i ] = = ' | ' ) {
bin_count + + ;
if ( bin ) {
if ( binpos > 0 ) {
SCLogError ( " Incomplete hex code in content - %s. Invalidating signature. " ,
contentstr ) ;
goto error ;
}
bin = 0 ;
} else {
bin = 1 ;
}
} else if ( ! escape & & str [ i ] = = ' \\ ' ) {
escape = 1 ;
} else {
if ( bin ) {
if ( isdigit ( ( unsigned char ) str [ i ] ) | |
str [ i ] = = ' A ' | | str [ i ] = = ' a ' | |
str [ i ] = = ' B ' | | str [ i ] = = ' b ' | |
str [ i ] = = ' C ' | | str [ i ] = = ' c ' | |
str [ i ] = = ' D ' | | str [ i ] = = ' d ' | |
str [ i ] = = ' E ' | | str [ i ] = = ' e ' | |
str [ i ] = = ' F ' | | str [ i ] = = ' f ' )
{
// SCLogDebug("part of binary: %c", str[i]);
binstr [ binpos ] = ( char ) str [ i ] ;
binpos + + ;
if ( binpos = = 2 ) {
uint8_t c = strtol ( ( char * ) binstr , ( char * * ) NULL , 16 ) & 0xFF ;
binpos = 0 ;
str [ x ] = c ;
x + + ;
converted = 1 ;
}
} else if ( str [ i ] = = ' ' ) {
// SCLogDebug("space as part of binary string");
}
else if ( str [ i ] ! = ' , ' ) {
SCLogError ( " Invalid hex code in "
" content - %s, hex %c. Invalidating signature. " ,
contentstr , str [ i ] ) ;
goto error ;
}
} else if ( escape ) {
if ( str [ i ] = = ' : ' | |
str [ i ] = = ' ; ' | |
str [ i ] = = ' \\ ' | |
str [ i ] = = ' \" ' )
{
str [ x ] = str [ i ] ;
x + + ;
} else {
SCLogError ( " '%c' has to be escaped " , str [ i - 1 ] ) ;
goto error ;
}
escape = 0 ;
converted = 1 ;
} else if ( str [ i ] = = ' " ' ) {
SCLogError ( " Invalid unescaped double quote within content section. " ) ;
goto error ;
} else {
str [ x ] = str [ i ] ;
x + + ;
}
}
}
if ( bin_count % 2 ! = 0 ) {
SCLogError ( " Invalid hex code assembly in "
" %s - %s. Invalidating signature. " ,
keyword , contentstr ) ;
goto error ;
}
if ( converted ) {
slen = x ;
}
}
if ( slen ) {
uint8_t * ptr = SCCalloc ( 1 , slen ) ;
if ( ptr = = NULL ) {
return - 1 ;
}
memcpy ( ptr , str , slen ) ;
* plen = ( uint16_t ) slen ;
* pstr = ptr ;
return 0 ;
}
error :
return - 1 ;
}
/**
* \ brief DetectContentParse
* \ initonly
*/
DetectContentData * DetectContentParse ( SpmGlobalThreadCtx * spm_global_thread_ctx ,
const char * contentstr )
{
DetectContentData * cd = NULL ;
uint8_t * content = NULL ;
uint16_t len = 0 ;
int ret ;
ret = DetectContentDataParse ( " content " , contentstr , & content , & len ) ;
if ( ret = = - 1 ) {
return NULL ;
}
cd = SCCalloc ( 1 , sizeof ( DetectContentData ) + len ) ;
if ( unlikely ( cd = = NULL ) ) {
SCFree ( content ) ;
exit ( EXIT_FAILURE ) ;
}
cd - > content = ( uint8_t * ) cd + sizeof ( DetectContentData ) ;
memcpy ( cd - > content , content , len ) ;
cd - > content_len = len ;
/* Prepare SPM search context. */
cd - > spm_ctx = SpmInitCtx ( cd - > content , cd - > content_len , 0 ,
spm_global_thread_ctx ) ;
if ( cd - > spm_ctx = = NULL ) {
SCFree ( content ) ;
SCFree ( cd ) ;
return NULL ;
}
cd - > depth = 0 ;
cd - > offset = 0 ;
cd - > within = 0 ;
cd - > distance = 0 ;
SCFree ( content ) ;
return cd ;
}
DetectContentData * DetectContentParseEncloseQuotes ( SpmGlobalThreadCtx * spm_global_thread_ctx ,
const char * contentstr )
{
return DetectContentParse ( spm_global_thread_ctx , contentstr ) ;
}
/**
* \ brief Helper function to print a DetectContentData
*/
void DetectContentPrint ( DetectContentData * cd )
{
int i = 0 ;
if ( cd = = NULL ) {
SCLogDebug ( " DetectContentData \" cd \" is NULL " ) ;
return ;
}
char * tmpstr = SCMalloc ( sizeof ( char ) * cd - > content_len + 1 ) ;
if ( tmpstr ! = NULL ) {
for ( i = 0 ; i < cd - > content_len ; i + + ) {
if ( isprint ( cd - > content [ i ] ) )
tmpstr [ i ] = cd - > content [ i ] ;
else
tmpstr [ i ] = ' . ' ;
}
tmpstr [ i ] = ' \0 ' ;
SCLogDebug ( " Content: \" %s \" " , tmpstr ) ;
SCFree ( tmpstr ) ;
} else {
SCLogDebug ( " Content: " ) ;
for ( i = 0 ; i < cd - > content_len ; i + + )
SCLogDebug ( " %c " , cd - > content [ i ] ) ;
}
SCLogDebug ( " Content_id: % " PRIu32 , cd - > id ) ;
SCLogDebug ( " Content_len: % " PRIu16 , cd - > content_len ) ;
SCLogDebug ( " Depth: % " PRIu16 , cd - > depth ) ;
SCLogDebug ( " Offset: % " PRIu16 , cd - > offset ) ;
SCLogDebug ( " Within: % " PRIi32 , cd - > within ) ;
SCLogDebug ( " Distance: % " PRIi32 , cd - > distance ) ;
SCLogDebug ( " flags: %u " , cd - > flags ) ;
SCLogDebug ( " negated: %s " , cd - > flags & DETECT_CONTENT_NEGATED ? " true " : " false " ) ;
SCLogDebug ( " relative match next: %s " , cd - > flags & DETECT_CONTENT_RELATIVE_NEXT ? " true " : " false " ) ;
if ( cd - > replace & & cd - > replace_len ) {
char * tmprstr = SCMalloc ( sizeof ( char ) * cd - > replace_len + 1 ) ;
if ( tmprstr ! = NULL ) {
for ( i = 0 ; i < cd - > replace_len ; i + + ) {
if ( isprint ( cd - > replace [ i ] ) )
tmprstr [ i ] = cd - > replace [ i ] ;
else
tmprstr [ i ] = ' . ' ;
}
tmprstr [ i ] = ' \0 ' ;
SCLogDebug ( " Replace: \" %s \" " , tmprstr ) ;
SCFree ( tmprstr ) ;
} else {
SCLogDebug ( " Replace: " ) ;
for ( i = 0 ; i < cd - > replace_len ; i + + )
SCLogDebug ( " %c " , cd - > replace [ i ] ) ;
}
}
SCLogDebug ( " ----------- " ) ;
}
/**
* \ brief Function to setup a content pattern .
*
* \ param de_ctx pointer to the current detection_engine
* \ param s pointer to the current Signature
* \ param m pointer to the last parsed SigMatch
* \ param contentstr pointer to the current keyword content string
* \ retval - 1 if error
* \ retval 0 if all was ok
*/
int DetectContentSetup ( DetectEngineCtx * de_ctx , Signature * s , const char * contentstr )
{
DetectContentData * cd = DetectContentParse ( de_ctx - > spm_global_thread_ctx , contentstr ) ;
if ( cd = = NULL )
goto error ;
if ( s - > init_data - > negated = = true ) {
cd - > flags | = DETECT_CONTENT_NEGATED ;
}
DetectContentPrint ( cd ) ;
if ( DetectBufferGetActiveList ( de_ctx , s ) = = - 1 )
goto error ;
int sm_list = s - > init_data - > list ;
if ( sm_list = = DETECT_SM_LIST_NOTSET ) {
sm_list = DETECT_SM_LIST_PMATCH ;
} else if ( sm_list > DETECT_SM_LIST_MAX & &
0 = = ( cd - > flags & DETECT_CONTENT_NEGATED ) ) {
/* Check transform compatibility */
const char * tstr ;
if ( ! DetectEngineBufferTypeValidateTransform (
de_ctx , sm_list , cd - > content , cd - > content_len , & tstr ) ) {
SCLogError ( " content string \" %s \" incompatible with %s transform " , contentstr , tstr ) ;
goto error ;
}
}
if ( SigMatchAppendSMToList ( de_ctx , s , DETECT_CONTENT , ( SigMatchCtx * ) cd , sm_list ) = = NULL ) {
goto error ;
}
return 0 ;
error :
DetectContentFree ( de_ctx , cd ) ;
return - 1 ;
}
/**
* \ brief this function will SCFree memory associated with DetectContentData
*
* \ param cd pointer to DetectContentData
*/
void DetectContentFree ( DetectEngineCtx * de_ctx , void * ptr )
{
SCEnter ( ) ;
DetectContentData * cd = ( DetectContentData * ) ptr ;
if ( cd = = NULL )
SCReturn ;
SpmDestroyCtx ( cd - > spm_ctx ) ;
SCFree ( cd ) ;
SCReturn ;
}
/**
* \ brief Determine the size needed to accommodate the content
* elements of a signature
* \ param s signature to get dsize value from
* \ param max_size Maximum buffer / data size allowed .
* \ param list signature match list .
* \ param len Maximum length required
* \ param offset Maximum offset encountered
*
* Note that negated content does not contribute to the maximum
* required size value . However , each negated content ' s values
* must not exceed the size value .
*
* Values from negated content blocks are used to determine if the
* negated content block requires a value that exceeds " max_size " . The
* distance and within values from negated content blocks are added to
* the running total of required content size to see if the max_size
* would be exceeded .
*
* - Non - negated content contributes to the required size ( content length , distance )
* - Negated content values are checked but not accumulated for the required size .
*/
void SigParseRequiredContentSize (
const Signature * s , const int max_size , const SigMatch * sm , int * len , int * offset )
{
int max_offset = 0 , total_len = 0 ;
bool first = true ;
for ( ; sm ! = NULL ; sm = sm - > next ) {
if ( sm - > type ! = DETECT_CONTENT | | sm - > ctx = = NULL ) {
continue ;
}
DetectContentData * cd = ( DetectContentData * ) sm - > ctx ;
SCLogDebug ( " content_len %d; negated: %s; distance: %d, offset: %d, depth: %d " ,
cd - > content_len , cd - > flags & DETECT_CONTENT_NEGATED ? " yes " : " no " , cd - > distance ,
cd - > offset , cd - > depth ) ;
if ( ! first ) {
/* only count content with relative modifiers */
if ( ! ( ( cd - > flags & DETECT_CONTENT_DISTANCE ) | | ( cd - > flags & DETECT_CONTENT_WITHIN ) ) )
continue ;
if ( cd - > flags & DETECT_CONTENT_NEGATED ) {
/* Check if distance/within cause max to be exceeded */
int check = total_len + cd - > distance + cd - > within ;
if ( max_size < check ) {
* len = check ;
return ;
}
continue ;
}
}
SCLogDebug ( " content_len %d; distance: %d, offset: %d, depth: %d " , cd - > content_len ,
cd - > distance , cd - > offset , cd - > depth ) ;
total_len + = cd - > content_len + cd - > distance ;
max_offset = MAX ( max_offset , cd - > offset ) ;
first = false ;
}
* len = total_len ;
* offset = max_offset ;
}
/**
* \ retval true valid
* \ retval false invalid
*/
bool DetectContentPMATCHValidateCallback ( const Signature * s )
{
if ( ! ( s - > flags & SIG_FLAG_DSIZE ) ) {
return true ;
}
int max_right_edge_i = SigParseGetMaxDsize ( s ) ;
if ( max_right_edge_i < 0 ) {
return true ;
}
uint32_t max_right_edge = ( uint32_t ) max_right_edge_i ;
int min_dsize_required = SigParseMaxRequiredDsize ( s ) ;
if ( min_dsize_required > = 0 ) {
SCLogDebug ( " min_dsize %d; max_right_edge %d " , min_dsize_required , max_right_edge ) ;
if ( ( uint32_t ) min_dsize_required > max_right_edge ) {
SCLogError ( " signature can't match as required content length %d exceeds dsize value %d " ,
min_dsize_required , max_right_edge ) ;
return false ;
}
}
return true ;
}
/** \brief apply depth/offset and distance/within to content matches
*
* The idea is that any limitation we can set is a win , as the mpm
* can use this to reduce match candidates .
*
* E . g . if we have ' content : " 1 " ; depth : 1 ; content : " 2 " ; distance : 0 ; within : 1 ; '
* we know that we can add ' offset : 1 ; depth : 2 ; ' to the 2 nd condition . This
* will then be used in mpm if the 2 nd condition would be selected for mpm .
*
* Another example : ' content : " 1 " ; depth : 1 ; content : " 2 " ; distance : 0 ; ' . Here we
* cannot set a depth , but we can set an offset of ' offset : 1 ; ' . This will
* make the mpm a bit more precise .
*/
static void PropagateLimits ( Signature * s , SigMatch * sm_head )
{
# define VALIDATE(e) \
if ( ! ( e ) ) { \
return ; \
}
uint16_t offset = 0 ;
uint16_t offset_plus_pat = 0 ;
uint16_t depth = 0 ;
bool has_active_depth_chain = false ;
bool has_depth = false ;
bool has_ends_with = false ;
uint16_t ends_with_depth = 0 ;
for ( SigMatch * sm = sm_head ; sm ! = NULL ; sm = sm - > next ) {
switch ( sm - > type ) {
case DETECT_CONTENT : {
DetectContentData * cd = ( DetectContentData * ) sm - > ctx ;
if ( ( cd - > flags & ( DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE ) ) = = 0 ) {
offset = depth = 0 ;
offset_plus_pat = cd - > content_len ;
SCLogDebug ( " reset " ) ;
has_active_depth_chain = false ;
continue ;
}
if ( sm - > prev = = NULL ) {
if ( cd - > distance > = 0 & & cd - > distance < = ( int32_t ) USHRT_MAX & &
cd - > within > = 0 & & cd - > within < = ( int32_t ) USHRT_MAX ) {
if ( cd - > flags & DETECT_CONTENT_DISTANCE ) {
if ( cd - > distance > 0 )
cd - > flags | = DETECT_CONTENT_OFFSET ;
cd - > flags & = ~ DETECT_CONTENT_DISTANCE ;
cd - > offset = ( uint16_t ) cd - > distance ;
cd - > distance = 0 ;
cd - > flags | = DETECT_CONTENT_DISTANCE2OFFSET ;
}
if ( cd - > flags & DETECT_CONTENT_WITHIN ) {
cd - > flags | = DETECT_CONTENT_DEPTH ;
cd - > flags & = ~ DETECT_CONTENT_WITHIN ;
cd - > depth = ( uint16_t ) cd - > within + cd - > offset ;
cd - > within = 0 ;
cd - > flags | = DETECT_CONTENT_WITHIN2DEPTH ;
}
}
}
if ( cd - > flags & DETECT_CONTENT_NEGATED ) {
offset = depth = 0 ;
offset_plus_pat = 0 ;
SCLogDebug ( " reset because of negation " ) ;
has_active_depth_chain = false ;
continue ;
}
if ( cd - > depth ) {
has_depth = true ;
has_active_depth_chain = true ;
}
SCLogDebug ( " sm %p depth %u offset %u distance %d within %d " , sm , cd - > depth ,
cd - > offset , cd - > distance , cd - > within ) ;
SCLogDebug ( " stored: offset %u depth %u offset_plus_pat %u " , offset , depth ,
offset_plus_pat ) ;
if ( ( cd - > flags & ( DETECT_DEPTH | DETECT_CONTENT_WITHIN ) ) = = 0 ) {
if ( depth )
SCLogDebug ( " no within, reset depth " ) ;
depth = 0 ;
has_active_depth_chain = false ;
}
if ( ( cd - > flags & DETECT_CONTENT_DISTANCE ) = = 0 ) {
if ( offset_plus_pat )
SCLogDebug ( " no distance, reset offset_plus_pat & offset " ) ;
offset_plus_pat = offset = 0 ;
}
SCLogDebug ( " stored: offset %u depth %u offset_plus_pat %u "
" has_active_depth_chain %s " ,
offset , depth , offset_plus_pat , has_active_depth_chain ? " true " : " false " ) ;
if ( cd - > flags & DETECT_CONTENT_DISTANCE ) {
if ( cd - > distance > = 0 ) {
VALIDATE ( ( uint32_t ) offset_plus_pat + cd - > distance < = UINT16_MAX ) ;
offset = cd - > offset = ( uint16_t ) ( offset_plus_pat + cd - > distance ) ;
SCLogDebug ( " distance %d: updated content to have offset %u " , cd - > distance ,
cd - > offset ) ;
} else {
if ( abs ( cd - > distance ) > offset_plus_pat )
offset = cd - > offset = 0 ;
else
offset = cd - > offset = ( uint16_t ) ( offset_plus_pat + cd - > distance ) ;
offset_plus_pat = offset + cd - > content_len ;
SCLogDebug ( " distance %d: updated content to have offset %u " , cd - > distance ,
cd - > offset ) ;
}
}
if ( has_active_depth_chain ) {
if ( offset_plus_pat & & cd - > flags & DETECT_CONTENT_WITHIN & & cd - > within > = 0 ) {
if ( depth & & depth > offset_plus_pat ) {
int32_t dist = 0 ;
if ( cd - > flags & DETECT_CONTENT_DISTANCE & & cd - > distance > 0 ) {
dist = cd - > distance ;
SCLogDebug (
" distance to add: %u. depth + dist %u " , dist , depth + dist ) ;
}
SCLogDebug ( " depth %u + cd->within %u " , depth , cd - > within ) ;
VALIDATE ( depth + cd - > within + dist > = 0 & &
depth + cd - > within + dist < = UINT16_MAX ) ;
depth = cd - > depth = ( uint16_t ) ( depth + cd - > within + dist ) ;
} else {
SCLogDebug ( " offset %u + cd->within %u " , offset , cd - > within ) ;
VALIDATE ( depth + cd - > within > = 0 & & depth + cd - > within < = UINT16_MAX ) ;
depth = cd - > depth = ( uint16_t ) ( offset + cd - > within ) ;
}
SCLogDebug ( " updated content to have depth %u " , cd - > depth ) ;
} else {
if ( cd - > depth = = 0 & & depth ! = 0 ) {
if ( cd - > within > 0 ) {
SCLogDebug ( " within %d distance %d " , cd - > within , cd - > distance ) ;
if ( cd - > flags & DETECT_CONTENT_DISTANCE & & cd - > distance > = 0 ) {
VALIDATE ( offset_plus_pat + cd - > distance > = 0 & &
offset_plus_pat + cd - > distance < = UINT16_MAX ) ;
cd - > offset = ( uint16_t ) ( offset_plus_pat + cd - > distance ) ;
SCLogDebug ( " updated content to have offset %u " , cd - > offset ) ;
}
VALIDATE ( depth + cd - > within > = 0 & &
depth + cd - > within < = UINT16_MAX ) ;
depth = cd - > depth = ( uint16_t ) ( cd - > within + depth ) ;
SCLogDebug ( " updated content to have depth %u " , cd - > depth ) ;
if ( cd - > flags & DETECT_CONTENT_ENDS_WITH ) {
has_ends_with = true ;
if ( ends_with_depth = = 0 )
ends_with_depth = depth ;
ends_with_depth = MIN ( ends_with_depth , depth ) ;
}
}
}
}
}
if ( cd - > offset = = 0 ) { // && offset != 0) {
if ( cd - > flags & DETECT_CONTENT_DISTANCE & & cd - > distance > = 0 ) {
cd - > offset = offset_plus_pat ;
SCLogDebug ( " update content to have offset %u " , cd - > offset ) ;
}
}
if ( ( cd - > flags & ( DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE ) ) = =
( DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN ) | |
( cd - > flags & ( DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE ) ) = =
( DETECT_CONTENT_DISTANCE ) ) {
if ( cd - > distance > = 0 ) {
// only distance
VALIDATE ( ( uint32_t ) offset_plus_pat + cd - > distance < = UINT16_MAX ) ;
offset = cd - > offset = ( uint16_t ) ( offset_plus_pat + cd - > distance ) ;
offset_plus_pat = offset + cd - > content_len ;
SCLogDebug ( " offset %u offset_plus_pat %u " , offset , offset_plus_pat ) ;
}
}
if ( cd - > flags & DETECT_CONTENT_OFFSET ) {
offset = cd - > offset ;
offset_plus_pat = offset + cd - > content_len ;
SCLogDebug ( " stored offset %u offset_plus_pat %u " , offset , offset_plus_pat ) ;
}
if ( cd - > depth ) {
depth = cd - > depth ;
SCLogDebug ( " stored depth now %u " , depth ) ;
offset_plus_pat = offset + cd - > content_len ;
if ( cd - > flags & DETECT_CONTENT_ENDS_WITH ) {
has_ends_with = true ;
if ( ends_with_depth = = 0 )
ends_with_depth = depth ;
ends_with_depth = MIN ( ends_with_depth , depth ) ;
}
}
if ( ( cd - > flags & ( DETECT_CONTENT_WITHIN | DETECT_CONTENT_DEPTH ) ) = = 0 ) {
has_active_depth_chain = false ;
depth = 0 ;
}
break ;
}
case DETECT_PCRE : {
// relative could leave offset_plus_pat set.
const DetectPcreData * pd = ( const DetectPcreData * ) sm - > ctx ;
if ( pd - > flags & DETECT_PCRE_RELATIVE ) {
depth = 0 ;
} else {
SCLogDebug ( " non-anchored PCRE not supported, reset offset_plus_pat & offset " ) ;
offset_plus_pat = offset = depth = 0 ;
}
has_active_depth_chain = false ;
break ;
}
default :
SCLogDebug ( " keyword not supported, reset offset_plus_pat & offset " ) ;
offset_plus_pat = offset = depth = 0 ;
has_active_depth_chain = false ;
break ;
}
}
/* apply anchored 'ends with' as depth to all patterns */
if ( has_depth & & has_ends_with ) {
for ( SigMatch * sm = sm_head ; sm ! = NULL ; sm = sm - > next ) {
switch ( sm - > type ) {
case DETECT_CONTENT : {
DetectContentData * cd = ( DetectContentData * ) sm - > ctx ;
if ( cd - > depth = = 0 )
cd - > depth = ends_with_depth ;
cd - > depth = MIN ( ends_with_depth , cd - > depth ) ;
if ( cd - > depth )
cd - > flags | = DETECT_CONTENT_DEPTH ;
break ;
}
}
}
}
# undef VALIDATE
}
void DetectContentPropagateLimits ( Signature * s )
{
PropagateLimits ( s , s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] ) ;
for ( uint32_t x = 0 ; x < s - > init_data - > buffer_index ; x + + ) {
PropagateLimits ( s , s - > init_data - > buffers [ x ] . head ) ;
}
}
static inline bool NeedsAsHex ( uint8_t c )
{
if ( ! isprint ( c ) )
return true ;
switch ( c ) {
case ' / ' :
case ' ; ' :
case ' : ' :
case ' \\ ' :
case ' ' :
case ' | ' :
case ' " ' :
case ' ` ' :
case ' \' ' :
return true ;
}
return false ;
}
void DetectContentPatternPrettyPrint ( const DetectContentData * cd , char * str , size_t str_len )
{
bool hex = false ;
for ( uint16_t i = 0 ; i < cd - > content_len ; i + + ) {
if ( NeedsAsHex ( cd - > content [ i ] ) ) {
char hex_str [ 4 ] ;
snprintf ( hex_str , sizeof ( hex_str ) , " %s%02X " , ! hex ? " | " : " " , cd - > content [ i ] ) ;
strlcat ( str , hex_str , str_len ) ;
hex = true ;
} else {
char p_str [ 3 ] ;
snprintf ( p_str , sizeof ( p_str ) , " %s%c " , hex ? " | " : " " , cd - > content [ i ] ) ;
strlcat ( str , p_str , str_len ) ;
hex = false ;
}
}
if ( hex ) {
strlcat ( str , " | " , str_len ) ;
}
}
int DetectContentConvertToNocase ( DetectEngineCtx * de_ctx , DetectContentData * cd )
{
if ( cd - > flags & DETECT_CONTENT_NOCASE ) {
SCLogError ( " can't use multiple nocase modifiers with the same content " ) ;
return - 1 ;
}
/* for consistency in later use (e.g. by MPM construction and hashing),
* coerce the content string to lower - case . */
for ( uint8_t * c = cd - > content ; c < cd - > content + cd - > content_len ; c + + ) {
* c = u8_tolower ( * c ) ;
}
cd - > flags | = DETECT_CONTENT_NOCASE ;
/* Recreate the context with nocase chars */
SpmDestroyCtx ( cd - > spm_ctx ) ;
cd - > spm_ctx = SpmInitCtx ( cd - > content , cd - > content_len , 1 , de_ctx - > spm_global_thread_ctx ) ;
if ( cd - > spm_ctx = = NULL ) {
return - 1 ;
}
return 0 ;
}
# ifdef UNITTESTS /* UNITTESTS */
# include "detect-engine-alert.h"
# include "packet.h"
static bool TestLastContent ( const Signature * s , uint16_t o , uint16_t d )
{
const SigMatch * sm = s - > init_data - > smlists_tail [ DETECT_SM_LIST_PMATCH ] ;
if ( ! sm ) {
SCLogDebug ( " no sm " ) ;
return false ;
}
if ( ! ( sm - > type = = DETECT_CONTENT ) ) {
SCLogDebug ( " not content " ) ;
return false ;
}
const DetectContentData * cd = ( const DetectContentData * ) sm - > ctx ;
if ( o ! = cd - > offset ) {
SCLogDebug ( " offset mismatch %u != %u " , o , cd - > offset ) ;
return false ;
}
if ( d ! = cd - > depth ) {
SCLogDebug ( " depth mismatch %u != %u " , d , cd - > depth ) ;
return false ;
}
return true ;
}
# define TEST_RUN(sig, o, d) \
{ \
SCLogDebug ( " TEST_RUN start: '%s' " , ( sig ) ) ; \
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ; \
FAIL_IF_NULL ( de_ctx ) ; \
de_ctx - > flags | = DE_QUIET ; \
char rule [ 2048 ] ; \
snprintf ( rule , sizeof ( rule ) , " alert tcp any any -> any any (%s sid:1; rev:1;) " , ( sig ) ) ; \
Signature * s = DetectEngineAppendSig ( de_ctx , rule ) ; \
FAIL_IF_NULL ( s ) ; \
SigPrepareStage1 ( de_ctx ) ; \
bool res = TestLastContent ( s , ( o ) , ( d ) ) ; \
FAIL_IF ( res = = false ) ; \
DetectEngineCtxFree ( de_ctx ) ; \
}
# define TEST_DONE \
PASS
/** \test test propagation of depth/offset/distance/within */
static int DetectContentDepthTest01 ( void )
{
// straight depth/offset
TEST_RUN ( " content: \" abc \" ; offset:1; depth:3; " , 1 , 4 ) ;
// dsize applied as depth
TEST_RUN ( " dsize:10; content: \" abc \" ; " , 0 , 10 ) ;
TEST_RUN ( " dsize:<10; content: \" abc \" ; " , 0 , 10 ) ;
TEST_RUN ( " dsize:5<>10; content: \" abc \" ; " , 0 , 10 ) ;
// relative match, directly following anchored content
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" xyz \" ; distance:0; within:3; " , 3 , 6 ) ;
// relative match, directly following anchored content
TEST_RUN ( " content: \" abc \" ; offset:3; depth:3; content: \" xyz \" ; distance:0; within:3; " , 6 , 9 ) ;
TEST_RUN ( " content: \" abc \" ; depth:6; content: \" xyz \" ; distance:0; within:3; " , 3 , 9 ) ;
// multiple relative matches after anchored content
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" klm \" ; distance:0; within:3; content: \" xyz \" ; distance:0; within:3; " , 6 , 9 ) ;
// test 'reset' due to unanchored content
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" klm \" ; content: \" xyz \" ; distance:0; within:3; " , 3 , 0 ) ;
// test 'reset' due to unanchored pcre
TEST_RUN ( " content: \" abc \" ; depth:3; pcre:/ \" klm \" /; content: \" xyz \" ; distance:0; within:3; " , 0 , 0 ) ;
// test relative pcre. We can use previous offset+pattern len
TEST_RUN ( " content: \" abc \" ; depth:3; pcre:/ \" klm \" /R; content: \" xyz \" ; distance:0; within:3; " , 3 , 0 ) ;
TEST_RUN ( " content: \" abc \" ; offset:3; depth:3; pcre:/ \" klm \" /R; content: \" xyz \" ; distance:0; within:3; " , 6 , 0 ) ;
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" klm \" ; within:3; content: \" xyz \" ; within:3; " , 0 , 9 ) ;
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" klm \" ; distance:0; content: \" xyz \" ; distance:0; " , 6 , 0 ) ;
// tests to see if anchored 'ends_with' is applied to other content as depth
TEST_RUN ( " content: \" abc \" ; depth:6; isdataat:!1,relative; content: \" klm \" ; " , 0 , 6 ) ;
TEST_RUN ( " content: \" abc \" ; depth:3; content: \" klm \" ; within:3; content: \" xyz \" ; within:3; isdataat:!1,relative; content: \" def \" ; " , 0 , 9 ) ;
TEST_RUN ( " content: \" |03| \" ; depth:1; content: \" |e0| \" ; distance:4; within:1; " , 5 , 6 ) ;
TEST_RUN ( " content: \" |03| \" ; depth:1; content: \" |e0| \" ; distance:4; within:1; content: \" Cookie|3a| \" ; distance:5; within:7; " , 11 , 18 ) ;
TEST_RUN ( " content: \" this \" ; content: \" is \" ; within:6; content: \" big \" ; within:8; content: \" string \" ; within:8; " , 0 , 0 ) ;
TEST_RUN ( " dsize:<80; content:! \" |00 22 02 00| \" ; depth: 4; content: \" |00 00 04| \" ; distance:8; within:3; content: \" |00 00 00 00 00| \" ; distance:6; within:5; " , 17 , 80 ) ;
TEST_RUN ( " content:! \" |00 22 02 00| \" ; depth: 4; content: \" |00 00 04| \" ; distance:8; within:3; content: \" |00 00 00 00 00| \" ; distance:6; within:5; " , 17 , 0 ) ;
TEST_RUN ( " content: \" |0d 0a 0d 0a| \" ; content: \" code= \" ; distance:0; " , 4 , 0 ) ;
TEST_RUN ( " content: \" |0d 0a 0d 0a| \" ; content: \" code= \" ; distance:0; content: \" xploit.class \" ; distance:2; within:18; " , 11 , 0 ) ;
TEST_RUN ( " content: \" |16 03| \" ; depth:2; content: \" |55 04 0a| \" ; distance:0; " , 2 , 0 ) ;
TEST_RUN ( " content: \" |16 03| \" ; depth:2; content: \" |55 04 0a| \" ; distance:0; content: \" |0d|LogMeIn, Inc. \" ; distance:1; within:14; " , 6 , 0 ) ;
TEST_RUN ( " content: \" |16 03| \" ; depth:2; content: \" |55 04 0a| \" ; distance:0; content: \" |0d|LogMeIn, Inc. \" ; distance:1; within:14; content: \" .app \" ; " , 0 , 0 ) ;
TEST_RUN ( " content: \" = \" ; offset:4; depth:9; " , 4 , 13 ) ;
// low end: offset 4 + patlen 1 = 5. So 5 + distance 55 = 60.
// hi end: depth '13' (4+9) + distance 55 = 68 + within 2 = 70
TEST_RUN ( " content: \" = \" ; offset:4; depth:9; content: \" =& \" ; distance:55; within:2; " , 60 , 70 ) ;
// distance value is too high so we bail and not set anything on this content
TEST_RUN ( " content: \" 0123456789 \" ; content: \" abcdef \" ; distance:1048576; " , 0 , 0 ) ;
// Bug #5162.
TEST_RUN ( " content: \" SMB \" ; depth:8; content: \" |09 00| \" ; distance:8; within:2; " , 11 , 18 ) ;
TEST_RUN ( " content: \" SMB \" ; depth:8; content: \" |09 00| \" ; distance:8; within:2; content: \" |05 "
" 00 00| \" ; distance:0; " ,
13 , 0 ) ;
TEST_RUN ( " content: \" SMB \" ; depth:8; content: \" |09 00| \" ; distance:8; within:2; content: \" |05 "
" 00 00| \" ; distance:0; content: \" |0c 00| \" ; distance:19; within:2; " ,
35 , 0 ) ;
TEST_RUN ( " content: \" SMB \" ; depth:8; content: \" |09 00| \" ; distance:8; within:2; content: \" |05 "
" 00 00| \" ; distance:0; content: \" |0c 00| \" ; distance:19; within:2; content: \" |15 00 "
" 00 00| \" ; distance:20; within:4; " ,
57 , 0 ) ;
TEST_DONE ;
}
/**
* \ brief Print list of DETECT_CONTENT SigMatch ' s allocated in a
* SigMatch list , from the current sm to the end
* \ param sm pointer to the current SigMatch to start printing from
*/
static void DetectContentPrintAll ( SigMatch * sm )
{
# ifdef DEBUG
if ( SCLogDebugEnabled ( ) ) {
int i = 0 ;
if ( sm = = NULL )
return ;
SigMatch * first_sm = sm ;
/* Print all of them */
for ( ; first_sm ! = NULL ; first_sm = first_sm - > next ) {
if ( first_sm - > type = = DETECT_CONTENT ) {
SCLogDebug ( " Printing SigMatch DETECT_CONTENT %d " , + + i ) ;
DetectContentPrint ( ( DetectContentData * ) first_sm - > ctx ) ;
}
}
}
# endif /* DEBUG */
}
static int g_file_data_buffer_id = 0 ;
static int g_dce_stub_data_buffer_id = 0 ;
/**
* \ test DetectContentParseTest01 this is a test to make sure we can deal with escaped colons
*/
static int DetectContentParseTest01 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " abc \\ :def " ;
const char * teststringparsed = " abc:def " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
if ( memcmp ( cd - > content , teststringparsed , strlen ( teststringparsed ) ) ! = 0 ) {
SCLogDebug ( " expected %s got " , teststringparsed ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
} else {
SCLogDebug ( " expected %s got NULL: " , teststringparsed ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest02 this is a test to make sure we can deal with escaped semi - colons
*/
static int DetectContentParseTest02 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " abc \\ ;def " ;
const char * teststringparsed = " abc;def " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
if ( memcmp ( cd - > content , teststringparsed , strlen ( teststringparsed ) ) ! = 0 ) {
SCLogDebug ( " expected %s got " , teststringparsed ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
} else {
SCLogDebug ( " expected %s got NULL: " , teststringparsed ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest03 this is a test to make sure we can deal with escaped double - quotes
*/
static int DetectContentParseTest03 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " abc \\ \" def " ;
const char * teststringparsed = " abc \" def " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
if ( memcmp ( cd - > content , teststringparsed , strlen ( teststringparsed ) ) ! = 0 ) {
SCLogDebug ( " expected %s got " , teststringparsed ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
} else {
SCLogDebug ( " expected %s got NULL: " , teststringparsed ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest04 this is a test to make sure we can deal with escaped backslashes
*/
static int DetectContentParseTest04 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " abc \\ \\ def " ;
const char * teststringparsed = " abc \\ def " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
uint16_t len = ( cd - > content_len > strlen ( teststringparsed ) ) ;
if ( memcmp ( cd - > content , teststringparsed , len ) ! = 0 ) {
SCLogDebug ( " expected %s got " , teststringparsed ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
} else {
SCLogDebug ( " expected %s got NULL: " , teststringparsed ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest05 test illegal escape
*/
static int DetectContentParseTest05 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " abc \\ def " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
SCLogDebug ( " expected NULL got " ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest06 test a binary content
*/
static int DetectContentParseTest06 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " a|42|c|44|e|46| " ;
const char * teststringparsed = " abcdef " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
uint16_t len = ( cd - > content_len > strlen ( teststringparsed ) ) ;
if ( memcmp ( cd - > content , teststringparsed , len ) ! = 0 ) {
SCLogDebug ( " expected %s got " , teststringparsed ) ;
PrintRawUriFp ( stdout , cd - > content , cd - > content_len ) ;
SCLogDebug ( " : " ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
} else {
SCLogDebug ( " expected %s got NULL: " , teststringparsed ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest07 test an empty content
*/
static int DetectContentParseTest07 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
SCLogDebug ( " expected NULL got %p: " , cd ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test DetectContentParseTest08 test an empty content
*/
static int DetectContentParseTest08 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
const char * teststring = " " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd ! = NULL ) {
SCLogDebug ( " expected NULL got %p: " , cd ) ;
result = 0 ;
DetectContentFree ( NULL , cd ) ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
return result ;
}
/**
* \ test Test packet Matches
* \ param raw_eth_pkt pointer to the ethernet packet
* \ param pktsize size of the packet
* \ param sig pointer to the signature to test
* \ param sid sid number of the signature
* \ retval return 1 if match
* \ retval return 0 if not
*/
static int DetectContentLongPatternMatchTest ( uint8_t * raw_eth_pkt , uint16_t pktsize , const char * sig ,
uint32_t sid )
{
Packet * p = PacketGetFromAlloc ( ) ;
FAIL_IF_NULL ( p ) ;
DecodeThreadVars dtv ;
ThreadVars th_v ;
DetectEngineThreadCtx * det_ctx = NULL ;
memset ( & dtv , 0 , sizeof ( DecodeThreadVars ) ) ;
memset ( & th_v , 0 , sizeof ( th_v ) ) ;
FlowInitConfig ( FLOW_QUIET ) ;
DecodeEthernet ( & th_v , & dtv , p , raw_eth_pkt , pktsize ) ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
de_ctx - > flags | = DE_QUIET ;
Signature * s = DetectEngineAppendSig ( de_ctx , sig ) ;
FAIL_IF_NULL ( s ) ;
if ( de_ctx - > sig_list - > init_data - > smlists_tail [ DETECT_SM_LIST_PMATCH ] - > type = = DETECT_CONTENT ) {
DetectContentData * co = ( DetectContentData * ) de_ctx - > sig_list - > init_data
- > smlists_tail [ DETECT_SM_LIST_PMATCH ]
- > ctx ;
FAIL_IF ( co - > flags & DETECT_CONTENT_RELATIVE_NEXT ) ;
}
SCLogDebug ( " ---DetectContentLongPatternMatchTest--- " ) ;
DetectContentPrintAll ( de_ctx - > sig_list - > init_data - > smlists [ DETECT_SM_LIST_MATCH ] ) ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
int result = PacketAlertCheck ( p , sid ) ;
DetectEngineThreadCtxDeinit ( & th_v , ( void * ) det_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
PacketRecycle ( p ) ;
FlowShutdown ( ) ;
SCFree ( p ) ;
return result ;
}
/**
* \ brief Wrapper for DetectContentLongPatternMatchTest
*/
static int DetectContentLongPatternMatchTestWrp ( const char * sig , uint32_t sid )
{
/** Real packet with the following tcp data:
* " Hi, this is a big test to check content matches of splitted "
* " patterns between multiple chunks! "
* ( without quotes ! : ) )
*/
uint8_t raw_eth_pkt [ ] = {
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x08 , 0x00 , 0x45 , 0x00 ,
0x00 , 0x85 , 0x00 , 0x01 , 0x00 , 0x00 , 0x40 , 0x06 ,
0x7c , 0x70 , 0x7f , 0x00 , 0x00 , 0x01 , 0x7f , 0x00 ,
0x00 , 0x01 , 0x00 , 0x14 , 0x00 , 0x50 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x50 , 0x02 ,
0x20 , 0x00 , 0xc9 , 0xad , 0x00 , 0x00 , 0x48 , 0x69 ,
0x2c , 0x20 , 0x74 , 0x68 , 0x69 , 0x73 , 0x20 , 0x69 ,
0x73 , 0x20 , 0x61 , 0x20 , 0x62 , 0x69 , 0x67 , 0x20 ,
0x74 , 0x65 , 0x73 , 0x74 , 0x20 , 0x74 , 0x6f , 0x20 ,
0x63 , 0x68 , 0x65 , 0x63 , 0x6b , 0x20 , 0x63 , 0x6f ,
0x6e , 0x74 , 0x65 , 0x6e , 0x74 , 0x20 , 0x6d , 0x61 ,
0x74 , 0x63 , 0x68 , 0x65 , 0x73 , 0x20 , 0x6f , 0x66 ,
0x20 , 0x73 , 0x70 , 0x6c , 0x69 , 0x74 , 0x74 , 0x65 ,
0x64 , 0x20 , 0x70 , 0x61 , 0x74 , 0x74 , 0x65 , 0x72 ,
0x6e , 0x73 , 0x20 , 0x62 , 0x65 , 0x74 , 0x77 , 0x65 ,
0x65 , 0x6e , 0x20 , 0x6d , 0x75 , 0x6c , 0x74 , 0x69 ,
0x70 , 0x6c , 0x65 , 0x20 , 0x63 , 0x68 , 0x75 , 0x6e ,
0x6b , 0x73 , 0x21 } ; /* end raw_eth_pkt */
return DetectContentLongPatternMatchTest ( raw_eth_pkt , ( uint16_t ) sizeof ( raw_eth_pkt ) ,
sig , sid ) ;
}
/**
* \ test Check if we match a normal pattern ( not splitted )
*/
static int DetectContentLongPatternMatchTest01 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big test \" ; sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match a splitted pattern
*/
static int DetectContentLongPatternMatchTest02 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big test to check content matches of "
" splitted patterns between multiple chunks! \" ; sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check that we don ' t match the signature if one of the splitted
* chunks doesn ' t match the packet
*/
static int DetectContentLongPatternMatchTest03 ( void )
{
/** The last chunk of the content should not match */
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big test to check content matches of "
" splitted patterns between multiple splitted chunks! \" ; sid:1;) " ;
return ( DetectContentLongPatternMatchTestWrp ( sig , 1 ) = = 0 ) ? 1 : 0 ;
}
/**
* \ test Check if we match multiple content ( not splitted )
*/
static int DetectContentLongPatternMatchTest04 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is \" ; depth:15 ;content: \" a big test \" ; "
" within:15; content: \" to check content matches of \" ; "
" within:30; content: \" splitted patterns \" ; distance:1; "
" within:30; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check that we match packets with multiple chunks and not chunks
* Here we should specify only contents that fit in 32 bytes
* Each of them with their modifier values
*/
static int DetectContentLongPatternMatchTest05 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big \" ; depth:17; "
" isdataat:30, relative; "
" content: \" test \" ; within: 5; distance:1; "
" isdataat:15, relative; "
" content: \" of splitted \" ; within:37; distance:15; "
" isdataat:20,relative; "
" content: \" patterns \" ; within:9; distance:1; "
" isdataat:10, relative; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check that we match packets with multiple chunks and not chunks
* Here we should specify contents that fit and contents that must be splitted
* Each of them with their modifier values
*/
static int DetectContentLongPatternMatchTest06 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big test to check cont \" ; depth:36; "
" content: \" ent matches \" ; within:11; distance:0; "
" content: \" of splitted patterns between multiple \" ; "
" within:38; distance:1; "
" content: \" chunks! \" ; within: 8; distance:1; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match contents that are in the payload
* but not in the same order as specified in the signature
*/
static int DetectContentLongPatternMatchTest07 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" chunks! \" ; "
" content: \" content matches \" ; offset:32; depth:47; "
" content: \" of splitted patterns between multiple \" ; "
" content: \" Hi, this is a big \" ; offset:0; depth:17; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match contents that are in the payload
* but not in the same order as specified in the signature
*/
static int DetectContentLongPatternMatchTest08 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" ent matches \" ; "
" content: \" of splitted patterns between multiple \" ; "
" within:38; distance:1; "
" content: \" chunks! \" ; within: 8; distance:1; "
" content: \" Hi, this is a big test to check cont \" ; depth:36; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match contents that are in the payload
* but not in the same order as specified in the signature
*/
static int DetectContentLongPatternMatchTest09 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" ent matches \" ; "
" content: \" of splitted patterns between multiple \" ; "
" offset:47; depth:85; "
" content: \" chunks! \" ; within: 8; distance:1; "
" content: \" Hi, this is a big test to chec \" ; depth:36; "
" content: \" k cont \" ; distance:0; within:6; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match two consecutive simple contents
*/
static int DetectContentLongPatternMatchTest10 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" Hi, this is a big test to check \" ; "
" content: \" con \" ; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
/**
* \ test Check if we match two contents of length 1
*/
static int DetectContentLongPatternMatchTest11 ( void )
{
const char * sig = " alert tcp any any -> any any (msg: \" Nothing.. \" ; "
" content: \" H \" ; "
" content: \" i \" ; "
" sid:1;) " ;
return DetectContentLongPatternMatchTestWrp ( sig , 1 ) ;
}
static int DetectContentParseTest09 ( void )
{
DetectContentData * cd = NULL ;
const char * teststring = " boo " ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
FAIL_IF_NULL ( cd ) ;
DetectContentFree ( NULL , cd ) ;
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
PASS ;
}
/**
* \ test Test cases where if within specified is < content length we invalidate
* the sig .
*/
static int DetectContentParseTest17 ( void )
{
int result = 0 ;
const char * sigstr = " alert tcp any any -> any any (msg: \" Dummy \" ; "
" content: \" one \" ; content: \" two \" ; within:2; sid:1;) " ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > sig_list = SigInit ( de_ctx , sigstr ) ;
if ( de_ctx - > sig_list ! = NULL )
goto end ;
result = 1 ;
end :
SigCleanSignatures ( de_ctx ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Test content for dce sig .
*/
static int DetectContentParseTest18 ( void )
{
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
Signature * s = SigAlloc ( ) ;
FAIL_IF_NULL ( s ) ;
FAIL_IF ( DetectSignatureSetAppProto ( s , ALPROTO_DCERPC ) < 0 ) ;
FAIL_IF_NOT ( DetectContentSetup ( de_ctx , s , " one " ) = = 0 ) ;
FAIL_IF ( DetectBufferIsPresent ( s , g_dce_stub_data_buffer_id ) ) ;
FAIL_IF_NOT ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] ! = NULL ) ;
SigFree ( de_ctx , s ) ;
s = SigAlloc ( ) ;
FAIL_IF_NULL ( s ) ;
FAIL_IF_NOT ( DetectContentSetup ( de_ctx , s , " one " ) = = 0 ) ;
FAIL_IF ( DetectBufferIsPresent ( s , g_dce_stub_data_buffer_id ) ) ;
FAIL_IF_NOT ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] ! = NULL ) ;
SigFree ( de_ctx , s ) ;
DetectEngineCtxFree ( de_ctx ) ;
PASS ;
}
/**
* \ test Test content for dce sig .
*/
static int DetectContentParseTest19 ( void )
{
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
de_ctx - > flags | = DE_QUIET ;
Signature * s =
DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing dce iface, stub_data with content \" ; "
" dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
" dce_stub_data; "
" content: \" one \" ; distance:0; sid:1;) " ) ;
FAIL_IF_NULL ( s ) ;
SigMatch * sm = DetectBufferGetFirstSigMatch ( s , g_dce_stub_data_buffer_id ) ;
FAIL_IF_NULL ( sm ) ;
FAIL_IF_NOT ( sm - > type = = DETECT_CONTENT ) ;
FAIL_IF_NOT ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] = = NULL ) ;
DetectContentData * data = ( DetectContentData * ) sm - > ctx ;
FAIL_IF_NOT ( data - > flags = = DETECT_CONTENT_DISTANCE ) ;
s = DetectEngineAppendSig ( de_ctx ,
" alert tcp any any -> any any "
" (msg: \" Testing dce iface, stub_data with contents & distance, within \" ; "
" dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
" dce_stub_data; "
" content: \" one \" ; distance:0; content: \" two \" ; within:10; sid:2;) " ) ;
FAIL_IF_NULL ( s ) ;
sm = DetectBufferGetFirstSigMatch ( s , g_dce_stub_data_buffer_id ) ;
FAIL_IF_NULL ( sm ) ;
FAIL_IF_NOT ( sm - > type = = DETECT_CONTENT ) ;
FAIL_IF_NULL ( sm - > next ) ;
sm = sm - > next ;
FAIL_IF_NOT ( sm - > type = = DETECT_CONTENT ) ;
FAIL_IF_NOT ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] = = NULL ) ;
data = ( DetectContentData * ) sm - > ctx ;
FAIL_IF_NOT ( data - > flags = = DETECT_CONTENT_WITHIN ) ;
FAIL_IF_NOT ( data - > within = = 10 ) ;
s = DetectEngineAppendSig ( de_ctx ,
" alert tcp any any -> any any "
" (msg: \" Testing dce iface, stub with contents, distance, within \" ; "
" dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
" dce_stub_data; "
" content: \" one \" ; distance:0; "
" content: \" two \" ; within:10; distance:2; sid:3;) " ) ;
FAIL_IF_NULL ( s ) ;
sm = DetectBufferGetFirstSigMatch ( s , g_dce_stub_data_buffer_id ) ;
FAIL_IF_NULL ( sm ) ;
FAIL_IF_NOT ( sm - > type = = DETECT_CONTENT ) ;
FAIL_IF_NULL ( sm - > next ) ;
sm = sm - > next ;
FAIL_IF_NOT ( sm - > type = = DETECT_CONTENT ) ;
data = ( DetectContentData * ) sm - > ctx ;
FAIL_IF_NOT ( data - > flags = = ( DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE ) ) ;
FAIL_IF_NOT ( data - > within = = 10 ) ;
FAIL_IF_NOT ( data - > distance = = 2 ) ;
FAIL_IF_NOT ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] = = NULL ) ;
s = DetectEngineAppendSig ( de_ctx , " alert tcp any any -> any any "
" (msg: \" Testing content \" ; "
" content: \" one \" ; sid:4;) " ) ;
FAIL_IF_NULL ( s ) ;
FAIL_IF ( DetectBufferIsPresent ( s , g_dce_stub_data_buffer_id ) ) ;
FAIL_IF ( s - > init_data - > smlists [ DETECT_SM_LIST_PMATCH ] = = NULL ) ;
DetectEngineCtxFree ( de_ctx ) ;
PASS ;
}
/**
* \ test Test content for dce sig .
*/
static int DetectContentParseTest20 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" \" ; sid:238012;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest21 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" ; sid:238012;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest22 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" boo; sid:238012;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest23 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content:boo \" ; sid:238012;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest24 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
DetectContentData * cd = 0 ;
Signature * s = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
s = de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: ! \" boo \" ; sid:238012;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
printf ( " de_ctx->sig_list == NULL: " ) ;
result = 0 ;
goto end ;
}
if ( s - > init_data - > smlists_tail [ DETECT_SM_LIST_PMATCH ] = = NULL | |
s - > init_data - > smlists_tail [ DETECT_SM_LIST_PMATCH ] - > ctx = = NULL ) {
printf ( " de_ctx->pmatch_tail == NULL || de_ctx->pmatch_tail->ctx == NULL: " ) ;
result = 0 ;
goto end ;
}
cd = ( DetectContentData * ) s - > init_data - > smlists_tail [ DETECT_SM_LIST_PMATCH ] - > ctx ;
result = ( strncmp ( " boo " , ( char * ) cd - > content , cd - > content_len ) = = 0 ) ;
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest25 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" | \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest26 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest27 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" af| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest28 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest29 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" aast| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest30 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" aast|af \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest31 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" aast|af| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest32 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af|asdf \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest33 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af|af| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest34 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af|af|af \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list ! = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
/**
* \ test Parsing test
*/
static int DetectContentParseTest35 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
int result = 1 ;
de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert udp any any -> any any "
" (msg: \" test \" ; content: \" |af|af|af| \" ; sid:1;) " ) ;
if ( de_ctx - > sig_list = = NULL ) {
result = 0 ;
goto end ;
}
end :
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
static int SigTestPositiveTestContent ( const char * rule , uint8_t * buf )
{
uint16_t buflen = strlen ( ( char * ) buf ) ;
ThreadVars th_v ;
DetectEngineThreadCtx * det_ctx = NULL ;
memset ( & th_v , 0 , sizeof ( th_v ) ) ;
Packet * p = UTHBuildPacket ( buf , buflen , IPPROTO_TCP ) ;
FAIL_IF_NULL ( p ) ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , rule ) ;
FAIL_IF_NULL ( de_ctx - > sig_list ) ;
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
FAIL_IF_NULL ( det_ctx ) ;
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
FAIL_IF ( PacketAlertCheck ( p , 1 ) ! = 1 ) ;
DetectEngineThreadCtxDeinit ( & th_v , ( void * ) det_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
UTHFreePackets ( & p , 1 ) ;
PASS ;
}
static int DetectContentParseTest41 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
int patlen = 255 ;
char * teststring = SCMalloc ( sizeof ( char ) * ( patlen + 1 ) ) ;
if ( unlikely ( teststring = = NULL ) )
return 0 ;
int idx = 0 ;
for ( int i = 0 ; i < patlen ; idx + + , i + + ) {
teststring [ idx ] = ' a ' ;
}
teststring [ idx + + ] = ' \0 ' ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd = = NULL ) {
SCLogDebug ( " expected not NULL " ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
SCFree ( teststring ) ;
DetectContentFree ( NULL , cd ) ;
return result ;
}
/**
* Tests that content lengths > 255 are supported .
*/
static int DetectContentParseTest42 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
int patlen = 256 ;
char * teststring = SCMalloc ( sizeof ( char ) * ( patlen + 1 ) ) ;
if ( unlikely ( teststring = = NULL ) )
return 0 ;
int idx = 0 ;
for ( int i = 0 ; i < patlen ; idx + + , i + + ) {
teststring [ idx ] = ' a ' ;
}
teststring [ idx + + ] = ' \0 ' ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd = = NULL ) {
SCLogDebug ( " expected not NULL " ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
SCFree ( teststring ) ;
DetectContentFree ( NULL , cd ) ;
return result ;
}
static int DetectContentParseTest43 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
int patlen = 258 ;
char * teststring = SCMalloc ( sizeof ( char ) * ( patlen + 1 ) ) ;
if ( unlikely ( teststring = = NULL ) )
return 0 ;
int idx = 0 ;
teststring [ idx + + ] = ' | ' ;
teststring [ idx + + ] = ' 4 ' ;
teststring [ idx + + ] = ' 6 ' ;
teststring [ idx + + ] = ' | ' ;
for ( int i = 0 ; i < ( patlen - 4 ) ; idx + + , i + + ) {
teststring [ idx ] = ' a ' ;
}
teststring [ idx + + ] = ' \0 ' ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd = = NULL ) {
SCLogDebug ( " expected not NULL " ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
SCFree ( teststring ) ;
DetectContentFree ( NULL , cd ) ;
return result ;
}
/**
* Tests that content lengths > 255 are supported .
*/
static int DetectContentParseTest44 ( void )
{
int result = 1 ;
DetectContentData * cd = NULL ;
int patlen = 259 ;
char * teststring = SCMalloc ( sizeof ( char ) * ( patlen + 1 ) ) ;
if ( unlikely ( teststring = = NULL ) )
return 0 ;
int idx = 0 ;
teststring [ idx + + ] = ' | ' ;
teststring [ idx + + ] = ' 4 ' ;
teststring [ idx + + ] = ' 6 ' ;
teststring [ idx + + ] = ' | ' ;
for ( int i = 0 ; i < ( patlen - 4 ) ; idx + + , i + + ) {
teststring [ idx ] = ' a ' ;
}
teststring [ idx + + ] = ' \0 ' ;
uint8_t spm_matcher = SinglePatternMatchDefaultMatcher ( ) ;
SpmGlobalThreadCtx * spm_global_thread_ctx = SpmInitGlobalThreadCtx ( spm_matcher ) ;
FAIL_IF ( spm_global_thread_ctx = = NULL ) ;
cd = DetectContentParse ( spm_global_thread_ctx , teststring ) ;
if ( cd = = NULL ) {
SCLogDebug ( " expected not NULL " ) ;
result = 0 ;
}
SpmDestroyGlobalThreadCtx ( spm_global_thread_ctx ) ;
SCFree ( teststring ) ;
DetectContentFree ( NULL , cd ) ;
return result ;
}
/**
* \ test Parsing test to check for unescaped quote within content section
*/
static int DetectContentParseTest45 ( void )
{
DetectEngineCtx * de_ctx = NULL ;
de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx ,
" alert tcp any any -> any any "
" (msg: \" test \" ; content: \" |ff| \" content: \" TEST \" ; sid:1;) " ) ;
FAIL_IF_NOT_NULL ( de_ctx - > sig_list ) ;
DetectEngineCtxFree ( de_ctx ) ;
PASS ;
}
static int SigTestNegativeTestContent ( const char * rule , uint8_t * buf )
{
uint16_t buflen = strlen ( ( char * ) buf ) ;
Packet * p = NULL ;
ThreadVars th_v ;
DetectEngineThreadCtx * det_ctx = NULL ;
int result = 0 ;
memset ( & th_v , 0 , sizeof ( th_v ) ) ;
p = UTHBuildPacket ( buf , buflen , IPPROTO_TCP ) ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
de_ctx - > flags | = DE_QUIET ;
de_ctx - > sig_list = SigInit ( de_ctx , rule ) ;
if ( de_ctx - > sig_list = = NULL ) {
goto end ;
}
SigGroupBuild ( de_ctx ) ;
DetectEngineThreadCtxInit ( & th_v , ( void * ) de_ctx , ( void * ) & det_ctx ) ;
SigMatchSignatures ( & th_v , de_ctx , det_ctx , p ) ;
if ( PacketAlertCheck ( p , 1 ) ! = 0 ) {
goto end ;
}
result = 1 ;
end :
if ( det_ctx ! = NULL ) {
DetectEngineThreadCtxDeinit ( & th_v , ( void * ) det_ctx ) ;
}
if ( de_ctx ! = NULL ) {
SigGroupCleanup ( de_ctx ) ;
SigCleanSignatures ( de_ctx ) ;
DetectEngineCtxFree ( de_ctx ) ;
}
UTHFreePackets ( & p , 1 ) ;
return result ;
}
/**
* \ test A positive test that checks that the content string doesn ' t contain
* the negated content
*/
static int SigTest41TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any "
" (msg: \" HTTP URI cap \" ; content:! \" GES \" ; sid:1;) " ,
( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n "
" GET /two/ HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test crash condition : as packet has no direction , it defaults to toclient
* in stream ctx inspection of packet . There a null ptr deref happens
* We don ' t care about the match / nomatch here .
*/
static int SigTest41aTestNegatedContent ( void )
{
( void ) SigTestPositiveTestContent ( " alert tcp any any -> any any (msg: \" HTTP URI cap \" ; flow:to_server; content: \" GET \" ; sid:1;) " , ( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
return 1 ;
}
/**
* \ test A positive test that checks that the content string doesn ' t contain
* the negated content within the specified depth
*/
static int SigTest42TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content:! \" eeeeeeeeeee \" ; depth:22; offset:35; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that checks that the content string doesn ' t contain
* the negated content within the specified depth , and also after the
* specified offset . Since the content is there , the match fails .
*
* Match is at offset : 23 , depth : 34
*/
static int SigTest43TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content:! \" eeeeeeeeeee \" ; depth:34; offset:23; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that checks that the content string doesn ' t contain
* the negated content after the specified offset and within the specified
* depth .
*/
static int SigTest44TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content:! \" eeeeeeeeeee \" ; offset:40; depth:35; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A positive test that uses a combination of content string with negated
* content string
*/
static int SigTest45TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:5; "
" content:! \" eeeeeeeeeee \" ; depth:23; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that uses a combination of content string with negated
* content string , with we receiving a failure for ' onee ' itself .
*/
static int SigTest46TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaaE \" ; "
" content:! \" eeeeeeeeeee \" ; depth:23; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that uses a combination of content string with negated
* content string , with we receiving a failure of first content ' s offset
* condition
*/
static int SigTest47TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; offset:5; "
" content:! \" eeeeeeeeeee \" ; depth:23; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A positive test that checks that we don ' t have a negated content within
* the specified length from the previous content match .
*/
static int SigTest48TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content: \" GET \" ; content:! \" GES \" ; within:26; sid:1;) " ,
( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ "
" HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content with the use of within
*/
static int SigTest49TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content: \" GET \" ; content:! \" Host \" ; within:26; sid:1;) " ,
( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ "
" HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test A positive test that checks the combined use of content and negated
* content with the use of distance
*/
static int SigTest50TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content: \" GET \" ; content:! \" GES \" ; distance:25; sid:1;) " ,
( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ "
" HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content with the use of distance
*
* First GET at offset 0
* First Host at offset 21
*/
static int SigTest51TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" GET \" ; content:! \" Host \" ; distance:17; sid:1;) " , ( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content , with the content not being present
*/
static int SigTest52TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content: \" GES \" ; content:! \" BOO \" ; sid:1;) " ,
( uint8_t * ) " GET /one/ HTTP/1.1 \r \n Host: one.example.org \r \n \r \n \r \n GET /two/ "
" HTTP/1.1 \r \n Host: two.example.org \r \n \r \n \r \n " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content , in the presence of within
*/
static int SigTest53TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content: \" aaa \" ; content:! \" Ggggg \" ; within:56; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/**
* \ test A positive test that checks the combined use of content and negated
* content , in the presence of within
*/
static int SigTest54TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" gggggg \" ; within:20; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that checks the use of negated content along with
* the presence of depth
*/
static int SigTest55TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content:! \" aaa \" ; depth:5; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh " ) ;
}
/**
* \ test A positive test that checks the combined use of 2 contents in the
* presence of within
*/
static int SigTest56TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content: \" aaa \" ; content: \" Ggggg \" ; within:56; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Gggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content , in the presence of within
*/
static int SigTest57TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content: \" aaa \" ; content:! \" Ggggg \" ; within:56; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/**
* \ test A positive test that checks the combined use of content and negated
* content , in the presence of distance
*/
static int SigTest58TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" Ggggg \" ; distance:57; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/**
* \ test A negative test that checks the combined use of content and negated
* content , in the presence of distance
*/
static int SigTest59TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" Gggg \" ; distance:30; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest60TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content:! \" aaa \" ; content: \" Ggggg \" ; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest61TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Ggggg \" ; within:30; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/** \test Test negation in combination with within and depth
*
* Match of " aaa " at offset : 0 , depth : 3
* Match of " Gggggg " at offset : 46 , depth : 52
*
* This signature should not match for the test to pass .
*/
static int SigTest62TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Gggggg \" ; within:49; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest63TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Gggggg \" ; within:56; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest64TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Gggggg \" ; within:30; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/** \test Test negation in combination with within and depth
*
* Match of " aaa " at offset : 0 , depth : 3
* Match of " gggggg " at offset : 46 , depth : 52
*
* This signature should not match for the test to pass .
*/
static int SigTest65TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Gggggg \" ; distance:0; within:49; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest66TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" Gggggg \" ; within:30; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest67TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:10; "
" content:! \" XXXX \" ; within:56; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc XXXXdddd eeeeeeeeeee ffffffffff XXXXggggg hhhhhhhh " ) ;
}
static int SigTest68TestNegatedContent ( void )
{
return SigTestPositiveTestContent (
" alert tcp any any -> any any (content: \" aaa \" ; depth:10; content: \" cccc \" ; offset:8; "
" content:! \" Gggggg \" ; within:28; content: \" hhhhhhhh \" ; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest69TestNegatedContent ( void )
{
return SigTestNegativeTestContent (
" alert tcp any any -> any any (content: \" aaa \" ; depth:10; content: \" cccc \" ; offset:8; "
" content:! \" Gggggg \" ; within:48; content: \" hhhhhhhh \" ; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest70TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" Gggggg \" ; within:52; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
/** \test within and distance */
static int SigTest71TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" Gggggg \" ; within:40; distance:43; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest72TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; "
" content:! \" Gggggg \" ; within:49; distance:43; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh " ) ;
}
static int SigTest73TestNegatedContent ( void )
{
return SigTestNegativeTestContent ( " alert tcp any any -> any any (content: \" aaa \" ; depth:5; "
" content:! \" eeeeeeeeeee \" ; depth:35; sid:1;) " ,
( uint8_t * ) " aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh " ) ;
}
static int SigTest74TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (msg: \" HTTP URI cap \" ; content: \" USER \" ; content:! \" PASS \" ; sid:1;) " , ( uint8_t * ) " USER apple " ) ;
}
static int SigTest75TestNegatedContent ( void )
{
return SigTestPositiveTestContent ( " alert tcp any any -> any any (msg: \" HTTP URI cap \" ; content: \" USER \" ; content: \" !PASS \" ; sid:1;) " , ( uint8_t * ) " USER !PASS " ) ;
}
static int SigTest76TestBug134 ( void )
{
uint8_t * buf = ( uint8_t * ) " test detect ${IFS} in traffic " ;
uint16_t buflen = strlen ( ( char * ) buf ) ;
Packet * p = UTHBuildPacket ( buf , buflen , IPPROTO_TCP ) ;
int result = 0 ;
Flow f ;
memset ( & f , 0 , sizeof ( Flow ) ) ;
FLOW_INITIALIZE ( & f ) ;
p - > dp = 515 ;
p - > flowflags | = FLOW_PKT_ESTABLISHED ;
p - > flowflags | = FLOW_PKT_TOSERVER ;
p - > flow = & f ;
p - > flags | = PKT_HAS_FLOW ;
char sig [ ] = " alert tcp any any -> any 515 "
" (msg: \" detect IFS \" ; flow:to_server,established; content: \" ${IFS} \" ; "
" depth:50; offset:0; sid:900091; rev:1;) " ;
if ( UTHPacketMatchSigMpm ( p , sig , MPM_AC ) = = 0 ) {
result = 0 ;
goto end ;
}
result = 1 ;
end :
if ( p ! = NULL )
UTHFreePacket ( p ) ;
FLOW_DESTROY ( & f ) ;
return result ;
}
static int SigTest77TestBug139 ( void )
{
uint8_t buf [ ] = {
0x12 , 0x23 , 0x34 , 0x35 , 0x52 , 0x52 , 0x24 , 0x42 , 0x22 , 0x24 ,
0x52 , 0x24 , 0x82 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x24 , 0x34 } ;
uint16_t buflen = sizeof ( buf ) ;
Packet * p = UTHBuildPacket ( buf , buflen , IPPROTO_UDP ) ;
int result = 0 ;
p - > dp = 53 ;
char sig [ ] = " alert udp any any -> any 53 (msg: \" dns testing \" ; "
" content: \" |00 00| \" ; depth:5; offset:13; sid:9436601; "
" rev:1;) " ;
if ( UTHPacketMatchSigMpm ( p , sig , MPM_AC ) = = 0 ) {
result = 0 ;
goto end ;
}
result = 1 ;
end :
if ( p ! = NULL )
UTHFreePacket ( p ) ;
return result ;
}
static int DetectLongContentTestCommon ( const char * sig , uint32_t sid )
{
/* Packet with 512 A's in it for testing long content. */
static uint8_t pkt [ 739 ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x08 , 0x00 , 0x45 , 0x00 ,
0x02 , 0xd5 , 0x4a , 0x18 , 0x40 , 0x00 , 0x40 , 0x06 ,
0xd7 , 0xd6 , 0x0a , 0x10 , 0x01 , 0x0b , 0x0a , 0x10 ,
0x01 , 0x0a , 0xdb , 0x36 , 0x00 , 0x50 , 0xca , 0xc5 ,
0xcc , 0xd1 , 0x95 , 0x77 , 0x0f , 0x7d , 0x80 , 0x18 ,
0x00 , 0xe5 , 0x77 , 0x9d , 0x00 , 0x00 , 0x01 , 0x01 ,
0x08 , 0x0a , 0x1d , 0xe0 , 0x86 , 0xc6 , 0xfc , 0x73 ,
0x49 , 0xf3 , 0x50 , 0x4f , 0x53 , 0x54 , 0x20 , 0x2f ,
0x20 , 0x48 , 0x54 , 0x54 , 0x50 , 0x2f , 0x31 , 0x2e ,
0x31 , 0x0d , 0x0a , 0x55 , 0x73 , 0x65 , 0x72 , 0x2d ,
0x41 , 0x67 , 0x65 , 0x6e , 0x74 , 0x3a , 0x20 , 0x63 ,
0x75 , 0x72 , 0x6c , 0x2f , 0x37 , 0x2e , 0x33 , 0x37 ,
0x2e , 0x30 , 0x0d , 0x0a , 0x48 , 0x6f , 0x73 , 0x74 ,
0x3a , 0x20 , 0x31 , 0x30 , 0x2e , 0x31 , 0x36 , 0x2e ,
0x31 , 0x2e , 0x31 , 0x30 , 0x0d , 0x0a , 0x41 , 0x63 ,
0x63 , 0x65 , 0x70 , 0x74 , 0x3a , 0x20 , 0x2a , 0x2f ,
0x2a , 0x0d , 0x0a , 0x43 , 0x6f , 0x6e , 0x74 , 0x65 ,
0x6e , 0x74 , 0x2d , 0x4c , 0x65 , 0x6e , 0x67 , 0x74 ,
0x68 , 0x3a , 0x20 , 0x35 , 0x32 , 0x38 , 0x0d , 0x0a ,
0x43 , 0x6f , 0x6e , 0x74 , 0x65 , 0x6e , 0x74 , 0x2d ,
0x54 , 0x79 , 0x70 , 0x65 , 0x3a , 0x20 , 0x61 , 0x70 ,
0x70 , 0x6c , 0x69 , 0x63 , 0x61 , 0x74 , 0x69 , 0x6f ,
0x6e , 0x2f , 0x78 , 0x2d , 0x77 , 0x77 , 0x77 , 0x2d ,
0x66 , 0x6f , 0x72 , 0x6d , 0x2d , 0x75 , 0x72 , 0x6c ,
0x65 , 0x6e , 0x63 , 0x6f , 0x64 , 0x65 , 0x64 , 0x0d ,
0x0a , 0x0d , 0x0a , 0x58 , 0x58 , 0x58 , 0x58 , 0x58 ,
0x58 , 0x58 , 0x58 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
0x41 , 0x41 , 0x41 , 0x58 , 0x58 , 0x58 , 0x58 , 0x58 ,
0x58 , 0x58 , 0x58
} ;
return DetectContentLongPatternMatchTest ( pkt , ( uint16_t ) sizeof ( pkt ) , sig ,
sid ) ;
}
static int DetectLongContentTest1 ( void )
{
/* Signature with 256 A's. */
const char * sig = " alert tcp any any -> any any (msg: \" Test Rule \" ; content: \" AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \" ; sid:1;) " ;
return DetectLongContentTestCommon ( sig , 1 ) ;
}
static int DetectLongContentTest2 ( void )
{
/* Signature with 512 A's. */
const char * sig = " alert tcp any any -> any any (msg: \" Test Rule \" ; content: \" AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \" ; sid:1;) " ;
return DetectLongContentTestCommon ( sig , 1 ) ;
}
static int DetectLongContentTest3 ( void )
{
/* Signature with 513 A's. */
const char * sig = " alert tcp any any -> any any (msg: \" Test Rule \" ; content: \" AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \" ; sid:1;) " ;
return ! DetectLongContentTestCommon ( sig , 1 ) ;
}
static int DetectBadBinContent ( void )
{
DetectEngineCtx * de_ctx = NULL ;
de_ctx = DetectEngineCtxInit ( ) ;
FAIL_IF_NULL ( de_ctx ) ;
de_ctx - > flags | = DE_QUIET ;
FAIL_IF_NOT_NULL ( DetectEngineAppendSig (
de_ctx , " alert tcp any any -> any any (msg: \" test \" ; content: \" |a| \" ; sid:1;) " ) ) ;
FAIL_IF_NOT_NULL ( DetectEngineAppendSig (
de_ctx , " alert tcp any any -> any any (msg: \" test \" ; content: \" |aa b| \" ; sid:1;) " ) ) ;
FAIL_IF_NOT_NULL ( DetectEngineAppendSig (
de_ctx , " alert tcp any any -> any any (msg: \" test \" ; content: \" |aa bz| \" ; sid:1;) " ) ) ;
/* https://redmine.openinfosecfoundation.org/issues/5201 */
FAIL_IF_NOT_NULL ( DetectEngineAppendSig (
de_ctx , " alert tcp any any -> any any (msg: \" test \" ; content: \" |22 2 22| \" ; sid:1;) " ) ) ;
DetectEngineCtxFree ( de_ctx ) ;
PASS ;
}
/**
* \ brief this function registers unit tests for DetectContent
*/
static void DetectContentRegisterTests ( void )
{
g_file_data_buffer_id = DetectBufferTypeGetByName ( " file_data " ) ;
g_dce_stub_data_buffer_id = DetectBufferTypeGetByName ( " dce_stub_data " ) ;
UtRegisterTest ( " DetectContentDepthTest01 " , DetectContentDepthTest01 ) ;
UtRegisterTest ( " DetectContentParseTest01 " , DetectContentParseTest01 ) ;
UtRegisterTest ( " DetectContentParseTest02 " , DetectContentParseTest02 ) ;
UtRegisterTest ( " DetectContentParseTest03 " , DetectContentParseTest03 ) ;
UtRegisterTest ( " DetectContentParseTest04 " , DetectContentParseTest04 ) ;
UtRegisterTest ( " DetectContentParseTest05 " , DetectContentParseTest05 ) ;
UtRegisterTest ( " DetectContentParseTest06 " , DetectContentParseTest06 ) ;
UtRegisterTest ( " DetectContentParseTest07 " , DetectContentParseTest07 ) ;
UtRegisterTest ( " DetectContentParseTest08 " , DetectContentParseTest08 ) ;
UtRegisterTest ( " DetectContentParseTest09 " , DetectContentParseTest09 ) ;
UtRegisterTest ( " DetectContentParseTest17 " , DetectContentParseTest17 ) ;
UtRegisterTest ( " DetectContentParseTest18 " , DetectContentParseTest18 ) ;
UtRegisterTest ( " DetectContentParseTest19 " , DetectContentParseTest19 ) ;
UtRegisterTest ( " DetectContentParseTest20 " , DetectContentParseTest20 ) ;
UtRegisterTest ( " DetectContentParseTest21 " , DetectContentParseTest21 ) ;
UtRegisterTest ( " DetectContentParseTest22 " , DetectContentParseTest22 ) ;
UtRegisterTest ( " DetectContentParseTest23 " , DetectContentParseTest23 ) ;
UtRegisterTest ( " DetectContentParseTest24 " , DetectContentParseTest24 ) ;
UtRegisterTest ( " DetectContentParseTest25 " , DetectContentParseTest25 ) ;
UtRegisterTest ( " DetectContentParseTest26 " , DetectContentParseTest26 ) ;
UtRegisterTest ( " DetectContentParseTest27 " , DetectContentParseTest27 ) ;
UtRegisterTest ( " DetectContentParseTest28 " , DetectContentParseTest28 ) ;
UtRegisterTest ( " DetectContentParseTest29 " , DetectContentParseTest29 ) ;
UtRegisterTest ( " DetectContentParseTest30 " , DetectContentParseTest30 ) ;
UtRegisterTest ( " DetectContentParseTest31 " , DetectContentParseTest31 ) ;
UtRegisterTest ( " DetectContentParseTest32 " , DetectContentParseTest32 ) ;
UtRegisterTest ( " DetectContentParseTest33 " , DetectContentParseTest33 ) ;
UtRegisterTest ( " DetectContentParseTest34 " , DetectContentParseTest34 ) ;
UtRegisterTest ( " DetectContentParseTest35 " , DetectContentParseTest35 ) ;
UtRegisterTest ( " DetectContentParseTest41 " , DetectContentParseTest41 ) ;
UtRegisterTest ( " DetectContentParseTest42 " , DetectContentParseTest42 ) ;
UtRegisterTest ( " DetectContentParseTest43 " , DetectContentParseTest43 ) ;
UtRegisterTest ( " DetectContentParseTest44 " , DetectContentParseTest44 ) ;
UtRegisterTest ( " DetectContentParseTest45 " , DetectContentParseTest45 ) ;
/* The reals */
UtRegisterTest ( " DetectContentLongPatternMatchTest01 " ,
DetectContentLongPatternMatchTest01 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest02 " ,
DetectContentLongPatternMatchTest02 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest03 " ,
DetectContentLongPatternMatchTest03 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest04 " ,
DetectContentLongPatternMatchTest04 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest05 " ,
DetectContentLongPatternMatchTest05 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest06 " ,
DetectContentLongPatternMatchTest06 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest07 " ,
DetectContentLongPatternMatchTest07 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest08 " ,
DetectContentLongPatternMatchTest08 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest09 " ,
DetectContentLongPatternMatchTest09 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest10 " ,
DetectContentLongPatternMatchTest10 ) ;
UtRegisterTest ( " DetectContentLongPatternMatchTest11 " ,
DetectContentLongPatternMatchTest11 ) ;
/* Negated content tests */
UtRegisterTest ( " SigTest41TestNegatedContent " , SigTest41TestNegatedContent ) ;
UtRegisterTest ( " SigTest41aTestNegatedContent " ,
SigTest41aTestNegatedContent ) ;
UtRegisterTest ( " SigTest42TestNegatedContent " , SigTest42TestNegatedContent ) ;
UtRegisterTest ( " SigTest43TestNegatedContent " , SigTest43TestNegatedContent ) ;
UtRegisterTest ( " SigTest44TestNegatedContent " , SigTest44TestNegatedContent ) ;
UtRegisterTest ( " SigTest45TestNegatedContent " , SigTest45TestNegatedContent ) ;
UtRegisterTest ( " SigTest46TestNegatedContent " , SigTest46TestNegatedContent ) ;
UtRegisterTest ( " SigTest47TestNegatedContent " , SigTest47TestNegatedContent ) ;
UtRegisterTest ( " SigTest48TestNegatedContent " , SigTest48TestNegatedContent ) ;
UtRegisterTest ( " SigTest49TestNegatedContent " , SigTest49TestNegatedContent ) ;
UtRegisterTest ( " SigTest50TestNegatedContent " , SigTest50TestNegatedContent ) ;
UtRegisterTest ( " SigTest51TestNegatedContent " , SigTest51TestNegatedContent ) ;
UtRegisterTest ( " SigTest52TestNegatedContent " , SigTest52TestNegatedContent ) ;
UtRegisterTest ( " SigTest53TestNegatedContent " , SigTest53TestNegatedContent ) ;
UtRegisterTest ( " SigTest54TestNegatedContent " , SigTest54TestNegatedContent ) ;
UtRegisterTest ( " SigTest55TestNegatedContent " , SigTest55TestNegatedContent ) ;
UtRegisterTest ( " SigTest56TestNegatedContent " , SigTest56TestNegatedContent ) ;
UtRegisterTest ( " SigTest57TestNegatedContent " , SigTest57TestNegatedContent ) ;
UtRegisterTest ( " SigTest58TestNegatedContent " , SigTest58TestNegatedContent ) ;
UtRegisterTest ( " SigTest59TestNegatedContent " , SigTest59TestNegatedContent ) ;
UtRegisterTest ( " SigTest60TestNegatedContent " , SigTest60TestNegatedContent ) ;
UtRegisterTest ( " SigTest61TestNegatedContent " , SigTest61TestNegatedContent ) ;
UtRegisterTest ( " SigTest62TestNegatedContent " , SigTest62TestNegatedContent ) ;
UtRegisterTest ( " SigTest63TestNegatedContent " , SigTest63TestNegatedContent ) ;
UtRegisterTest ( " SigTest64TestNegatedContent " , SigTest64TestNegatedContent ) ;
UtRegisterTest ( " SigTest65TestNegatedContent " , SigTest65TestNegatedContent ) ;
UtRegisterTest ( " SigTest66TestNegatedContent " , SigTest66TestNegatedContent ) ;
UtRegisterTest ( " SigTest67TestNegatedContent " , SigTest67TestNegatedContent ) ;
UtRegisterTest ( " SigTest68TestNegatedContent " , SigTest68TestNegatedContent ) ;
UtRegisterTest ( " SigTest69TestNegatedContent " , SigTest69TestNegatedContent ) ;
UtRegisterTest ( " SigTest70TestNegatedContent " , SigTest70TestNegatedContent ) ;
UtRegisterTest ( " SigTest71TestNegatedContent " , SigTest71TestNegatedContent ) ;
UtRegisterTest ( " SigTest72TestNegatedContent " , SigTest72TestNegatedContent ) ;
UtRegisterTest ( " SigTest73TestNegatedContent " , SigTest73TestNegatedContent ) ;
UtRegisterTest ( " SigTest74TestNegatedContent " , SigTest74TestNegatedContent ) ;
UtRegisterTest ( " SigTest75TestNegatedContent " , SigTest75TestNegatedContent ) ;
UtRegisterTest ( " SigTest76TestBug134 " , SigTest76TestBug134 ) ;
UtRegisterTest ( " SigTest77TestBug139 " , SigTest77TestBug139 ) ;
UtRegisterTest ( " DetectLongContentTest1 " , DetectLongContentTest1 ) ;
UtRegisterTest ( " DetectLongContentTest2 " , DetectLongContentTest2 ) ;
UtRegisterTest ( " DetectLongContentTest3 " , DetectLongContentTest3 ) ;
UtRegisterTest ( " DetectBadBinContent " , DetectBadBinContent ) ;
}
# endif /* UNITTESTS */