/** * \brief this function is used to parse filemd5 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 "filemd5" option * * \retval 0 on Success * \retval -1 on Failure */ static int DetectFileMd5Setup (DetectEngineCtx *de_ctx, Signature *s, char *str) { DetectFileMd5Data *filemd5 = NULL; SigMatch *sm = NULL; filemd5 = DetectFileMd5Parse(de_ctx, str); if (filemd5 == NULL) goto error; /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_FILEMD5; sm->ctx = (void *)filemd5; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_FILEMATCH); s->file_flags |= (FILE_SIG_NEED_FILE|FILE_SIG_NEED_MD5); return 0; error: if (filemd5 != NULL) DetectFileMd5Free(filemd5); if (sm != NULL) SCFree(sm); return -1; }
/** * \brief this function is used to parse filemd5 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 "filemd5" option * * \retval 0 on Success * \retval -1 on Failure */ static int DetectFileMd5Setup (DetectEngineCtx *de_ctx, Signature *s, char *str) { DetectFileMd5Data *filemd5 = NULL; SigMatch *sm = NULL; filemd5 = DetectFileMd5Parse(str); if (filemd5 == NULL) goto error; /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_FILEMD5; sm->ctx = (void *)filemd5; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_FILEMATCH); if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } AppLayerHtpNeedFileInspection(); /** \todo remove this once we support more than http */ s->alproto = ALPROTO_HTTP; s->file_flags |= (FILE_SIG_NEED_FILE|FILE_SIG_NEED_MD5); return 0; error: if (filemd5 != NULL) DetectFileMd5Free(filemd5); if (sm != NULL) SCFree(sm); return -1; }
/** * \brief Parse the filemd5 keyword * * \param idstr Pointer to the user provided option * * \retval filemd5 pointer to DetectFileMd5Data on success * \retval NULL on failure */ static DetectFileMd5Data *DetectFileMd5Parse (const DetectEngineCtx *de_ctx, char *str) { DetectFileMd5Data *filemd5 = NULL; FILE *fp = NULL; char *filename = NULL; /* We have a correct filemd5 option */ filemd5 = SCMalloc(sizeof(DetectFileMd5Data)); if (unlikely(filemd5 == NULL)) goto error; memset(filemd5, 0x00, sizeof(DetectFileMd5Data)); if (strlen(str) && str[0] == '!') { filemd5->negated = 1; str++; } filemd5->hash = ROHashInit(18, 16); if (filemd5->hash == NULL) { goto error; } /* get full filename */ filename = DetectLoadCompleteSigPath(de_ctx, str); if (filename == NULL) { goto error; } char line[8192] = ""; fp = fopen(filename, "r"); if (fp == NULL) { SCLogError(SC_ERR_OPENING_RULE_FILE, "opening md5 file %s: %s", filename, strerror(errno)); goto error; } int line_no = 0; while(fgets(line, (int)sizeof(line), fp) != NULL) { size_t len = strlen(line); line_no++; /* ignore comments and empty lines */ if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t') continue; while (isspace(line[--len])); /* Check if we have a trailing newline, and remove it */ len = strlen(line); if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) { line[len - 1] = '\0'; } /* cut off longer lines */ if (strlen(line) > 32) line[32] = 0x00; if (MD5LoadHash(filemd5->hash, line, filename, line_no) != 1) { goto error; } } fclose(fp); fp = NULL; if (ROHashInitFinalize(filemd5->hash) != 1) { goto error; } SCLogInfo("MD5 hash size %u bytes%s", ROHashMemorySize(filemd5->hash), filemd5->negated ? ", negated match" : ""); SCFree(filename); return filemd5; error: if (filemd5 != NULL) DetectFileMd5Free(filemd5); if (fp != NULL) fclose(fp); if (filename != NULL) SCFree(filename); return NULL; }