From: Victor Julien Date: Thu, 7 Jun 2012 08:45:56 +0000 (+0200) Subject: filemd5: add support code for md5 handling for signatures. X-Git-Tag: suricata-1.3rc1~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9e93ec52cdc7f02fb870b0471043edb9bb7bd1f;p=thirdparty%2Fsuricata.git filemd5: add support code for md5 handling for signatures. --- diff --git a/src/app-layer-htp-file.c b/src/app-layer-htp-file.c index f14e17f1a0..341d7ff011 100644 --- a/src/app-layer-htp-file.c +++ b/src/app-layer-htp-file.c @@ -112,6 +112,11 @@ int HTPFileOpen(HtpState *s, uint8_t *filename, uint16_t filename_len, flags |= FILE_NOMAGIC; } + if (s->f->flags & FLOW_FILE_NO_MD5_TC) { + SCLogDebug("no md5 for this flow in toclient direction, so none for this file"); + flags |= FILE_NOMD5; + } + if (!(flags & FILE_STORE) && s->f->flags & FLOW_FILE_NO_STORE_TC) { flags |= FILE_NOSTORE; } @@ -136,6 +141,11 @@ int HTPFileOpen(HtpState *s, uint8_t *filename, uint16_t filename_len, flags |= FILE_NOMAGIC; } + if (s->f->flags & FLOW_FILE_NO_MD5_TS) { + SCLogDebug("no md5 for this flow in toserver direction, so none for this file"); + flags |= FILE_NOMD5; + } + if (!(flags & FILE_STORE) && s->f->flags & FLOW_FILE_NO_STORE_TS) { flags |= FILE_NOSTORE; } diff --git a/src/detect-engine-file.c b/src/detect-engine-file.c index cc2f427387..cf5ab2a713 100644 --- a/src/detect-engine-file.c +++ b/src/detect-engine-file.c @@ -120,7 +120,7 @@ static int DetectFileInspect(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, break; } - if (s->file_flags & FILE_SIG_NEED_FILEMD5 && (!(file->flags & FILE_MD5))) { + if (s->file_flags & FILE_SIG_NEED_MD5 && (!(file->flags & FILE_MD5))) { SCLogDebug("sig needs file md5, but we don't have any"); r = 0; break; diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index e8d6c0cc67..3c7ccad8a7 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -1573,10 +1573,10 @@ int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, } /** - * \brief Set the filestore_cnt in the sgh. + * \brief Set the need md5 flag in the sgh. * * \param de_ctx detection engine ctx for the signatures - * \param sgh sig group head to set the counter in + * \param sgh sig group head to set the flag in */ void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { Signature *s = NULL; @@ -1599,6 +1599,34 @@ void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { return; } +/** + * \brief Set the need magic flag in the sgh. + * + * \param de_ctx detection engine ctx for the signatures + * \param sgh sig group head to set the flag in + */ +void SigGroupHeadSetFileMd5Flag(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { + Signature *s = NULL; + uint32_t sig = 0; + + if (sgh == NULL) + return; + + for (sig = 0; sig < sgh->sig_cnt; sig++) { + s = sgh->match_array[sig]; + if (s == NULL) + continue; + + if (SignatureIsFileMd5Inspecting(s)) { + sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMD5; + SCLogDebug("sgh %p has filemd5", sgh); + break; + } + } + + return; +} + /** * \brief Set the filestore_cnt in the sgh. * diff --git a/src/detect-engine-siggroup.h b/src/detect-engine-siggroup.h index df0e29e6e3..588e761f84 100644 --- a/src/detect-engine-siggroup.h +++ b/src/detect-engine-siggroup.h @@ -88,5 +88,6 @@ void SigGroupHeadStore(DetectEngineCtx *, SigGroupHead *); int SigGroupHeadBuildHeadArray(DetectEngineCtx *, SigGroupHead *); void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *, SigGroupHead *); void SigGroupHeadSetFilestoreCount(DetectEngineCtx *, SigGroupHead *); +void SigGroupHeadSetFileMd5Flag(DetectEngineCtx *, SigGroupHead *); #endif /* __DETECT_ENGINE_SIGGROUP_H__ */ diff --git a/src/detect-filemd5.c b/src/detect-filemd5.c index ca6b047d1f..e225e12b6c 100644 --- a/src/detect-filemd5.c +++ b/src/detect-filemd5.c @@ -325,7 +325,7 @@ static int DetectFileMd5Setup (DetectEngineCtx *de_ctx, Signature *s, char *str) /** \todo remove this once we support more than http */ s->alproto = ALPROTO_HTTP; - s->file_flags |= (FILE_SIG_NEED_FILE|FILE_SIG_NEED_FILEMD5); + s->file_flags |= (FILE_SIG_NEED_FILE|FILE_SIG_NEED_MD5); return 0; error: diff --git a/src/detect.c b/src/detect.c index aa0c7d9f4a..9cb5526200 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1877,6 +1877,14 @@ end: SCLogDebug("disabling magic for flow"); FileDisableMagic(p->flow, STREAM_TOSERVER); } + + /* see if this sgh requires us to consider file md5 */ + if (!FileForceMd5() && (p->flow->sgh_toserver == NULL || + !(p->flow->sgh_toserver->flags & SIG_GROUP_HEAD_HAVEFILEMD5))) + { + SCLogDebug("disabling md5 for flow"); + FileDisableMd5(p->flow, STREAM_TOSERVER); + } } else if (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flow->flags & FLOW_SGH_TOCLIENT)) { p->flow->sgh_toclient = det_ctx->sgh; p->flow->flags |= FLOW_SGH_TOCLIENT; @@ -1892,6 +1900,14 @@ end: SCLogDebug("disabling magic for flow"); FileDisableMagic(p->flow, STREAM_TOCLIENT); } + + /* check if this flow needs md5, if not disable it */ + if (!FileForceMd5() && (p->flow->sgh_toclient == NULL || + !(p->flow->sgh_toclient->flags & SIG_GROUP_HEAD_HAVEFILEMD5))) + { + SCLogDebug("disabling md5 for flow"); + FileDisableMd5(p->flow, STREAM_TOCLIENT); + } } } @@ -2049,6 +2065,24 @@ int SignatureIsFilemagicInspecting(Signature *s) { return 0; } +/** + * \brief Check if a signature contains the filemd5 keyword. + * + * \param s signature + * + * \retval 0 no + * \retval 1 yes + */ +int SignatureIsFileMd5Inspecting(Signature *s) { + if (s == NULL) + return 0; + + if (s->file_flags & FILE_SIG_NEED_MD5) + return 1; + + return 0; +} + /** \brief Test is a initialized signature is IP only * \param de_ctx detection engine ctx * \param s the signature @@ -4008,6 +4042,7 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx) { SigGroupHeadBuildHeadArray(de_ctx, sgh); SigGroupHeadSetFilemagicFlag(de_ctx, sgh); + SigGroupHeadSetFileMd5Flag(de_ctx, sgh); SigGroupHeadSetFilestoreCount(de_ctx, sgh); SCLogDebug("filestore count %u", sgh->filestore_cnt); } diff --git a/src/detect.h b/src/detect.h index 5c04201196..2b0041aafe 100644 --- a/src/detect.h +++ b/src/detect.h @@ -291,7 +291,7 @@ typedef struct DetectPort_ { #define FILE_SIG_NEED_TYPE 0x04 #define FILE_SIG_NEED_MAGIC 0x08 /**< need the start of the file */ #define FILE_SIG_NEED_FILECONTENT 0x10 -#define FILE_SIG_NEED_FILEMD5 0x20 +#define FILE_SIG_NEED_MD5 0x20 /* Detection Engine flags */ #define DE_QUIET 0x01 /**< DE is quiet (esp for unittests) */ @@ -829,6 +829,7 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HEAD_MPM_HSMD (1 << 16) #define SIG_GROUP_HEAD_MPM_HSCD (1 << 17) #define SIG_GROUP_HEAD_MPM_HUAD (1 << 18) +#define SIG_GROUP_HEAD_HAVEFILEMD5 (1 << 19) typedef struct SigGroupHeadInitData_ { /* list of content containers @@ -1065,6 +1066,7 @@ Signature *DetectGetTagSignature(void); int SignatureIsFilestoring(Signature *); int SignatureIsFilemagicInspecting(Signature *); +int SignatureIsFileMd5Inspecting(Signature *); #endif /* __DETECT_H__ */ diff --git a/src/flow.h b/src/flow.h index ab34da4124..34f4e84e1d 100644 --- a/src/flow.h +++ b/src/flow.h @@ -98,6 +98,10 @@ /** flow is ipv6 */ #define FLOW_IPV6 0x08000000 +/** no md5 on files in this flow */ +#define FLOW_FILE_NO_MD5_TS 0x10000000 +#define FLOW_FILE_NO_MD5_TC 0x20000000 + #define FLOW_IS_IPV4(f) \ (((f)->flags & FLOW_IPV4) == FLOW_IPV4) #define FLOW_IS_IPV6(f) \ diff --git a/src/log-file.c b/src/log-file.c index 3bbd5276b6..2037fd9146 100644 --- a/src/log-file.c +++ b/src/log-file.c @@ -438,6 +438,7 @@ static OutputCtx *LogFileLogInitCtx(ConfNode *conf) #endif } + FileForceTrackingEnable(); SCReturnPtr(output_ctx, "OutputCtx"); } diff --git a/src/util-file.c b/src/util-file.c index 47ca1aa495..4b45b22e7d 100644 --- a/src/util-file.c +++ b/src/util-file.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2011 Open Information Security Foundation +/* Copyright (C) 2007-2012 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 @@ -45,6 +45,11 @@ static int g_file_force_magic = 0; */ static int g_file_force_md5 = 0; +/** \brief switch to force tracking off all files + * regardless of the rules. + */ +static int g_file_force_tracking = 0; + /* prototypes */ static void FileFree(File *); static void FileDataFree(FileData *); @@ -65,6 +70,10 @@ int FileForceMd5(void) { return g_file_force_md5; } +void FileForceTrackingEnable(void) { + g_file_force_tracking = 1; +} + int FileMagicSize(void) { /** \todo make this size configurable */ return 512; @@ -295,14 +304,6 @@ static File *FileAlloc(uint8_t *name, uint16_t name_len) { new->name_len = name_len; memcpy(new->name, name, name_len); -#ifdef HAVE_NSS - if (g_file_force_md5) { - new->md5_ctx = HASH_Create(HASH_AlgMD5); - if (new->md5_ctx != NULL) { - HASH_Begin(new->md5_ctx); - } - } -#endif return new; } @@ -424,7 +425,7 @@ int FileAppendData(FileContainer *ffc, uint8_t *data, uint32_t data_len) { if (FileStoreNoStoreCheck(ffc->tail) == 1) { #ifdef HAVE_NSS /* no storage but forced md5 */ - if (g_file_force_md5) { + if (g_file_force_tracking || ffc->tail->md5_ctx) { if (ffc->tail->md5_ctx) HASH_Update(ffc->tail->md5_ctx, data, data_len); @@ -432,8 +433,8 @@ int FileAppendData(FileContainer *ffc, uint8_t *data, uint32_t data_len) { SCReturnInt(0); } #endif - ffc->tail->state = FILE_STATE_CLOSED; - SCLogDebug("flowfile state transitioned to FILE_STATE_CLOSED"); + ffc->tail->state = FILE_STATE_TRUNCATED; + SCLogDebug("flowfile state transitioned to FILE_STATE_TRUNCATED"); SCReturnInt(-2); } @@ -486,9 +487,22 @@ File *FileOpenFile(FileContainer *ffc, uint8_t *name, ff->store = -1; } if (flags & FILE_NOMAGIC) { - SCLogDebug("no doing magic for this file"); + SCLogDebug("not doing magic for this file"); ff->flags |= FILE_NOMAGIC; } + if (flags & FILE_NOMD5) { + SCLogDebug("not doing md5 for this file"); + ff->flags |= FILE_NOMD5; + } + +#ifdef HAVE_NSS + if (!(ff->flags & FILE_NOMD5) || g_file_force_md5) { + ff->md5_ctx = HASH_Create(HASH_AlgMD5); + if (ff->md5_ctx != NULL) { + HASH_Begin(ff->md5_ctx); + } + } +#endif ff->state = FILE_STATE_OPENED; SCLogDebug("flowfile state transitioned to FILE_STATE_OPENED"); @@ -533,14 +547,11 @@ static int FileCloseFilePtr(File *ff, uint8_t *data, if (ff->store == -1) { #ifdef HAVE_NSS - /* no storage but forced md5 */ - if (g_file_force_md5) { - if (ff->md5_ctx) - HASH_Update(ff->md5_ctx, data, data_len); - - ff->size += data_len; - } + /* no storage but md5 */ + if (ff->md5_ctx) + HASH_Update(ff->md5_ctx, data, data_len); #endif + ff->size += data_len; } else { FileData *ffd = FileDataAlloc(data, data_len); if (ffd == NULL) { @@ -666,6 +677,42 @@ void FileDisableMagic(Flow *f, uint8_t direction) { SCReturn; } +/** + * \brief disable file md5 calc for this flow + * + * \param f *LOCKED* flow + * \param direction flow direction + */ +void FileDisableMd5(Flow *f, uint8_t direction) { + File *ptr = NULL; + + SCEnter(); + + DEBUG_ASSERT_FLOW_LOCKED(f); + + if (direction == STREAM_TOSERVER) + f->flags |= FLOW_FILE_NO_MD5_TS; + else + f->flags |= FLOW_FILE_NO_MD5_TC; + + FileContainer *ffc = AppLayerGetFilesFromFlow(f, direction); + if (ffc != NULL) { + for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) { + SCLogDebug("disabling md5 for file %p from direction %s", + ptr, direction == STREAM_TOSERVER ? "toserver":"toclient"); + ptr->flags |= FILE_NOMD5; + + /* destroy any ctx we may have so far */ + if (ptr->md5_ctx != NULL) { + HASH_Destroy(ptr->md5_ctx); + ptr->md5_ctx = NULL; + } + } + } + + SCReturn; +} + /** * \brief set no store flag, close file if needed * diff --git a/src/util-file.h b/src/util-file.h index 3b811ef598..777e43acef 100644 --- a/src/util-file.h +++ b/src/util-file.h @@ -36,6 +36,7 @@ #define FILE_MD5 0x10 #define FILE_LOGGED 0x20 #define FILE_STORED 0x40 +#define FILE_NOMD5 0x80 typedef enum FileState_ { FILE_STATE_NONE = 0, /**< no state */ @@ -163,17 +164,20 @@ void FileDisableStoring(struct Flow_ *, uint8_t); */ void FileDisableStoringForTransaction(struct Flow_ *, uint8_t, uint16_t); -void FileDisableMagic(Flow *f, uint8_t); void FlowFileDisableStoringForTransaction(struct Flow_ *f, uint16_t tx_id); void FilePrune(FileContainer *ffc); +void FileDisableMagic(Flow *f, uint8_t); void FileForceMagicEnable(void); int FileForceMagic(void); +void FileDisableMd5(Flow *f, uint8_t); void FileForceMd5Enable(void); int FileForceMd5(void); +void FileForceTrackingEnable(void); + void FileStoreAllFiles(FileContainer *); void FileStoreAllFilesForTx(FileContainer *, uint16_t); void FileStoreFileById(FileContainer *fc, uint16_t);