From dd53acce112e59a9ba35e3389c9bad4ea81480ca Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Mon, 15 Sep 2008 15:33:09 +0200 Subject: [PATCH] Tokenize params too. Signed-off-by: Florent Bruneau --- postlicyd/Makefile | 10 ++- postlicyd/config.c | 19 ++++-- postlicyd/filter.c | 28 ++++++++- postlicyd/filter.h | 11 +++- postlicyd/param_tokens.sh | 124 ++++++++++++++++++++++++++++++++++++++ postlicyd/rbl.c | 78 ++++++++++++++---------- 6 files changed, 225 insertions(+), 45 deletions(-) create mode 100755 postlicyd/param_tokens.sh diff --git a/postlicyd/Makefile b/postlicyd/Makefile index 3d49ba2..7605bc8 100644 --- a/postlicyd/Makefile +++ b/postlicyd/Makefile @@ -34,12 +34,18 @@ include ../mk/tc.mk PROGRAMS = postlicyd GENERATED = policy_tokens.h policy_tokens.c \ filter_tokens.h filter_tokens.c \ - hook_tokens.h hook_tokens.c + hook_tokens.h hook_tokens.c \ + param_tokens.h param_tokens.c TESTS = test-rbl -postlicyd_SOURCES = main-postlicyd.c ../common/lib.a filter.c config.c greylist.c rbl.c $(GENERATED) +FILTERS = rbl.c greylist.c + +postlicyd_SOURCES = main-postlicyd.c ../common/lib.a filter.c config.c $(FILTERS) $(GENERATED) postlicyd_LIBADD = $(TC_LIBS) tst-rbl_SOURCES = tst-rbl.c +hook_tokens.h hook_tokens.c: $(FILTERS) +param_tokens.c param_tokens.h: $(FILTERS) config.c + include ../mk/common.mk diff --git a/postlicyd/config.c b/postlicyd/config.c index 21e49d1..67cfb29 100644 --- a/postlicyd/config.c +++ b/postlicyd/config.c @@ -38,6 +38,10 @@ #include "config.h" #include "str.h" +#define config_param_register(Param) + +config_param_register("first_filter"); + struct config_t { A(filter_t) filters; A(filter_params_t) params; @@ -235,9 +239,11 @@ read_param_value: READ_STRING("parameter value", value, value_len, ;); { filter_params_t param; - param.name = m_strdup(key); - param.value = m_strdup(value); - array_add(config->params, param); + param.type = param_tokenize(key, key_len); + if (param.type != ATK_UNKNOWN) { + param.value = m_strdup(value); + array_add(config->params, param); + } } goto read_section; @@ -266,9 +272,10 @@ read_filter: key + 3, filter.name); } } else { - if (!filter_add_param(&filter, key, key_len, value, value_len)) { - goto error; - } + /* filter_add_param failure mean unknown type or unsupported type. + * this are non-fatal errors. + */ + (void)filter_add_param(&filter, key, key_len, value, value_len); } } READ_NEXT(;); diff --git a/postlicyd/filter.c b/postlicyd/filter.c index e5b8f35..bbb08c5 100644 --- a/postlicyd/filter.c +++ b/postlicyd/filter.c @@ -41,6 +41,7 @@ static filter_runner_t runners[FTK_count]; static filter_constructor_t constructors[FTK_count]; static filter_destructor_t destructors[FTK_count]; static bool hooks[FTK_count][HTK_count]; +static bool params[FTK_count][ATK_count]; filter_type_t filter_register(const char *type, filter_constructor_t constructor, filter_destructor_t destructor, filter_runner_t runner) @@ -70,6 +71,20 @@ filter_result_t filter_hook_register(filter_type_t filter, return tok; } +filter_param_id_t filter_param_register(filter_type_t filter, + const char *name) +{ + filter_param_id_t tok = param_tokenize(name, m_strlen(name)); + CHECK_FILTER(filter); + CHECK_PARAM(tok); + + syslog(LOG_INFO, "param %s registered for filter type %s", name, + ftokens[filter]); + + params[filter][tok] = true; + return tok; +} + bool filter_build(filter_t *filter) { bool ret = true; @@ -140,7 +155,16 @@ bool filter_add_param(filter_t *filter, const char *name, ssize_t name_len, const char *value, ssize_t value_len) { filter_params_t param; - param.name = m_strdup(name); + param.type = param_tokenize(name, name_len); + if (param.type == ATK_UNKNOWN) { + syslog(LOG_ERR, "unknown parameter %.*s", name_len, name); + return false; + } + if (!params[filter->type][param.type]) { + syslog(LOG_ERR, "hook %s is not valid for filter %s", + atokens[param.type], ftokens[filter->type]); + return false; + } param.value = m_strdup(value); array_add(filter->params, param); return true; @@ -156,7 +180,7 @@ bool filter_add_hook(filter_t *filter, const char *name, ssize_t name_len, return false; } if (!hooks[filter->type][hook.type]) { - syslog(LOG_ERR, "hook %s is valid for filter %s", + syslog(LOG_ERR, "hook %s not is valid for filter %s", htokens[hook.type], ftokens[filter->type]); return false; } diff --git a/postlicyd/filter.h b/postlicyd/filter.h index 986e6cf..5037868 100644 --- a/postlicyd/filter.h +++ b/postlicyd/filter.h @@ -39,11 +39,13 @@ #include "common.h" #include "filter_tokens.h" #include "hook_tokens.h" +#include "param_tokens.h" #include "query.h" #include "array.h" typedef filter_token filter_type_t; typedef hook_token filter_result_t; +typedef param_token filter_param_id_t; typedef struct filter_hook_t { filter_result_t type; @@ -55,7 +57,7 @@ typedef struct filter_hook_t { ARRAY(filter_hook_t) typedef struct filter_params_t { - char *name; + filter_param_id_t type; char *value; } filter_params_t; ARRAY(filter_params_t) @@ -78,6 +80,9 @@ ARRAY(filter_t) #define CHECK_HOOK(Hook) \ assert(Hook != HTK_UNKNOWN && Hook != HTK_count \ && "Unknown hook") +#define CHECK_PARAM(Param) \ + assert(Param != ATK_UNKNOWN && Param != ATK_count \ + && "Unknown param") typedef filter_result_t (*filter_runner_t)(const filter_t *filter, const query_t *query); @@ -91,6 +96,9 @@ filter_type_t filter_register(const char *type, filter_constructor_t constructor __attribute__((nonnull(2))) filter_result_t filter_hook_register(filter_type_t filter, const char *name); +__attribute__((nonnull(2))) +filter_param_id_t filter_param_register(filter_type_t filter, const char *name); + __attribute__((nonnull(1))) static inline void filter_init(filter_t *filter) { @@ -148,7 +156,6 @@ static inline void filter_hook_wipe(filter_hook_t *hook) __attribute__((nonnull(1))) static inline void filter_params_wipe(filter_params_t *param) { - p_delete(¶m->name); p_delete(¶m->value); } diff --git a/postlicyd/param_tokens.sh b/postlicyd/param_tokens.sh new file mode 100755 index 0000000..85786ae --- /dev/null +++ b/postlicyd/param_tokens.sh @@ -0,0 +1,124 @@ +#! /bin/sh -e + +die() { + echo "$@" 1>&2 + exit 2 +} + +do_hdr() { + cat <//g' +%{ +`do_hdr` + +#include "str.h" +#include "`echo "${this%.sh}"`.h" + +static const struct tok * +tokenize_aux(const char *str, unsigned int len); + +%} +struct tok { const char *name; int val; }; +%% +`grep_self "$0" | do_tokens` +%% + +const char *atokens[ATK_count] = { +`grep_self "$0" | sed -e 's/.*/ "&",/'` +}; + +param_token param_tokenize(const char *s, ssize_t len) +{ + if (len < 0) + len = m_strlen(s); + + if (len) { + const struct tok *res = tokenize_aux(s, len); + return res ? res->val : ATK_UNKNOWN; + } else { + return ATK_UNKNOWN; + } +} +EOF +} + +grep_self() { + ( ( grep 'filter_param_register(.*, *"' *.c | sed 's/.*filter_param_register(.*, *"\(.*\)" *).*/\1/' ) && + ( grep 'config_param_register( *".*' config.c | sed 's/.*config_param_register( *"\(.*\)".*/\1/' ) ) | sort | uniq +} + +trap "rm -f $1" 1 2 3 15 +rm -f $1 +case "$1" in + *.h) do_h > $1;; + *.c) do_c > $1;; + *) die "you must ask for the 'h' or 'c' generation";; +esac +chmod -w $1 + +exit 0 diff --git a/postlicyd/rbl.c b/postlicyd/rbl.c index 5267bf6..ed4ab2b 100644 --- a/postlicyd/rbl.c +++ b/postlicyd/rbl.c @@ -253,17 +253,18 @@ static bool rbl_filter_constructor(filter_t *filter) } foreach (filter_params_t *param, filter->params) { - /* file parameter is: - * [no]lock:weight:filename - * valid options are: - * - lock: memlock the database in memory. - * - nolock: don't memlock the database in memory [default]. - * - \d+: a number describing the weight to give to the match - * the given list [mandatory] - * the file pointed by filename MUST be a valid ip list issued from - * the rsync (or equivalent) service of a (r)bl. - */ - if (strcmp(param->name, "file") == 0) { + switch (param->type) { + /* file parameter is: + * [no]lock:weight:filename + * valid options are: + * - lock: memlock the database in memory. + * - nolock: don't memlock the database in memory [default]. + * - \d+: a number describing the weight to give to the match + * the given list [mandatory] + * the file pointed by filename MUST be a valid ip list issued from + * the rsync (or equivalent) service of a (r)bl. + */ + case ATK_FILE: { bool lock = false; int weight = 0; rbldb_t *rbl = NULL; @@ -271,13 +272,15 @@ static bool rbl_filter_constructor(filter_t *filter) const char *p = m_strchrnul(param->value, ':'); char *next = NULL; for (int i = 0 ; i < 3 ; ++i) { - PARSE_CHECK(i == 2 || *p, - "file parameter must contains a locking state and a weight option"); + PARSE_CHECK(i == 2 || *p, + "file parameter must contains a locking state " + "and a weight option"); switch (i) { case 0: if ((p - current) == 4 && strncmp(current, "lock", 4) == 0) { lock = true; - } else if ((p - current) == 6 && strncmp(current, "nolock", 6) == 0) { + } else if ((p - current) == 6 + && strncmp(current, "nolock", 6) == 0) { lock = false; } else { PARSE_CHECK(false, "illegal locking state %.*s", @@ -303,32 +306,33 @@ static bool rbl_filter_constructor(filter_t *filter) current = p + 1; p = m_strchrnul(current, ':'); } - - /* hard_threshold parameter is an integer. - * If the matching score of a ip get a score gretter than this threshold, - * the hook "hard_match" is called. - * hard_threshold = 0 means, that all matches are hard matches. - * default is 0; - */ - } else if (strcmp(param->name, "hard_threshold") == 0) { + } break; + + /* hard_threshold parameter is an integer. + * If the matching score is greater than this threshold, + * the hook "hard_match" is called. + * hard_threshold = 0 means, that all matches are hard matches. + * default is 0; + */ + case ATK_HARD_THRESHOLD: { char *next; data->hard_threshold = strtol(param->value, &next, 10); PARSE_CHECK(*next, "invalid threshold value %s", param->value); - - /* soft_threshold parameter is an integer. - * if the matching score of an ip get a score getter than this threshold - * and smaller or equal than the hard_threshold, the hook "soft_match" - * is called. - * default is 0; - */ - } else if (strcmp(param->name, "hard_threshold") == 0) { + } break; + + /* soft_threshold parameter is an integer. + * if the matching score is greater than this threshold + * and smaller or equal than the hard_threshold, the hook "soft_match" + * is called. + * default is 0; + */ + case ATK_SOFT_THRESHOLD: { char *next; data->soft_threshold = strtol(param->value, &next, 10); PARSE_CHECK(*next, "invalid threshold value %s", param->value); + } break; - } else { - syslog(LOG_INFO, "ignored parameter %s in rbl filter %s", - filter->name, param->name); + default: break; } }} @@ -377,10 +381,18 @@ static int rbl_init(void) { filter_type_t type = filter_register("rbl", rbl_filter_constructor, rbl_filter_destructor, rbl_filter); + /* Hooks. + */ (void)filter_hook_register(type, "error"); (void)filter_hook_register(type, "fail"); (void)filter_hook_register(type, "hard_match"); (void)filter_hook_register(type, "soft_match"); + + /* Parameters. + */ + (void)filter_param_register(type, "file"); + (void)filter_param_register(type, "hard_threshold"); + (void)filter_param_register(type, "soft_threshold"); return 0; } module_init(rbl_init); -- 2.20.1