From: Duarte Silva Date: Fri, 29 Apr 2016 20:23:55 +0000 (+0200) Subject: file-hashing: added support for SHA-256 file hashing X-Git-Tag: suricata-3.2beta1~330 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=89eb935f733c6b7d1521d140226ae1b2c251853a;p=thirdparty%2Fsuricata.git file-hashing: added support for SHA-256 file hashing --- diff --git a/src/Makefile.am b/src/Makefile.am index edc6d65d2e..c19d33cf03 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -139,6 +139,7 @@ detect-fileext.c detect-fileext.h \ detect-filemagic.c detect-filemagic.h \ detect-filemd5.c detect-filemd5.h \ detect-filesha1.c detect-filesha1.h \ +detect-filesha256.c detect-filesha256.h \ detect-filename.c detect-filename.h \ detect-filesize.c detect-filesize.h \ detect-filestore.c detect-filestore.h \ diff --git a/src/app-layer-htp-file.c b/src/app-layer-htp-file.c index 18b193612b..fa3ac654f1 100644 --- a/src/app-layer-htp-file.c +++ b/src/app-layer-htp-file.c @@ -123,6 +123,11 @@ int HTPFileOpen(HtpState *s, const uint8_t *filename, uint16_t filename_len, flags |= FILE_NOSHA1; } + if (s->f->flags & FLOW_FILE_NO_SHA256_TC) { + SCLogDebug("no sha256 for this flow in toclient direction, so none for this file"); + flags |= FILE_NOSHA256; + } + if (!(flags & FILE_STORE) && (s->f->flags & FLOW_FILE_NO_STORE_TC)) { flags |= FILE_NOSTORE; } @@ -160,6 +165,11 @@ int HTPFileOpen(HtpState *s, const uint8_t *filename, uint16_t filename_len, flags |= FILE_NOSHA1; } + if (s->f->flags & FLOW_FILE_NO_SHA256_TS) { + SCLogDebug("no sha256 for this flow in toserver direction, so none for this file"); + flags |= FILE_NOSHA256; + } + if (!(flags & FILE_STORE) && (s->f->flags & FLOW_FILE_NO_STORE_TS)) { flags |= FILE_NOSTORE; } diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index f8b25c9470..2d584a7c47 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -427,6 +427,10 @@ int SMTPProcessDataChunk(const uint8_t *chunk, uint32_t len, flags |= FILE_NOSHA1; } + if (flow->flags & FLOW_FILE_NO_SHA256_TS) { + flags |= FILE_NOSHA256; + } + /* Find file */ if (entity->ctnt_flags & CTNT_IS_ATTACHMENT) { diff --git a/src/detect-engine-file.c b/src/detect-engine-file.c index 5eb36e853d..dafb28a880 100644 --- a/src/detect-engine-file.c +++ b/src/detect-engine-file.c @@ -135,6 +135,12 @@ static int DetectFileInspect(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, break; } + if ((s->file_flags & FILE_SIG_NEED_SHA256) && (!(file->flags & FILE_SHA256))) { + SCLogDebug("sig needs file sha256, but we don't have any"); + r = DETECT_ENGINE_INSPECT_SIG_NO_MATCH; + break; + } + if ((s->file_flags & FILE_SIG_NEED_SIZE) && file->state < FILE_STATE_CLOSED) { SCLogDebug("sig needs filesize, but state < FILE_STATE_CLOSED"); r = DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index 58a3058ad2..22019a3d36 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -637,6 +637,12 @@ void SigGroupHeadSetFileHashFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh) SCLogDebug("sgh %p has filesha1", sgh); break; } + + if (SignatureIsFileSha256Inspecting(s)) { + sgh->flags |= SIG_GROUP_HEAD_HAVEFILESHA256; + SCLogDebug("sgh %p has filesha256", sgh); + break; + } } return; diff --git a/src/detect-filemd5.c b/src/detect-filemd5.c index 6d8be5394e..c5cf4c1924 100644 --- a/src/detect-filemd5.c +++ b/src/detect-filemd5.c @@ -25,7 +25,6 @@ #include "suricata-common.h" #include "util-detect-file-hash.h" - #include "util-unittest.h" #include "util-unittest-helper.h" diff --git a/src/detect-filesha1.c b/src/detect-filesha1.c index ea4e469bfb..ad18866488 100644 --- a/src/detect-filesha1.c +++ b/src/detect-filesha1.c @@ -26,7 +26,6 @@ #include "suricata-common.h" #include "util-detect-file-hash.h" - #include "util-unittest.h" #include "util-unittest-helper.h" diff --git a/src/detect-filesha256.c b/src/detect-filesha256.c new file mode 100644 index 0000000000..4310445080 --- /dev/null +++ b/src/detect-filesha256.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2007-2016 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + * \author Duarte Silva + * + */ + +#include "suricata-common.h" + +#include "util-detect-file-hash.h" +#include "util-unittest.h" +#include "util-unittest-helper.h" + +#include "detect-filesha256.h" + +#ifndef HAVE_NSS + +static int DetectFileSha256SetupNoSupport (DetectEngineCtx *a, Signature *b, char *c) +{ + SCLogError(SC_ERR_NO_SHA256_SUPPORT, "no SHA-256 calculation support built in, needed for filesha256 keyword"); + return -1; +} + +/** + * \brief Registration function for keyword: filesha256 + */ +void DetectFileSha256Register(void) +{ + sigmatch_table[DETECT_FILESHA256].name = "filesha256"; + sigmatch_table[DETECT_FILESHA256].FileMatch = NULL; + sigmatch_table[DETECT_FILESHA256].Setup = DetectFileSha256SetupNoSupport; + sigmatch_table[DETECT_FILESHA256].Free = NULL; + sigmatch_table[DETECT_FILESHA256].RegisterTests = NULL; + sigmatch_table[DETECT_FILESHA256].flags = SIGMATCH_NOT_BUILT; + + SCLogDebug("registering filesha256 rule option"); + return; +} + +#else /* HAVE_NSS */ + +static int DetectFileSha256Setup (DetectEngineCtx *, Signature *, char *); +static void DetectFileSha256RegisterTests(void); + +/** + * \brief Registration function for keyword: filesha256 + */ +void DetectFileSha256Register(void) +{ + sigmatch_table[DETECT_FILESHA256].name = "filesha256"; + sigmatch_table[DETECT_FILESHA256].desc = "match file SHA-256 against list of SHA-256 checksums"; + sigmatch_table[DETECT_FILESHA256].url = "https://redmine.openinfosecfoundation.org/projects/suricata/wiki/File-keywords#filesha256"; + sigmatch_table[DETECT_FILESHA256].FileMatch = DetectFileHashMatch; + sigmatch_table[DETECT_FILESHA256].Setup = DetectFileSha256Setup; + sigmatch_table[DETECT_FILESHA256].Free = DetectFileHashFree; + sigmatch_table[DETECT_FILESHA256].RegisterTests = DetectFileSha256RegisterTests; + + SCLogDebug("registering filesha256 rule option"); + return; +} + +/** + * \brief this function is used to parse filesha256 options + * \brief into the current signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param str pointer to the user provided "filesha256" option + * + * \retval 0 on Success + * \retval -1 on Failure + */ +static int DetectFileSha256Setup (DetectEngineCtx *de_ctx, Signature *s, char *str) +{ + return DetectFileHashSetup(de_ctx, s, str, DETECT_FILESHA256); +} + +#ifdef UNITTESTS +static int SHA256MatchLookupString(ROHashTable *hash, char *string) +{ + uint8_t sha256[32]; + if (ReadHashString(sha256, string, "file", 88, 64) == 1) { + void *ptr = ROHashLookup(hash, &sha256, (uint16_t)sizeof(sha256)); + if (ptr == NULL) + return 0; + else + return 1; + } + return 0; +} + +static int SHA256MatchTest01(void) +{ + ROHashTable *hash = ROHashInit(4, 32); + if (hash == NULL) { + return 0; + } + if (LoadHashTable(hash, "9c891edb5da763398969b6aaa86a5d46971bd28a455b20c2067cb512c9f9a0f8", "file", 1, DETECT_FILESHA256) != 1) + return 0; + if (LoadHashTable(hash, "6eee51705f34b6cfc7f0c872a7949ec3e3172a908303baf5d67d03b98f70e7e3", "file", 2, DETECT_FILESHA256) != 1) + return 0; + if (LoadHashTable(hash, "b12c7d57507286bbbe36d7acf9b34c22c96606ffd904e3c23008399a4a50c047", "file", 3, DETECT_FILESHA256) != 1) + return 0; + if (LoadHashTable(hash, "ca496e1ddadc290050339dd75ce8830ad3028ce1556a5368874a4aec3aee114b", "file", 4, DETECT_FILESHA256) != 1) + return 0; + if (LoadHashTable(hash, "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f", "file", 5, DETECT_FILESHA256) != 1) + return 0; + if (LoadHashTable(hash, "d765e722e295969c0a5c2d90f549db8b89ab617900bf4698db41c7cdad993bb9", "file", 6, DETECT_FILESHA256) != 1) + return 0; + + if (ROHashInitFinalize(hash) != 1) { + return 0; + } + + if (SHA256MatchLookupString(hash, "9c891edb5da763398969b6aaa86a5d46971bd28a455b20c2067cb512c9f9a0f8") != 1) + return 0; + if (SHA256MatchLookupString(hash, "6eee51705f34b6cfc7f0c872a7949ec3e3172a908303baf5d67d03b98f70e7e3") != 1) + return 0; + if (SHA256MatchLookupString(hash, "b12c7d57507286bbbe36d7acf9b34c22c96606ffd904e3c23008399a4a50c047") != 1) + return 0; + if (SHA256MatchLookupString(hash, "ca496e1ddadc290050339dd75ce8830ad3028ce1556a5368874a4aec3aee114b") != 1) + return 0; + if (SHA256MatchLookupString(hash, "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f") != 1) + return 0; + if (SHA256MatchLookupString(hash, "d765e722e295969c0a5c2d90f549db8b89ab617900bf4698db41c7cdad993bb9") != 1) + return 0; + /* Shouldn't match */ + if (SHA256MatchLookupString(hash, "3333333333333333333333333333333333333333333333333333333333333333") == 1) + return 0; + + ROHashFree(hash); + return 1; +} +#endif + +void DetectFileSha256RegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("SHA256MatchTest01", SHA256MatchTest01); +#endif +} + +#endif /* HAVE_NSS */ diff --git a/src/detect-filesha256.h b/src/detect-filesha256.h new file mode 100644 index 0000000000..a205b48699 --- /dev/null +++ b/src/detect-filesha256.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2007-2016 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + * \author Duarte Silva + */ + +#ifndef __DETECT_FILESHA256_H__ +#define __DETECT_FILESHA256_H__ + +/* prototypes */ +void DetectFileSha256Register (void); + +#endif /* __DETECT_FILESHA256_H__ */ diff --git a/src/detect.c b/src/detect.c index 767329b26d..aeb8123064 100644 --- a/src/detect.c +++ b/src/detect.c @@ -109,6 +109,7 @@ #include "detect-filemagic.h" #include "detect-filemd5.h" #include "detect-filesha1.h" +#include "detect-filesha256.h" #include "detect-filesize.h" #include "detect-dsize.h" #include "detect-flowvar.h" @@ -1870,6 +1871,14 @@ end: FileDisableSha1(pflow, STREAM_TOSERVER); } + /* see if this sgh requires us to consider file sha256 */ + if (!FileForceSha256() && (pflow->sgh_toserver == NULL || + !(pflow->sgh_toserver->flags & SIG_GROUP_HEAD_HAVEFILESHA256))) + { + SCLogDebug("disabling sha256 for flow"); + FileDisableSha256(pflow, STREAM_TOSERVER); + } + /* see if this sgh requires us to consider filesize */ if (pflow->sgh_toserver == NULL || !(pflow->sgh_toserver->flags & SIG_GROUP_HEAD_HAVEFILESIZE)) @@ -1909,6 +1918,14 @@ end: FileDisableSha1(pflow, STREAM_TOCLIENT); } + /* check if this flow needs sha256, if not disable it */ + if (!FileForceSha256() && (pflow->sgh_toclient == NULL || + !(pflow->sgh_toclient->flags & SIG_GROUP_HEAD_HAVEFILESHA256))) + { + SCLogDebug("disabling sha256 for flow"); + FileDisableSha256(pflow, STREAM_TOCLIENT); + } + /* see if this sgh requires us to consider filesize */ if (pflow->sgh_toclient == NULL || !(pflow->sgh_toclient->flags & SIG_GROUP_HEAD_HAVEFILESIZE)) @@ -2185,6 +2202,22 @@ int SignatureIsFileSha1Inspecting(Signature *s) return 0; } +/** + * \brief Check if a signature contains the filesha256 keyword. + * + * \param s signature + * + * \retval 0 no + * \retval 1 yes + */ +int SignatureIsFileSha256Inspecting(Signature *s) +{ + if ((s != NULL) && (s->file_flags & FILE_SIG_NEED_SHA256)) + return 1; + + return 0; +} + /** * \brief Check if a signature contains the filesize keyword. * @@ -4409,6 +4442,7 @@ void SigTableSetup(void) DetectFilemagicRegister(); DetectFileMd5Register(); DetectFileSha1Register(); + DetectFileSha256Register(); DetectFilesizeRegister(); DetectAppLayerEventRegister(); DetectHttpUARegister(); diff --git a/src/detect.h b/src/detect.h index b3b947f5ed..260f23f7cb 100644 --- a/src/detect.h +++ b/src/detect.h @@ -938,12 +938,13 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HEAD_HAVEFILEMD5 (1 << 21) #define SIG_GROUP_HEAD_HAVEFILESIZE (1 << 22) #define SIG_GROUP_HEAD_HAVEFILESHA1 (1 << 23) +#define SIG_GROUP_HEAD_HAVEFILESHA256 (1 << 24) -#define SIG_GROUP_HEAD_MPM_DNSQUERY (1 << 24) -#define SIG_GROUP_HEAD_MPM_TLSSNI (1 << 25) -#define SIG_GROUP_HEAD_MPM_TLSISSUER (1 << 26) -#define SIG_GROUP_HEAD_MPM_TLSSUBJECT (1 << 27) -#define SIG_GROUP_HEAD_MPM_FD_SMTP (1 << 28) +#define SIG_GROUP_HEAD_MPM_DNSQUERY (1 << 25) +#define SIG_GROUP_HEAD_MPM_TLSSNI (1 << 26) +#define SIG_GROUP_HEAD_MPM_TLSISSUER (1 << 27) +#define SIG_GROUP_HEAD_MPM_TLSSUBJECT (1 << 28) +#define SIG_GROUP_HEAD_MPM_FD_SMTP (1 << 29) #define APP_MPMS_MAX 21 @@ -1281,6 +1282,7 @@ int SignatureIsFilestoring(Signature *); int SignatureIsFilemagicInspecting(Signature *); int SignatureIsFileMd5Inspecting(Signature *); int SignatureIsFileSha1Inspecting(Signature *s); +int SignatureIsFileSha256Inspecting(Signature *s); int SignatureIsFilesizeInspecting(Signature *); int DetectRegisterThreadCtxFuncs(DetectEngineCtx *, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int); diff --git a/src/flow.h b/src/flow.h index 182f547c9f..199b17ee94 100644 --- a/src/flow.h +++ b/src/flow.h @@ -105,6 +105,10 @@ typedef struct AppLayerParserState_ AppLayerParserState; #define FLOW_FILE_NO_SHA1_TS 0x04000000 #define FLOW_FILE_NO_SHA1_TC 0x08000000 +/** no sha256 on files in this flow */ +#define FLOW_FILE_NO_SHA256_TS 0x10000000 +#define FLOW_FILE_NO_SHA256_TC 0x20000000 + /** no size tracking of files in this flow */ #define FLOW_FILE_NO_SIZE_TS 0x40000000 #define FLOW_FILE_NO_SIZE_TC 0x80000000 diff --git a/src/log-file.c b/src/log-file.c index 73cde22685..bd5a5855eb 100644 --- a/src/log-file.c +++ b/src/log-file.c @@ -298,6 +298,14 @@ static void LogFileWriteJsonRecord(LogFileLogThread *aft, const Packet *p, const } fprintf(fp, "\", "); } + if (ff->flags & FILE_SHA256) { + fprintf(fp, "\"sha256\": \""); + size_t x; + for (x = 0; x < sizeof(ff->sha256); x++) { + fprintf(fp, "%02x", ff->sha256[x]); + } + fprintf(fp, "\", "); + } #endif break; case FILE_STATE_TRUNCATED: diff --git a/src/log-filestore.c b/src/log-filestore.c index b87473ee0c..d6be8f5f80 100644 --- a/src/log-filestore.c +++ b/src/log-filestore.c @@ -269,6 +269,14 @@ static void LogFilestoreLogCloseMetaFile(const File *ff) } fprintf(fp, "\n"); } + if (ff->flags & FILE_SHA256) { + fprintf(fp, "SHA256: "); + size_t x; + for (x = 0; x < sizeof(ff->sha256); x++) { + fprintf(fp, "%02x", ff->sha256[x]); + } + fprintf(fp, "\n"); + } #endif break; case FILE_STATE_TRUNCATED: diff --git a/src/output-json-file.c b/src/output-json-file.c index 76ad4c3db5..fb39bef720 100644 --- a/src/output-json-file.c +++ b/src/output-json-file.c @@ -143,6 +143,15 @@ static void FileWriteJsonRecord(JsonFileLogThread *aft, const Packet *p, const F } json_object_set_new(fjs, "sha1", json_string(s)); } + if (ff->flags & FILE_SHA256) { + size_t x; + int i; + char s[256]; + for (i = 0, x = 0; x < sizeof(ff->sha256); x++) { + i += snprintf(&s[i], 255-i, "%02x", ff->sha256[x]); + } + json_object_set_new(fjs, "sha256", json_string(s)); + } #endif break; case FILE_STATE_TRUNCATED: diff --git a/src/util-error.c b/src/util-error.c index 8b6d48afe8..7e13f67d8a 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -328,6 +328,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_NO_FILES_FOR_PROTOCOL); CASE_CODE (SC_ERR_INVALID_HASH); CASE_CODE (SC_ERR_NO_SHA1_SUPPORT); + CASE_CODE (SC_ERR_NO_SHA256_SUPPORT); } return "UNKNOWN_ERROR"; diff --git a/src/util-error.h b/src/util-error.h index 312ace1d7a..6aef68cbb9 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -318,6 +318,7 @@ typedef enum { SC_ERR_NO_FILES_FOR_PROTOCOL, SC_ERR_INVALID_HASH, SC_ERR_NO_SHA1_SUPPORT, + SC_ERR_NO_SHA256_SUPPORT, } SCError; const char *SCErrorToString(SCError); diff --git a/src/util-file.c b/src/util-file.c index 82efb90e67..f44549c6aa 100644 --- a/src/util-file.c +++ b/src/util-file.c @@ -56,6 +56,11 @@ static int g_file_force_md5 = 0; */ static int g_file_force_sha1 = 0; +/** \brief switch to force sha256 calculation on all files + * regardless of the rules. + */ +static int g_file_force_sha256 = 0; + /** \brief switch to force tracking off all files * regardless of the rules. */ @@ -84,6 +89,11 @@ void FileForceSha1Enable(void) g_file_force_sha1 = 1; } +void FileForceSha256Enable(void) +{ + g_file_force_sha256 = 1; +} + int FileForceFilestore(void) { return g_file_force_filestore; @@ -104,6 +114,11 @@ int FileForceSha1(void) return g_file_force_sha1; } +int FileForceSha256(void) +{ + return g_file_force_sha256; +} + void FileForceTrackingEnable(void) { g_file_force_tracking = 1; @@ -306,6 +321,8 @@ static void FileFree(File *ff) HASH_Destroy(ff->md5_ctx); if (ff->sha1_ctx) HASH_Destroy(ff->sha1_ctx); + if (ff->sha256_ctx) + HASH_Destroy(ff->sha256_ctx); #endif SCFree(ff); } @@ -383,6 +400,9 @@ static int AppendData(File *file, const uint8_t *data, uint32_t data_len) if (file->sha1_ctx) { HASH_Update(file->sha1_ctx, data, data_len); } + if (file->sha256_ctx) { + HASH_Update(file->sha256_ctx, data, data_len); + } #endif SCReturnInt(0); } @@ -425,6 +445,10 @@ int FileAppendData(FileContainer *ffc, const uint8_t *data, uint32_t data_len) HASH_Update(ffc->tail->sha1_ctx, data, data_len); SCReturnInt(0); } + if (ffc->tail->sha256_ctx) { + HASH_Update(ffc->tail->sha256_ctx, data, data_len); + SCReturnInt(0); + } #endif if (g_file_force_tracking || (!(ffc->tail->flags & FILE_NOTRACK))) SCReturnInt(0); @@ -497,6 +521,10 @@ File *FileOpenFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg, SCLogDebug("not doing sha1 for this file"); ff->flags |= FILE_NOSHA1; } + if (flags & FILE_NOSHA256) { + SCLogDebug("not doing sha256 for this file"); + ff->flags |= FILE_NOSHA256; + } if (flags & FILE_USE_DETECT) { SCLogDebug("considering content_inspect tracker when pruning"); ff->flags |= FILE_USE_DETECT; @@ -515,6 +543,12 @@ File *FileOpenFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg, HASH_Begin(ff->sha1_ctx); } } + if (!(ff->flags & FILE_NOSHA256) || g_file_force_sha256) { + ff->sha256_ctx = HASH_Create(HASH_AlgSHA256); + if (ff->sha256_ctx != NULL) { + HASH_Begin(ff->sha256_ctx); + } + } #endif ff->state = FILE_STATE_OPENED; @@ -554,6 +588,8 @@ static int FileCloseFilePtr(File *ff, const uint8_t *data, HASH_Update(ff->md5_ctx, data, data_len); if (ff->sha1_ctx) HASH_Update(ff->sha1_ctx, data, data_len); + if (ff->sha256_ctx) + HASH_Update(ff->sha256_ctx, data, data_len); #endif } else { if (AppendData(ff, data, data_len) != 0) { @@ -586,6 +622,11 @@ static int FileCloseFilePtr(File *ff, const uint8_t *data, HASH_End(ff->sha1_ctx, ff->sha1, &len, sizeof(ff->sha1)); ff->flags |= FILE_SHA1; } + if (ff->sha256_ctx) { + unsigned int len = 0; + HASH_End(ff->sha256_ctx, ff->sha256, &len, sizeof(ff->sha256)); + ff->flags |= FILE_SHA256; + } #endif } @@ -760,6 +801,45 @@ void FileDisableSha1(Flow *f, uint8_t direction) SCReturn; } +/** + * \brief disable file sha256 calc for this flow + * + * \param f *LOCKED* flow + * \param direction flow direction + */ +void FileDisableSha256(Flow *f, uint8_t direction) +{ + File *ptr = NULL; + + SCEnter(); + + DEBUG_ASSERT_FLOW_LOCKED(f); + + if (direction == STREAM_TOSERVER) + f->flags |= FLOW_FILE_NO_SHA256_TS; + else + f->flags |= FLOW_FILE_NO_SHA256_TC; + + FileContainer *ffc = AppLayerParserGetFiles(f->proto, f->alproto, f->alstate, direction); + if (ffc != NULL) { + for (ptr = ffc->head; ptr != NULL; ptr = ptr->next) { + SCLogDebug("disabling sha256 for file %p from direction %s", + ptr, direction == STREAM_TOSERVER ? "toserver":"toclient"); + ptr->flags |= FILE_NOSHA256; + +#ifdef HAVE_NSS + /* destroy any ctx we may have so far */ + if (ptr->sha256_ctx != NULL) { + HASH_Destroy(ptr->sha256_ctx); + ptr->sha256_ctx = NULL; + } +#endif + } + } + + SCReturn; +} + /** * \brief disable file size tracking for this flow * @@ -809,7 +889,8 @@ void FileDisableStoringForFile(File *ff) ff->flags |= FILE_NOSTORE; if (ff->state == FILE_STATE_OPENED && FileSize(ff) >= (uint64_t)FileMagicSize()) { - if (g_file_force_md5 == 0 && g_file_force_sha1 == 0 && g_file_force_tracking == 0) { + if (g_file_force_md5 == 0 && g_file_force_sha1 == 0 && g_file_force_sha256 == 0 + && g_file_force_tracking == 0) { (void)FileCloseFilePtr(ff, NULL, 0, (FILE_TRUNCATED|FILE_NOSTORE)); } diff --git a/src/util-file.h b/src/util-file.h index 0c476bd9f4..fa9d75276b 100644 --- a/src/util-file.h +++ b/src/util-file.h @@ -193,6 +193,10 @@ void FileDisableSha1(Flow *f, uint8_t); void FileForceSha1Enable(void); int FileForceSha1(void); +void FileDisableSha256(Flow *f, uint8_t); +void FileForceSha256Enable(void); +int FileForceSha256(void); + void FileForceTrackingEnable(void); void FileStoreAllFiles(FileContainer *); diff --git a/src/util-lua-common.c b/src/util-lua-common.c index 4b712b9f62..3c9e7718d9 100644 --- a/src/util-lua-common.c +++ b/src/util-lua-common.c @@ -603,9 +603,20 @@ static int LuaCallbackFileInfoPushToStackFromFile(lua_State *luastate, const Fil strlcat(sha1, one, sizeof(sha1)); } } + char sha256[65] = ""; + char *sha256ptr = sha256; + if (file->flags & FILE_SHA256) { + size_t x; + for (x = 0; x < sizeof(file->sha256); x++) { + char one[3] = ""; + snprintf(one, sizeof(one), "%02x", file->sha256[x]); + strlcat(sha256, one, sizeof(sha256)); + } + } #else char *md5ptr = NULL; char *sha1ptr = NULL; + char *sha256ptr = NULL; #endif lua_pushnumber(luastate, file->file_id); @@ -615,6 +626,7 @@ static int LuaCallbackFileInfoPushToStackFromFile(lua_State *luastate, const Fil lua_pushstring (luastate, file->magic); lua_pushstring(luastate, md5ptr); lua_pushstring(luastate, sha1ptr); + lua_pushstring(luastate, sha256ptr); return 6; }