X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fconfig.c;h=75f7cc2f0a797b0ac07120bdaea2869ae5dbace9;hb=063d8a2ddca1e35efde7a3dec5eb04387dfb0922;hp=d4131f117ea32119b329e7f0dc6922ab525eacfb;hpb=4cc3c542c668521aef91f06f5bdff1c73643b646;p=apps%2Fpfixtools.git diff --git a/postlicyd/config.c b/postlicyd/config.c index d4131f1..75f7cc2 100644 --- a/postlicyd/config.c +++ b/postlicyd/config.c @@ -16,17 +16,20 @@ /* products derived from this software without specific prior written */ /* permission. */ /* */ -/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ -/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ -/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ -/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ -/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ -/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ -/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ -/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ -/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ -/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ -/* THE POSSIBILITY OF SUCH DAMAGE. */ +/* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */ +/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */ +/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */ +/* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */ +/* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */ +/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */ +/* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/* POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* Copyright (c) 2006-2008 the Authors */ +/* see AUTHORS and source files for details */ /******************************************************************************/ /* @@ -36,6 +39,7 @@ #include "file.h" #include "config.h" #include "str.h" +#include "resources.h" #define config_param_register(Param) @@ -78,6 +82,12 @@ config_param_register("verify_filter"); config_param_register("port"); +/* Format of the log message. + * The message exact format is $log: "reply" + */ +config_param_register("log_format"); + + static config_t *global_config = NULL; static inline config_t *config_new(void) @@ -94,6 +104,7 @@ static void config_close(config_t *config) } array_deep_wipe(config->filters, filter_wipe); array_deep_wipe(config->params, filter_params_wipe); + p_delete(&config->log_format); } void config_delete(config_t **config) @@ -113,70 +124,8 @@ static void config_exit() } module_exit(config_exit); -static bool config_second_pass(config_t *config) -{ - bool ok = true; - if (config->filters.len > 0) { -# define QSORT_TYPE filter_t -# define QSORT_BASE config->filters.data -# define QSORT_NELT config->filters.len -# define QSORT_LT(a,b) strcmp(a->name, b->name) < 0 -# include "qsort.c" - } - - foreach (filter_t *filter, config->filters) { - if (!filter_update_references(filter, &config->filters)) { - ok = false; - break; - } - }} - if (!ok) { - return false; - } - if (!filter_check_safety(&config->filters)) { - return false; - } - - ok = false; -#define PARSE_CHECK(Expr, Fmt, ...) \ - if (!(Expr)) { \ - err(Fmt, ##__VA_ARGS__); \ - return 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); \ - PARSE_CHECK(config->entry_points[SMTP_ ## State] >= 0, \ - "invalid filter name %s", 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 - FILTER_PARAM_PARSE_INT(PORT, config->port); - default: break; - } - }} - array_deep_wipe(config->params, filter_params_wipe); - - if (!ok) { - err("no entry point defined"); - } - - return ok; -} -static bool config_load(config_t *config) +static bool config_parse(config_t *config) { filter_t filter; file_map_t map; @@ -188,19 +137,18 @@ static bool config_load(config_t *config) char key[BUFSIZ]; char value[BUFSIZ]; - ssize_t key_len, value_len; + int key_len, value_len; if (!file_map_open(&map, config->filename, false)) { return false; } - config_close(config); filter_init(&filter); linep = p = map.map; #define READ_LOG(Lev, Fmt, ...) \ __log(LOG_ ## Lev, "config file %s:%d:%d: " Fmt, config->filename, \ - line + 1, p - linep + 1, ##__VA_ARGS__) + line + 1, (int)(p - linep + 1), ##__VA_ARGS__) #define READ_ERROR(Fmt, ...) \ do { \ READ_LOG(ERR, Fmt, ##__VA_ARGS__); \ @@ -388,17 +336,11 @@ read_filter: } end_of_section = true; READ_NEXT; - if (!filter_build(&filter)) { - READ_ERROR("invalid filter %s", filter.name); - } array_add(config->filters, filter); filter_init(&filter); goto read_section; ok: - if (!config_second_pass(config)) { - goto error; - } file_map_close(&map); return true; @@ -413,6 +355,105 @@ error: return false; } +static bool config_build_structure(config_t *config) +{ + bool ok = true; + if (config->filters.len > 0) { +# define QSORT_TYPE filter_t +# define QSORT_BASE config->filters.data +# define QSORT_NELT config->filters.len +# define QSORT_LT(a,b) strcmp(a->name, b->name) < 0 +# include "qsort.c" + } + + foreach (filter_t *filter, config->filters) { + if (!filter_update_references(filter, &config->filters)) { + ok = false; + break; + } + }} + if (!ok) { + return false; + } + if (!filter_check_safety(&config->filters)) { + return false; + } + + ok = false; +#define PARSE_CHECK(Expr, Fmt, ...) \ + if (!(Expr)) { \ + err(Fmt, ##__VA_ARGS__); \ + return 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); \ + PARSE_CHECK(config->entry_points[SMTP_ ## State] >= 0, \ + "invalid filter name %s", 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 + FILTER_PARAM_PARSE_INT(PORT, config->port); + FILTER_PARAM_PARSE_STRING(LOG_FORMAT, config->log_format, true); + default: break; + } + }} + array_deep_wipe(config->params, filter_params_wipe); + + if (config->log_format && !query_format_check(config->log_format)) { + err("invalid log format: \"%s\"", config->log_format); + return false; + } + + if (!ok) { + err("no entry point defined"); + } + return ok; +} + +static bool config_build_filters(config_t *config) +{ + foreach (filter_t *filter, config->filters) { + if (!filter_build(filter)) { + return false; + } + }} + + return true; +} + +static bool config_load(config_t *config) { + config_close(config); + + if (!config_parse(config)) { + err("Invalid configuration: cannot parse configuration file \"%s\"", config->filename); + return false; + } + if (!config_build_structure(config)) { + err("Invalid configuration: inconsistent filter structure"); + return false; + } + if (!config_build_filters(config)) { + err("Invalid configuration: invalid filter"); + return false; + } + + resource_garbage_collect(); + return true; +} + bool config_reload(config_t *config) { return config_load(config); @@ -423,8 +464,19 @@ config_t *config_read(const char *file) config_t *config = config_new(); config->filename = file; if (!config_reload(config)) { - p_delete(&config); + config_delete(&config); return NULL; } return config; } + +bool config_check(const char *file) +{ + config_t *config = config_new(); + config->filename = file; + + bool ret = config_parse(config) && config_build_structure(config); + + config_delete(&config); + return ret; +}