X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fconfig.c;h=7ea485c379636301d9c25aaacf20849e3a7145d9;hb=2520de08ed80b941f28c9ccb97a3785a507a831d;hp=21e49d1b79f61b42dd2c489c109dfcb7e44aa1f6;hpb=0df827a28124af3bb45cea7a3b80e5d1800bb1e2;p=apps%2Fpfixtools.git diff --git a/postlicyd/config.c b/postlicyd/config.c index 21e49d1..7ea485c 100644 --- a/postlicyd/config.c +++ b/postlicyd/config.c @@ -34,28 +34,63 @@ */ #include "file.h" -#include "filter.h" #include "config.h" #include "str.h" -struct config_t { - A(filter_t) filters; - A(filter_params_t) params; - int entry_point; -}; +#define config_param_register(Param) + +/* Filter to execute on "CONNECT" + */ +config_param_register("client_filter"); + +/* Filter to execute on "MAIL FROM" + */ +config_param_register("sender_filter"); + +/* Filter to execute on "RCPT TO" + */ +config_param_register("recipient_filter"); + +/* Filter to execute on "DATA" + */ +config_param_register("data_filter"); + +/* Filter to execute on "END-OF-DATA" + */ +config_param_register("end_of_data_filter"); + +/* Filter to execute on "ETRN" + */ +config_param_register("etrn_filter"); + +/* Filter to execute on "HELO" + */ +config_param_register("helo_filter"); +config_param_register("ehlo_filter"); + +/* Filter to execute on "VRFY" + */ +config_param_register("verify_filter"); static inline config_t *config_new(void) { config_t *config = p_new(config_t, 1); - config->entry_point = -1; return config; } +static void config_close(config_t *config) +{ + for (int i = 0 ; i < SMTP_count ; ++i) { + config->entry_points[i] = -1; + } + array_deep_wipe(config->filters, filter_wipe); + array_deep_wipe(config->params, filter_params_wipe); +} + void config_delete(config_t **config) { if (*config) { - array_deep_wipe((*config)->filters, filter_wipe); - array_deep_wipe((*config)->params, filter_params_wipe); + config_close(*config); p_delete(config); } } @@ -78,13 +113,46 @@ static bool config_second_pass(config_t *config) break; } }} + if (!ok) { + return false; + } + if (!filter_check_safety(&config->filters)) { + return false; + } + + ok = false; + foreach (filter_param_t *param, config->params) { + switch (param->type) { +#define CASE(Param, State) \ + case ATK_ ## Param ## _FILTER: \ + ok = true; \ + config->entry_points[SMTP_ ## State] \ + = filter_find_with_name(&config->filters, param->value); \ + break; + CASE(CLIENT, CONNECT) + CASE(EHLO, EHLO) + CASE(HELO, HELO) + CASE(SENDER, MAIL) + CASE(RECIPIENT, RCPT) + CASE(DATA, DATA) + CASE(END_OF_DATA, END_OF_MESSAGE) + CASE(VERIFY, VRFY) + CASE(ETRN, ETRN) +#undef CASE + default: break; + } + }} + array_deep_wipe(config->params, filter_params_wipe); + + if (!ok) { + syslog(LOG_ERR, "no entry point defined"); + } return ok; } -config_t *config_read(const char *file) +static bool config_load(config_t *config) { - config_t *config; filter_t filter; file_map_t map; const char *p; @@ -95,18 +163,18 @@ config_t *config_read(const char *file) char value[BUFSIZ]; ssize_t key_len, value_len; - if (!file_map_open(&map, file, false)) { + if (!file_map_open(&map, config->filename, false)) { return false; } - config = config_new(); + config_close(config); filter_init(&filter); linep = p = map.map; #define READ_ERROR(Fmt, ...) \ do { \ - syslog(LOG_ERR, "config file %s:%d:%d: " Fmt, file, line + 1, \ - p - linep + 1, ##__VA_ARGS__); \ + syslog(LOG_ERR, "config file %s:%d:%d: " Fmt, config->filename, \ + line + 1, p - linep + 1, ##__VA_ARGS__); \ goto error; \ } while (0) #define ADD_IN_BUFFER(Buffer, Len, Char) \ @@ -203,6 +271,9 @@ config_t *config_read(const char *file) if (escaped) { \ ADD_IN_BUFFER(Buffer, Len, '\\'); \ } \ + while ((Len) > 0 && isspace((Buffer)[(Len) - 1])) { \ + (Buffer)[--(Len)] = '\0'; \ + } \ } \ READ_NEXT(OnEOF); \ } while(0) @@ -234,10 +305,13 @@ read_param_value: READ_BLANK(goto badeof); 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); + filter_param_t param; + param.type = param_tokenize(key, key_len); + if (param.type != ATK_UNKNOWN) { + param.value = p_dupstr(value, value_len); + param.value_len = value_len; + array_add(config->params, param); + } } goto read_section; @@ -266,9 +340,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(;); @@ -284,14 +359,31 @@ ok: goto error; } file_map_close(&map); - return config; + return true; badeof: syslog(LOG_ERR, "Unexpected end of file"); error: - filter_wipe(&filter); - config_delete(&config); + if (filter.name) { + filter_wipe(&filter); + } file_map_close(&map); - return NULL; + return false; +} + +bool config_reload(config_t *config) +{ + return config_load(config); +} + +config_t *config_read(const char *file) +{ + config_t *config = config_new(); + config->filename = file; + if (!config_reload(config)) { + p_delete(&config); + return NULL; + } + return config; }