]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
filemd5: add support code for md5 handling for signatures.
authorVictor Julien <victor@inliniac.net>
Thu, 7 Jun 2012 08:45:56 +0000 (10:45 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 28 Jun 2012 20:51:20 +0000 (22:51 +0200)
src/app-layer-htp-file.c
src/detect-engine-file.c
src/detect-engine-siggroup.c
src/detect-engine-siggroup.h
src/detect-filemd5.c
src/detect.c
src/detect.h
src/flow.h
src/log-file.c
src/util-file.c
src/util-file.h

index f14e17f1a01b09fe28ffb0239b8b40bc6e43494a..341d7ff011f7463dbf87331e4cadc5b402bab291 100644 (file)
@@ -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;
         }
index cc2f427387f5899babd00d8b9c3cbbb0f4e25899..cf5ab2a713d6871610b5994618fd06a5817f64ac 100644 (file)
@@ -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;
index e8d6c0cc6743b223cd3619c209ffd0a92afe4acc..3c7ccad8a7fe4ccb86e11b63f22765384d6c253d 100644 (file)
@@ -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.
  *
index df0e29e6e39bb823e7a2b2a4d09e8bcf554b0120..588e761f84ac1d2996b00c8f3249edf1625f7161 100644 (file)
@@ -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__ */
index ca6b047d1fefc4b949f713b465a0837e0320b464..e225e12b6c4c4de595ff1f70653c0892a6f1db1a 100644 (file)
@@ -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:
index aa0c7d9f4a62af6987b556c9c024f6728ac104a3..9cb5526200e643f0af5adfe8871f62d43f7231f1 100644 (file)
@@ -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);
     }
index 5c042011963d7ae03fe11ec8311f2fff99346f17..2b0041aafe1244eeaf225216ab1b5a0a8c450341 100644 (file)
@@ -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__ */
 
index ab34da4124476e203c1aed36251d1ae432be358d..34f4e84e1d01e94ae9f3b6b8dcaabe8b7298c6ae 100644 (file)
 /** 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) \
index 3bbd5276b6902018dde0411f13adfaa2155b4bc3..2037fd91463e6b3dfb6b8f80ef23536589a477d3 100644 (file)
@@ -438,6 +438,7 @@ static OutputCtx *LogFileLogInitCtx(ConfNode *conf)
 #endif
     }
 
+    FileForceTrackingEnable();
     SCReturnPtr(output_ctx, "OutputCtx");
 }
 
index 47ca1aa495284c40c292e0dcd1130e4faac3afd3..4b45b22e7da5c87d8e19b4610b8db60b745e9276 100644 (file)
@@ -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
  *
index 3b811ef5984e06b64fe2370327a063cc75a1c277..777e43acef8cb085fb8f56b6a6d34b7728cb4448 100644 (file)
@@ -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);