From 61eddeba259c961cf7e5923460c8fd8734e0731c Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Mon, 14 Mar 2016 22:34:39 +1000 Subject: [PATCH] * add draft of f2b_filter_pcre.so --- src/filters/CMakeLists.txt | 7 ++ src/filters/pcre.c | 165 +++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 src/filters/pcre.c diff --git a/src/filters/CMakeLists.txt b/src/filters/CMakeLists.txt index 99e6565..c88dfb5 100644 --- a/src/filters/CMakeLists.txt +++ b/src/filters/CMakeLists.txt @@ -4,6 +4,13 @@ set(FILTERS "") add_library("f2b_filter_preg" MODULE "preg.c") list(APPEND FILTERS "f2b_filter_preg") +find_library(PCRE_FOUND "pcre") +if (PCRE_FOUND) + add_library("f2b_filter_pcre" MODULE "pcre.c") + target_link_libraries("f2b_filter_pcre" "pcre") + list(APPEND FILTERS "f2b_filter_pcre") +endif () + message(STATUS "- Filters : ${FILTERS}") install(TARGETS ${FILTERS} diff --git a/src/filters/pcre.c b/src/filters/pcre.c new file mode 100644 index 0000000..3df079c --- /dev/null +++ b/src/filters/pcre.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include + +#include "filter.h" + +#include + +#define HOST_REGEX "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})" + +typedef struct f2b_regex_t { + struct f2b_regex_t *next; + int matches; + pcre *regex; + pcre_extra *data; +} f2b_regex_t; + +struct _config { + char id[32]; + char error[256]; + bool icase; + bool study; + bool usejit; + f2b_regex_t *regexps; +}; + +bool +config(cfg_t *cfg, const char *key, const char *value) { + assert(cfg != NULL); + assert(key != NULL); + assert(value != NULL); + + if (strcmp(key, "icase") == 0) { + cfg->icase = (strcmp(value, "yes") == 0) ? true : false; + return true; + } + if (strcmp(key, "study") == 0) { + cfg->study = (strcmp(value, "yes") == 0) ? true : false; + return true; + } + if (strcmp(key, "use_jit") == 0) { + cfg->usejit = (strcmp(value, "yes") == 0) ? true : false; + return true; + } + + return false; +} + +bool +append(cfg_t *cfg, const char *pattern) { + f2b_regex_t *regex = NULL; + int flags = 0; + size_t bufsize; + char *buf = NULL; + char *token = NULL; + const char *errptr = NULL; + int erroffset = 0; + + assert(pattern != NULL); + + if (cfg->icase) + flags |= PCRE_CASELESS; + + if ((token = strstr(pattern, HOST_TOKEN)) == NULL) + return false; + + bufsize = strlen(pattern) + strlen(HOST_REGEX) + 1; + if ((buf = alloca(bufsize)) == NULL) + return false; + + memset(buf, 0x0, bufsize); + strncpy(buf, pattern, token - pattern); + strcat(buf, HOST_REGEX); + strcat(buf, token + strlen(HOST_TOKEN)); + + if ((regex = calloc(1, sizeof(f2b_regex_t))) == NULL) + return false; + + if ((regex->regex = pcre_compile(pattern, flags, &errptr, &erroffset, NULL)) == NULL) { + snprintf(cfg->error, sizeof(cfg->error), "regex compilation failed at %d: %s", erroffset, errptr); + free(regex); + return false; + } + + if (cfg->study) { + flags = PCRE_STUDY_EXTRA_NEEDED; + if (cfg->usejit) + flags |= PCRE_STUDY_JIT_COMPILE; + if ((regex->data = pcre_study(regex->regex, 0, &errptr)) == NULL) { + snprintf(cfg->error, sizeof(cfg->error), "regex learn failed: %s", errptr); + pcre_free(regex->regex); + free(regex); + return false; + } + } + + regex->next = cfg->regexps; + cfg->regexps = regex; + return false; +} + +bool +ready(cfg_t *cfg) { + assert(cfg != NULL); + if (cfg->regexps) + return true; + return false; +} + +const char * +error(cfg_t *cfg) { + assert(cfg != NULL); + + return cfg->error; +} + +bool +match(cfg_t *cfg, const char *line, char *buf, size_t buf_size) { + f2b_regex_t *r = NULL; + enum { OVECSIZE = 30 }; + int ovector[OVECSIZE]; + int flags = 0; + int rc = 0, sc = 0; /* sc = stringcount */ + + assert(cfg != NULL); + assert(line != NULL); + assert(buf != NULL); + + for (r = cfg->regexps; r != NULL; r = r->next) { + rc = pcre_exec(r->regex, r->data, line, strlen(line), 0, flags, &ovector[0], OVECSIZE); + if (rc < 0 && rc == PCRE_ERROR_NOMATCH) + continue; + if (rc < 0) { + snprintf(cfg->error, sizeof(cfg->error), "matched failed with error: %d", rc); + continue; + } + /* matched */ + r->matches++; + sc = (rc) ? rc : OVECSIZE / 3; + rc = pcre_copy_named_substring(r->regex, line, &ovector[0], sc, "host", buf, buf_size); + if (rc < 0) { + snprintf(cfg->error, sizeof(cfg->error), "can't copy matched string: %d", rc); + continue; + } + return true; + } + + return false; +} + +void +destroy(cfg_t *cfg) { + f2b_regex_t *next = NULL, *r = NULL; + + for (r = cfg->regexps; r != NULL; r = next) { + next = r->next; + if (cfg->study) + pcre_free_study(r->data); + pcre_free(&r->regex); + free(r); + } + free(cfg); +}