Add negation to filename and fileext, use same syntax as with content.

remotes/origin/master-1.2.x
Victor Julien 14 years ago
parent 32fb9f375d
commit 70f0d3d2e7

@ -51,14 +51,6 @@
#include "stream-tcp.h"
#include "detect-fileext.h"
/**
* \brief Regex for parsing the fileext string
*/
#define PARSE_REGEX "^\\s*\"?\\s*(.+)\\s*\"?\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectFileextMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t, void *, Signature *, SigMatch *);
static int DetectFileextSetup (DetectEngineCtx *, Signature *, char *);
void DetectFileextRegisterTests(void);
@ -76,27 +68,7 @@ void DetectFileextRegister(void) {
sigmatch_table[DETECT_FILEEXT].Free = DetectFileextFree;
sigmatch_table[DETECT_FILEEXT].RegisterTests = DetectFileextRegisterTests;
const char *eb;
int eo;
int opts = 0;
SCLogDebug("registering fileext rule option");
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL);
if (parse_regex == NULL) {
SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s",
PARSE_REGEX, eo, eb);
goto error;
}
parse_regex_study = pcre_study(parse_regex, 0, &eb);
if (eb != NULL) {
SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
goto error;
}
return;
error:
return;
}
@ -137,6 +109,7 @@ int DetectFileextMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
if (file->name[offset - 1] == '.' &&
SCMemcmp(file->name + offset, fileext->ext, fileext->len) == 0)
{
if (!(fileext->flags & DETECT_CONTENT_NEGATED)) {
ret = 1;
SCLogDebug("File ext found");
@ -145,8 +118,14 @@ int DetectFileextMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
}
}
}
}
SCMutexUnlock(&f->files_m);
if (ret == 0 && fileext->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated match");
ret = 1;
}
SCReturnInt(ret);
}
@ -161,53 +140,31 @@ int DetectFileextMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
DetectFileextData *DetectFileextParse (char *str)
{
DetectFileextData *fileext = NULL;
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
if (ret < 1 || ret > 3) {
SCLogError(SC_ERR_PCRE_MATCH, "invalid fileext option");
goto error;
}
if (ret > 1) {
const char *str_ptr;
res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error;
}
/* We have a correct filename option */
fileext = SCMalloc(sizeof(DetectFileextData));
if (fileext == NULL)
goto error;
memset(fileext, 0x00, sizeof(DetectFileextData));
/* Remove quotes if any and copy the filename */
if (str_ptr[0] == '\"') {
fileext->ext = (uint8_t *)SCStrdup((char*)str_ptr + 1);
} else {
fileext->ext = (uint8_t *)SCStrdup((char*)str_ptr);
}
if (fileext->ext[strlen((char *)fileext->ext) - 1] == '\"') {
fileext->ext[strlen((char *)fileext->ext) - 1] = '\0';
}
if (fileext->ext == NULL) {
if (DetectParseContentString (str, &fileext->ext, &fileext->len, &fileext->flags) == -1) {
goto error;
}
fileext->len = strlen((char *) fileext->ext);
fileext->bm_ctx = BoyerMooreCtxInit(fileext->ext, fileext->len);
if (fileext->bm_ctx == NULL) {
goto error;
SCLogDebug("flags %02X", fileext->flags);
if (fileext->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated fileext");
}
BoyerMooreCtxToNocase(fileext->bm_ctx, fileext->ext, fileext->len);
SCLogDebug("will look for fileext %s", fileext->ext);
#ifdef DEBUG
if (SCLogDebugEnabled()) {
char *ext = SCMalloc(fileext->len + 1);
memcpy(ext, fileext->ext, fileext->len);
ext[fileext->len] = '\0';
SCLogDebug("will look for fileext %s", ext);
}
#endif
return fileext;
@ -275,9 +232,6 @@ error:
void DetectFileextFree(void *ptr) {
if (ptr != NULL) {
DetectFileextData *fileext = (DetectFileextData *)ptr;
if (fileext->bm_ctx != NULL) {
BoyerMooreCtxDeInit(fileext->bm_ctx);
}
SCFree(fileext);
}
}

@ -23,14 +23,13 @@
#ifndef __DETECT_FILEEXT_H__
#define __DETECT_FILEEXT_H__
#include "util-spm-bm.h"
#include "util-spm-bm.h"
typedef struct DetectFileextData_ {
uint8_t *ext; /** file extension to match */
uint16_t len; /** length of the file */
BmCtx *bm_ctx;
uint8_t flags;
uint32_t flags;
} DetectFileextData;
/* prototypes */

@ -18,6 +18,7 @@
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
*
*/
@ -49,14 +50,6 @@
#include "detect-filename.h"
/**
* \brief Regex for parsing the protoversion string
*/
#define PARSE_REGEX "^\\s*\"?\\s*(.+)\\s*\"?\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int DetectFilenameMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t, void *, Signature *, SigMatch *);
static int DetectFilenameSetup (DetectEngineCtx *, Signature *, char *);
void DetectFilenameRegisterTests(void);
@ -74,27 +67,7 @@ void DetectFilenameRegister(void) {
sigmatch_table[DETECT_FILENAME].Free = DetectFilenameFree;
sigmatch_table[DETECT_FILENAME].RegisterTests = DetectFilenameRegisterTests;
const char *eb;
int eo;
int opts = 0;
SCLogDebug("registering filename rule option");
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL);
if (parse_regex == NULL) {
SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s",
PARSE_REGEX, eo, eb);
goto error;
}
parse_regex_study = pcre_study(parse_regex, 0, &eb);
if (eb != NULL) {
SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
goto error;
}
return;
error:
return;
}
@ -130,22 +103,37 @@ int DetectFilenameMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
file->name_len, filename->bm_ctx->bmGs,
filename->bm_ctx->bmBc) != NULL)
{
#ifdef DEBUG
if (SCLogDebugEnabled()) {
char *name = SCMalloc(filename->len + 1);
memcpy(name, filename->name, filename->len);
name[filename->len] = '\0';
SCLogDebug("will look for filename %s", name);
}
#endif
if (!(filename->flags & DETECT_CONTENT_NEGATED)) {
ret = 1;
SCLogDebug("File %s found", file->name);
/* Stop searching */
break;
}
}
}
}
SCMutexUnlock(&f->files_m);
if (ret == 0 && filename->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated match");
ret = 1;
}
SCReturnInt(ret);
}
/**
* \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
* \brief Parse the filename keyword
*
* \param idstr Pointer to the user provided id option
* \param idstr Pointer to the user provided option
*
* \retval filename pointer to DetectFilenameData on success
* \retval NULL on failure
@ -153,25 +141,6 @@ int DetectFilenameMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
DetectFilenameData *DetectFilenameParse (char *str)
{
DetectFilenameData *filename = NULL;
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
if (ret < 1 || ret > 3) {
SCLogError(SC_ERR_PCRE_MATCH, "invalid filename option");
goto error;
}
if (ret > 1) {
const char *str_ptr;
res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
goto error;
}
/* We have a correct filename option */
filename = SCMalloc(sizeof(DetectFilenameData));
@ -180,37 +149,36 @@ DetectFilenameData *DetectFilenameParse (char *str)
memset(filename, 0x00, sizeof(DetectFilenameData));
/* Remove quotes if any and copy the filename */
if (str_ptr[0] == '\"') {
filename->name = (uint8_t *)SCStrdup((char*)str_ptr + 1);
} else {
filename->name = (uint8_t *)SCStrdup((char*)str_ptr);
}
if (filename->name[strlen((char *)filename->name) - 1] == '\"') {
filename->name[strlen((char *)filename->name) - 1] = '\0';
}
if (filename->name == NULL) {
if (DetectParseContentString (str, &filename->name, &filename->len, &filename->flags) == -1) {
goto error;
}
filename->len = strlen((char *) filename->name);
filename->bm_ctx = BoyerMooreCtxInit(filename->name, filename->len);
if (filename->bm_ctx == NULL) {
goto error;
}
BoyerMooreCtxToNocase(filename->bm_ctx, filename->name, filename->len);
SCLogDebug("will look for filename %s", filename->name);
SCLogDebug("flags %02X", filename->flags);
if (filename->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("negated filename");
}
BoyerMooreCtxToNocase(filename->bm_ctx, filename->name, filename->len);
#ifdef DEBUG
if (SCLogDebugEnabled()) {
char *name = SCMalloc(filename->len + 1);
memcpy(name, filename->name, filename->len);
name[filename->len] = '\0';
SCLogDebug("will look for filename %s", name);
}
#endif
return filename;
error:
if (filename != NULL)
DetectFilenameFree(filename);
return NULL;
}
/**

@ -23,13 +23,14 @@
#ifndef __DETECT_FILENAME_H__
#define __DETECT_FILENAME_H__
#include "util-spm-bm.h"
typedef struct DetectFilenameData {
uint8_t *name; /** name of the file to match */
BmCtx *bm_ctx; /** BM context */
uint16_t len; /** name length */
uint8_t flags;
uint32_t flags;
} DetectFilenameData;
/* prototypes */

