@ -1,4 +1,4 @@
/* Copyright (C) 2007-202 2 Open Information Security Foundation
/* Copyright (C) 2007-202 3 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
@ -84,20 +84,7 @@ typedef struct DetectFilemagicThreadData {
magic_t ctx ;
} DetectFilemagicThreadData ;
typedef struct DetectFilemagicData {
uint8_t * name ; /** name of the file to match */
BmCtx * bm_ctx ; /** BM context */
uint16_t len ; /** name length */
uint32_t flags ;
} DetectFilemagicData ;
static int DetectFilemagicMatch ( DetectEngineThreadCtx * , Flow * ,
uint8_t , File * , const Signature * , const SigMatchCtx * ) ;
static int DetectFilemagicSetup ( DetectEngineCtx * , Signature * , const char * ) ;
# ifdef UNITTESTS
static void DetectFilemagicRegisterTests ( void ) ;
# endif
static void DetectFilemagicFree ( DetectEngineCtx * , void * ) ;
static int DetectFilemagicSetup ( DetectEngineCtx * , Signature * , const char * ) ;
static int g_file_match_list_id = 0 ;
static int DetectFilemagicSetupSticky ( DetectEngineCtx * de_ctx , Signature * s , const char * str ) ;
@ -119,12 +106,7 @@ void DetectFilemagicRegister(void)
sigmatch_table [ DETECT_FILEMAGIC ] . name = " filemagic " ;
sigmatch_table [ DETECT_FILEMAGIC ] . desc = " match on the information libmagic returns about a file " ;
sigmatch_table [ DETECT_FILEMAGIC ] . url = " /rules/file-keywords.html#filemagic " ;
sigmatch_table [ DETECT_FILEMAGIC ] . FileMatch = DetectFilemagicMatch ;
sigmatch_table [ DETECT_FILEMAGIC ] . Setup = DetectFilemagicSetup ;
sigmatch_table [ DETECT_FILEMAGIC ] . Free = DetectFilemagicFree ;
# ifdef UNITTESTS
sigmatch_table [ DETECT_FILEMAGIC ] . RegisterTests = DetectFilemagicRegisterTests ;
# endif
sigmatch_table [ DETECT_FILEMAGIC ] . flags = SIGMATCH_QUOTES_MANDATORY | SIGMATCH_HANDLE_NEGATION ;
sigmatch_table [ DETECT_FILEMAGIC ] . alternative = DETECT_FILE_MAGIC ;
@ -194,127 +176,6 @@ int FilemagicThreadLookup(magic_t *ctx, File *file)
SCReturnInt ( 0 ) ;
}
/**
* \ brief match the specified filemagic
*
* \ param t thread local vars
* \ param det_ctx pattern matcher thread local data
* \ param f * LOCKED * flow
* \ param flags direction flags
* \ param file file being inspected
* \ param s signature being inspected
* \ param m sigmatch that we will cast into DetectFilemagicData
*
* \ retval 0 no match
* \ retval 1 match
*/
static int DetectFilemagicMatch ( DetectEngineThreadCtx * det_ctx ,
Flow * f , uint8_t flags , File * file , const Signature * s , const SigMatchCtx * m )
{
SCEnter ( ) ;
int ret = 0 ;
DetectFilemagicData * filemagic = ( DetectFilemagicData * ) m ;
DetectFilemagicThreadData * tfilemagic =
( DetectFilemagicThreadData * ) DetectThreadCtxGetKeywordThreadCtx ( det_ctx , g_magic_thread_ctx_id ) ;
if ( tfilemagic = = NULL ) {
SCReturnInt ( 0 ) ;
}
if ( file - > magic = = NULL ) {
FilemagicThreadLookup ( & tfilemagic - > ctx , file ) ;
}
if ( file - > magic ! = NULL ) {
SCLogDebug ( " magic %s " , file - > magic ) ;
/* we include the \0 in the inspection, so patterns can match on the
* end of the string . */
if ( BoyerMooreNocase ( filemagic - > name , filemagic - > len , ( uint8_t * ) file - > magic ,
strlen ( file - > magic ) + 1 , filemagic - > bm_ctx ) ! = NULL )
{
# ifdef DEBUG
if ( SCLogDebugEnabled ( ) ) {
char * name = SCMalloc ( filemagic - > len + 1 ) ;
if ( name ! = NULL ) {
memcpy ( name , filemagic - > name , filemagic - > len ) ;
name [ filemagic - > len ] = ' \0 ' ;
SCLogDebug ( " will look for filemagic %s " , name ) ;
SCFree ( name ) ;
}
}
# endif
if ( ! ( filemagic - > flags & DETECT_CONTENT_NEGATED ) ) {
ret = 1 ;
}
} else if ( filemagic - > flags & DETECT_CONTENT_NEGATED ) {
SCLogDebug ( " negated match " ) ;
ret = 1 ;
}
}
SCReturnInt ( ret ) ;
}
/**
* \ brief Parse the filemagic keyword
*
* \ param de_ctx Pointer to the detection engine context
* \ param idstr Pointer to the user provided option
*
* \ retval filemagic pointer to DetectFilemagicData on success
* \ retval NULL on failure
*/
static DetectFilemagicData * DetectFilemagicParse ( DetectEngineCtx * de_ctx , const char * str , bool negate )
{
DetectFilemagicData * filemagic = NULL ;
/* We have a correct filemagic option */
filemagic = SCMalloc ( sizeof ( DetectFilemagicData ) ) ;
if ( unlikely ( filemagic = = NULL ) )
goto error ;
memset ( filemagic , 0x00 , sizeof ( DetectFilemagicData ) ) ;
if ( DetectContentDataParse ( " filemagic " , str , & filemagic - > name , & filemagic - > len ) = = - 1 ) {
goto error ;
}
filemagic - > bm_ctx = BoyerMooreNocaseCtxInit ( filemagic - > name , filemagic - > len ) ;
if ( filemagic - > bm_ctx = = NULL ) {
goto error ;
}
if ( negate ) {
filemagic - > flags | = DETECT_CONTENT_NEGATED ;
}
SCLogDebug ( " flags %02X " , filemagic - > flags ) ;
if ( filemagic - > flags & DETECT_CONTENT_NEGATED ) {
SCLogDebug ( " negated filemagic " ) ;
}
# ifdef DEBUG
if ( SCLogDebugEnabled ( ) ) {
char * name = SCMalloc ( filemagic - > len + 1 ) ;
if ( name ! = NULL ) {
memcpy ( name , filemagic - > name , filemagic - > len ) ;
name [ filemagic - > len ] = ' \0 ' ;
SCLogDebug ( " will look for filemagic %s " , name ) ;
SCFree ( name ) ;
}
}
# endif
return filemagic ;
error :
if ( filemagic ! = NULL )
DetectFilemagicFree ( de_ctx , filemagic ) ;
return NULL ;
}
static void * DetectFilemagicThreadInit ( void * data /*@unused@*/ )
{
DetectFilemagicThreadData * t = SCCalloc ( 1 , sizeof ( DetectFilemagicThreadData ) ) ;
@ -359,54 +220,40 @@ static void DetectFilemagicThreadFree(void *ctx)
*/
static int DetectFilemagicSetup ( DetectEngineCtx * de_ctx , Signature * s , const char * str )
{
SigMatch * sm = NULL ;
if ( s - > init_data - > transforms . cnt ) {
SCLogError ( " previous transforms not consumed before 'filemagic' " ) ;
SCReturnInt ( - 1 ) ;
}
s - > init_data - > list = DETECT_SM_LIST_NOTSET ;
s - > file_flags | = ( FILE_SIG_NEED_FILE | FILE_SIG_NEED_MAGIC ) ;
DetectFilemagicData * filemagic = DetectFilemagicParse ( de_ctx , str , s - > init_data - > negated ) ;
if ( filemagic = = NULL )
if ( DetectContentSetup ( de_ctx , s , str ) < 0 ) {
return - 1 ;
}
g_magic_thread_ctx_id = DetectRegisterThreadCtxFuncs (
de_ctx , " filemagic " , DetectFilemagicThreadInit , NULL , DetectFilemagicThreadFree , 1 ) ;
if ( g_magic_thread_ctx_id = = - 1 )
goto error ;
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature . */
sm = SigMatchAlloc ( ) ;
SigMatch * sm = DetectGetLastSMFromLists ( s , DETECT_CONTENT , - 1 ) ;
if ( sm = = NULL )
goto error ;
sm - > type = DETECT_FILEMAGIC ;
sm - > ctx = ( void * ) filemagic ;
SigMatchAppendSMToList ( s , sm , g_file_match_list_id ) ;
s - > file_flags | = ( FILE_SIG_NEED_FILE | FILE_SIG_NEED_MAGIC ) ;
return 0 ;
return - 1 ;
error :
DetectFilemagicFree ( de_ctx , filemagic ) ;
if ( sm ! = NULL )
SCFree ( sm ) ;
return - 1 ;
}
DetectContentData * cd = ( DetectContentData * ) sm - > ctx ;
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 ;
}
if ( DetectEngineContentModifierBufferSetup (
de_ctx , s , NULL , DETECT_FILE_MAGIC , g_file_magic_buffer_id , s - > alproto ) < 0 )
return - 1 ;
/**
* \ brief this function will free memory associated with DetectFilemagicData
*
* \ param filemagic pointer to DetectFilemagicData
*/
static void DetectFilemagicFree ( DetectEngineCtx * de_ctx , void * ptr )
{
if ( ptr ! = NULL ) {
DetectFilemagicData * filemagic = ( DetectFilemagicData * ) ptr ;
if ( filemagic - > bm_ctx ! = NULL ) {
BoyerMooreCtxDeInit ( filemagic - > bm_ctx ) ;
}
if ( filemagic - > name ! = NULL )
SCFree ( filemagic - > name ) ;
SCFree ( filemagic ) ;
if ( g_magic_thread_ctx_id = = - 1 ) {
g_magic_thread_ctx_id = DetectRegisterThreadCtxFuncs (
de_ctx , " filemagic " , DetectFilemagicThreadInit , NULL , DetectFilemagicThreadFree , 1 ) ;
if ( g_magic_thread_ctx_id = = - 1 )
return - 1 ;
}
return 0 ;
}
/* file.magic implementation */
@ -577,54 +424,5 @@ static int PrefilterMpmFilemagicRegister(DetectEngineCtx *de_ctx, SigGroupHead *
mpm_reg - > app_v2 . alproto , mpm_reg - > app_v2 . tx_min_progress ,
pectx , PrefilterMpmFilemagicFree , mpm_reg - > pname ) ;
}
# ifdef UNITTESTS /* UNITTESTS */
/**
* \ test DetectFilemagicTestParse01
*/
static int DetectFilemagicTestParse01 ( void )
{
DetectFilemagicData * dnd = DetectFilemagicParse ( NULL , " secret.pdf " , false ) ;
FAIL_IF_NULL ( dnd ) ;
DetectFilemagicFree ( NULL , dnd ) ;
PASS ;
}
/**
* \ test DetectFilemagicTestParse02
*/
static int DetectFilemagicTestParse02 ( void )
{
DetectFilemagicData * dnd = DetectFilemagicParse ( NULL , " backup.tar.gz " , false ) ;
FAIL_IF_NULL ( dnd ) ;
FAIL_IF_NOT ( dnd - > len = = 13 ) ;
FAIL_IF_NOT ( memcmp ( dnd - > name , " backup.tar.gz " , 13 ) = = 0 ) ;
DetectFilemagicFree ( NULL , dnd ) ;
PASS ;
}
/**
* \ test DetectFilemagicTestParse03
*/
static int DetectFilemagicTestParse03 ( void )
{
DetectFilemagicData * dnd = DetectFilemagicParse ( NULL , " cmd.exe " , false ) ;
FAIL_IF_NULL ( dnd ) ;
FAIL_IF_NOT ( dnd - > len = = 7 ) ;
FAIL_IF_NOT ( memcmp ( dnd - > name , " cmd.exe " , 7 ) = = 0 ) ;
DetectFilemagicFree ( NULL , dnd ) ;
PASS ;
}
/**
* \ brief this function registers unit tests for DetectFilemagic
*/
void DetectFilemagicRegisterTests ( void )
{
UtRegisterTest ( " DetectFilemagicTestParse01 " , DetectFilemagicTestParse01 ) ;
UtRegisterTest ( " DetectFilemagicTestParse02 " , DetectFilemagicTestParse02 ) ;
UtRegisterTest ( " DetectFilemagicTestParse03 " , DetectFilemagicTestParse03 ) ;
}
# endif /* UNITTESTS */
# endif /* HAVE_MAGIC */