/* MSG part of the detection engine. */
# include "suricata-common.h"
# include "detect.h"
# include "util-classification-config.h"
# include "util-debug.h"
# include "util-unittest.h"
# include "detect-parse.h"
# include "detect-engine.h"
# include "detect-engine-mpm.h"
int DetectMsgSetup ( DetectEngineCtx * de_ctx , Signature * s , SigMatch * m , char * msgstr ) ;
void DetectMsgRegisterTests ( void ) ;
void DetectMsgRegister ( void ) {
sigmatch_table [ DETECT_MSG ] . name = " msg " ;
sigmatch_table [ DETECT_MSG ] . Match = NULL ;
sigmatch_table [ DETECT_MSG ] . Setup = DetectMsgSetup ;
sigmatch_table [ DETECT_MSG ] . Free = NULL ;
sigmatch_table [ DETECT_MSG ] . RegisterTests = DetectMsgRegisterTests ;
}
int DetectMsgSetup ( DetectEngineCtx * de_ctx , Signature * s , SigMatch * m , char * msgstr )
{
char * str = NULL ;
uint16_t len ;
if ( strlen ( msgstr ) = = 0 )
goto error ;
/* strip "'s */
if ( msgstr [ 0 ] = = ' \" ' & & msgstr [ strlen ( msgstr ) - 1 ] = = ' \" ' ) {
str = SCStrdup ( msgstr + 1 ) ;
str [ strlen ( msgstr ) - 2 ] = ' \0 ' ;
} else if ( msgstr [ 1 ] = = ' \" ' & & msgstr [ strlen ( msgstr ) - 1 ] = = ' \" ' ) {
/* XXX do this parsing in a better way */
str = SCStrdup ( msgstr + 2 ) ;
str [ strlen ( msgstr ) - 3 ] = ' \0 ' ;
//printf("DetectMsgSetup: format hack applied: \'%s\'\n", str);
} else {
SCLogError ( SC_ERR_INVALID_VALUE , " format error \' %s \' " , msgstr ) ;
goto error ;
}
len = strlen ( str ) ;
if ( len = = 0 )
goto error ;
char converted = 0 ;
{
uint16_t i , x ;
uint8_t escape = 0 ;
/* it doesn't matter if we need to escape or not we remove the extra "\" to mimic snort */
for ( i = 0 , x = 0 ; i < len ; i + + ) {
//printf("str[%02u]: %c\n", i, str[i]);
if ( ! escape & & str [ i ] = = ' \\ ' ) {
escape = 1 ;
} else if ( escape ) {
if ( str [ i ] ! = ' : ' & &
str [ i ] ! = ' ; ' & &
str [ i ] ! = ' \\ ' & &
str [ i ] ! = ' \" ' )
{
SCLogDebug ( " character \" %c \" does not need to be escaped but is " , str [ i ] ) ;
}
escape = 0 ;
converted = 1 ;
str [ x ] = str [ i ] ;
x + + ;
} else {
str [ x ] = str [ i ] ;
x + + ;
}
}
#if 0 //def DEBUG
if ( SCLogDebugEnabled ( ) ) {
for ( i = 0 ; i < x ; i + + ) {
printf ( " %c " , str [ i ] ) ;
}
printf ( " \n " ) ;
}
# endif
if ( converted ) {
len = x ;
str [ len ] = ' \0 ' ;
}
}
s - > msg = SCMalloc ( len + 1 ) ;
if ( s - > msg = = NULL )
goto error ;
strlcpy ( s - > msg , str , len + 1 ) ;
SCFree ( str ) ;
return 0 ;
error :
SCFree ( str ) ;
return - 1 ;
}
/* -------------------------------------Unittests-----------------------------*/
# ifdef UNITTESTS
static int DetectMsgParseTest01 ( void )
{
int result = 0 ;
Signature * sig = NULL ;
char * teststringparsed = " flow stateless to_server " ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
SCClassConfGenerateValidDummyClassConfigFD01 ( ) ;
SCClassConfLoadClassficationConfigFile ( de_ctx ) ;
SCClassConfDeleteDummyClassificationConfigFD ( ) ;
sig = SigInit ( de_ctx , " alert tcp any any -> any any (msg: \" flow stateless to_server \" ; flow:stateless,to_server; content: \" flowstatelesscheck \" ; classtype:bad-unknown; sid: 40000002; rev: 1;) " ) ;
if ( sig = = NULL )
goto end ;
if ( strcmp ( sig - > msg , teststringparsed ) ! = 0 ) {
printf ( " got \" %s \" , expected: \" %s \" : " , sig - > msg , teststringparsed ) ;
goto end ;
}
result = 1 ;
end :
if ( sig ! = NULL )
SigFree ( sig ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
static int DetectMsgParseTest02 ( void )
{
int result = 0 ;
Signature * sig = NULL ;
char * teststringparsed = " msg escape tests wxy' \" \\ ;: " ;
DetectEngineCtx * de_ctx = DetectEngineCtxInit ( ) ;
if ( de_ctx = = NULL )
goto end ;
sig = SigInit ( de_ctx , " alert tcp any any -> any any (msg: \" msg escape tests \\ w \\ x \\ y \\ ' \\ \" \\ \\ ; \\ : \" ; flow:to_server,established; content: \" blah \" ; uricontent: \" /blah/ \" ; sid: 100;) " ) ;
if ( sig = = NULL )
goto end ;
if ( strcmp ( sig - > msg , teststringparsed ) ! = 0 ) {
printf ( " got \" %s \" , expected: \" %s \" : " , sig - > msg , teststringparsed ) ;
goto end ;
}
result = 1 ;
end :
if ( sig ! = NULL )
SigFree ( sig ) ;
if ( de_ctx ! = NULL )
DetectEngineCtxFree ( de_ctx ) ;
return result ;
}
# endif /* UNITTESTS */
/**
* \ brief this function registers unit tests for DetectMsg
*/
void DetectMsgRegisterTests ( void ) {
# ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest ( " DetectMsgParseTest01 " , DetectMsgParseTest01 , 1 ) ;
UtRegisterTest ( " DetectMsgParseTest02 " , DetectMsgParseTest02 , 1 ) ;
# endif /* UNITTESTS */
}