@ -2029,6 +2029,197 @@ error:
return NULL;
}
/**
* \brief Parse a content string, ie "abc|DE|fgh"
*
* \param content_str null terminated string containing the content
* \param result result pointer to pass the fully parsed byte array
* \param result_len size of the resulted data
* \param flags flags to be set by this parsing function
*
* \retval -1 error
* \retval 0 ok
*
* \initonly
*/
int DetectParseContentString (char *contentstr, uint8_t **result, uint16_t *result_len, uint32_t *result_flags)
{
char *str = NULL;
char *temp = NULL;
uint16_t len;
uint16_t pos = 0;
uint16_t slen = 0;
uint8_t *content = NULL;
uint16_t content_len = 0;
uint32_t flags = 0;
if ((temp = SCStrdup(contentstr)) == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory. Exiting...");
exit(EXIT_FAILURE);
}
if (strlen(temp) == 0) {
SCFree(temp);
return -1;
}
/* skip the first spaces */
slen = strlen(temp);
while (pos < slen && isspace(temp[pos])) {
pos++;
}
if (temp[pos] == '!') {
SCFree(temp);
if ((temp = SCStrdup(contentstr + pos + 1)) == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "error allocating memory. exiting...");
exit(EXIT_FAILURE);
}
pos = 0;
flags |= DETECT_CONTENT_NEGATED;
SCLogDebug("negation in place");
}
if (temp[pos] == '\"' && strlen(temp + pos) == 1)
goto error;
if (temp[pos] == '\"' && temp[pos + strlen(temp + pos) - 1] == '\"') {
if ((str = SCStrdup(temp + pos + 1)) == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "error allocating memory. exiting...");
exit(EXIT_FAILURE);
}
str[strlen(temp) - pos - 2] = '\0';
} else if (temp[pos] == '\"' || temp[pos + strlen(temp + pos) - 1] == '\"') {
goto error;
} else {
if ((str = SCStrdup(temp + pos)) == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "error allocating memory. exiting...");
exit(EXIT_FAILURE);
}
}
SCFree(temp);
temp = NULL;
len = strlen(str);
if (len == 0)
goto error;
//SCLogDebug("DetectContentParse: \"%s\", len %" PRIu32 "", str, len);
char converted = 0;
{
uint16_t i, x;
uint8_t bin = 0;
uint8_t escape = 0;
uint8_t binstr[3] = "";
uint8_t binpos = 0;
uint16_t bin_count = 0;
for (i = 0, x = 0; i < len; i++) {
// SCLogDebug("str[%02u]: %c", i, str[i]);
if (str[i] == '|') {
bin_count++;
if (bin) {
bin = 0;
} else {
bin = 1;
}
} else if(!escape && str[i] == '\\') {
escape = 1;
} else {
if (bin) {
if (isdigit(str[i]) ||
str[i] == 'A' || str[i] == 'a' ||
str[i] == 'B' || str[i] == 'b' ||
str[i] == 'C' || str[i] == 'c' ||
str[i] == 'D' || str[i] == 'd' ||
str[i] == 'E' || str[i] == 'e' ||
str[i] == 'F' || str[i] == 'f')
{
// SCLogDebug("part of binary: %c", str[i]);
binstr[binpos] = (char)str[i];
binpos++;
if (binpos == 2) {
uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
binpos = 0;
str[x] = c;
x++;
converted = 1;
}
} else if (str[i] == ' ') {
// SCLogDebug("space as part of binary string");
}
} else if (escape) {
if (str[i] == ':' ||
str[i] == ';' ||
str[i] == '\\' ||
str[i] == '\"')
{
str[x] = str[i];
x++;
} else {
//SCLogDebug("Can't escape %c", str[i]);
goto error;
}
escape = 0;
converted = 1;
} else {
str[x] = str[i];
x++;
}
}
}
if (bin_count % 2 != 0) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid hex code assembly in "
"content - %s. Invalidating signature", str);
goto error;
}
#if 0//def DEBUG
if (SCLogDebugEnabled()) {
for (i = 0; i < x; i++) {
if (isprint(str[i])) SCLogDebug("%c", str[i]);
else SCLogDebug("\\x%02u", str[i]);
}
SCLogDebug("");
}
#endif
if (converted) {
len = x;
}
}
content = SCMalloc(len);
if (content == NULL) {
exit(EXIT_FAILURE);
}
memcpy(content, str, len);
content_len = len;
SCFree(str);
*result = content;
*result_len = content_len;
*result_flags = flags;
SCLogDebug("flags %02X, result_flags %02X", flags, *result_flags);
return 0;
error:
SCFree(str);
SCFree(temp);
if (content != NULL)
SCFree(content);
return -1;
}
/*
* TESTS
*/

@ -70,5 +70,7 @@ int SigMatchListSMBelongsTo(Signature *, SigMatch *);
int DetectParseDupSigHashInit(DetectEngineCtx *);
void DetectParseDupSigHashFree(DetectEngineCtx *);
int DetectParseContentString (char *, uint8_t **, uint16_t *, uint32_t *);
#endif /* __DETECT_PARSE_H__ */

Loading…
Cancel
Save