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;
}
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;
}
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;
}
/**
- * \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;
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.
*
int SigGroupHeadBuildHeadArray(DetectEngineCtx *, SigGroupHead *);
void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *, SigGroupHead *);
void SigGroupHeadSetFilestoreCount(DetectEngineCtx *, SigGroupHead *);
+void SigGroupHeadSetFileMd5Flag(DetectEngineCtx *, SigGroupHead *);
#endif /* __DETECT_ENGINE_SIGGROUP_H__ */
/** \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:
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;
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);
+ }
}
}
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
SigGroupHeadBuildHeadArray(de_ctx, sgh);
SigGroupHeadSetFilemagicFlag(de_ctx, sgh);
+ SigGroupHeadSetFileMd5Flag(de_ctx, sgh);
SigGroupHeadSetFilestoreCount(de_ctx, sgh);
SCLogDebug("filestore count %u", sgh->filestore_cnt);
}
#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) */
#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
int SignatureIsFilestoring(Signature *);
int SignatureIsFilemagicInspecting(Signature *);
+int SignatureIsFileMd5Inspecting(Signature *);
#endif /* __DETECT_H__ */
/** 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) \
#endif
}
+ FileForceTrackingEnable();
SCReturnPtr(output_ctx, "OutputCtx");
}
-/* 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
*/
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 *);
return g_file_force_md5;
}
+void FileForceTrackingEnable(void) {
+ g_file_force_tracking = 1;
+}
+
int FileMagicSize(void) {
/** \todo make this size configurable */
return 512;
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;
}
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);
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);
}
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");
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) {
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
*
#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 */
*/
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);