From 6154a392a1f0d96d4599a45f1c37d84dbe5bfa4d Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Tue, 16 Sep 2008 18:31:39 +0200 Subject: [PATCH] Add a "special" return value: abort. Abort is a *private* hook and can not be associated to a user action. When abort is returned, the connection is closed as requested by the "SMTPD_POLICY_README". Signed-off-by: Florent Bruneau --- example/postlicyd.conf | 3 +++ postlicyd/filter.c | 17 ++++++++++++++--- postlicyd/filter.h | 2 +- postlicyd/greylist.c | 6 ++++++ postlicyd/main-postlicyd.c | 20 +++++++++----------- postlicyd/rbl.c | 1 + 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/example/postlicyd.conf b/example/postlicyd.conf index fa99670..8ba7a91 100644 --- a/example/postlicyd.conf +++ b/example/postlicyd.conf @@ -88,6 +88,9 @@ # - if the client is whitelisted, returns whitelist # - if the client is greylisted, returns greylist # - if a error occured (not currently possible), returns error +# State: +# this filter is a recipient filter and works in RCPT state only +# (smtpd_recipient_restrictions). # # Format: # A filter look likes that: diff --git a/postlicyd/filter.c b/postlicyd/filter.c index b7e2334..4bab4c9 100644 --- a/postlicyd/filter.c +++ b/postlicyd/filter.c @@ -43,6 +43,13 @@ static filter_destructor_t destructors[FTK_count]; static bool hooks[FTK_count][HTK_count]; static bool params[FTK_count][ATK_count]; +static const filter_hook_t default_hook = { + .type = 0, + .value = (char*)"DUNNO", + .postfix = true, + .filter_id = 0 +}; + filter_type_t filter_register(const char *type, filter_constructor_t constructor, filter_destructor_t destructor, filter_runner_t runner) { @@ -133,13 +140,17 @@ void filter_wipe(filter_t *filter) p_delete(&filter->name); } -filter_hook_t *filter_run(const filter_t *filter, const query_t *query) +const filter_hook_t *filter_run(const filter_t *filter, const query_t *query) { int start = 0; int end = filter->hooks.len; //syslog(LOG_DEBUG, "running filter %s (%s)", // filter->name, ftokens[filter->type]); filter_result_t res = runners[filter->type](filter, query); + + if (res == HTK_ABORT) { + return NULL; + } //syslog(LOG_DEBUG, "filter run, result is %s", htokens[res]); while (start < end) { @@ -157,7 +168,7 @@ filter_hook_t *filter_run(const filter_t *filter, const query_t *query) } syslog(LOG_WARNING, "missing hook %s for filter %s", htokens[res], filter->name); - return NULL; + return &default_hook; } void filter_set_name(filter_t *filter, const char *name, ssize_t len) @@ -201,7 +212,7 @@ bool filter_add_hook(filter_t *filter, const char *name, ssize_t name_len, syslog(LOG_ERR, "unknown hook type %.*s", name_len, name); return false; } - if (!hooks[filter->type][hook.type]) { + if (!hooks[filter->type][hook.type] || hook.type == HTK_ABORT) { 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 8a1aacb..a113727 100644 --- a/postlicyd/filter.h +++ b/postlicyd/filter.h @@ -163,7 +163,7 @@ __attribute__((nonnull(1))) void filter_wipe(filter_t *filter); __attribute__((nonnull(1,2))) -filter_hook_t *filter_run(const filter_t *filter, const query_t *query); +const filter_hook_t *filter_run(const filter_t *filter, const query_t *query); #endif diff --git a/postlicyd/greylist.c b/postlicyd/greylist.c index ca58979..88ec6c7 100644 --- a/postlicyd/greylist.c +++ b/postlicyd/greylist.c @@ -349,6 +349,11 @@ static filter_result_t greylist_filter(const filter_t *filter, const query_t *query) { const greylist_config_t *config = filter->data; + if (query->state != SMTP_RCPT) { + syslog(LOG_WARNING, "greylisting only works as smtpd_recipient_restrictions"); + return HTK_ABORT; + } + return try_greylist(config, query->sender, query->client_address, query->client_name, query->recipient) ? HTK_WHITELIST : HTK_GREYLIST; @@ -361,6 +366,7 @@ static int greylist_init(void) greylist_filter); /* Hooks. */ + (void)filter_hook_register(type, "abort"); (void)filter_hook_register(type, "error"); (void)filter_hook_register(type, "greylist"); (void)filter_hook_register(type, "whitelist"); diff --git a/postlicyd/main-postlicyd.c b/postlicyd/main-postlicyd.c index e75965f..d6c5cc4 100644 --- a/postlicyd/main-postlicyd.c +++ b/postlicyd/main-postlicyd.c @@ -167,24 +167,23 @@ static void policy_answer(server_t *pcy, const char *fmt, ...) epoll_modify(pcy->fd, EPOLLIN | EPOLLOUT, pcy); } -static void policy_process(server_t *pcy, config_t *config) +static bool policy_process(server_t *pcy, const config_t *config) { const query_t* query = pcy->data; - filter_t *filter; + const filter_t *filter; if (config->entry_points[query->state] == -1) { syslog(LOG_WARNING, "no filter defined for current protocol_state (%d)", query->state); - policy_answer(pcy, "DUNNO"); - return; + return false; } filter = array_ptr(config->filters, config->entry_points[query->state]); while (true) { - filter_hook_t *hook = filter_run(filter, query); + const filter_hook_t *hook = filter_run(filter, query); if (hook == NULL) { - policy_answer(pcy, "DUNNO"); - return; + syslog(LOG_WARNING, "request aborted"); + return false; } else if (hook->postfix) { policy_answer(pcy, "%s", hook->value); - return; + return true; } else { filter = array_ptr(config->filters, hook->filter_id); } @@ -197,7 +196,7 @@ static int policy_run(server_t *pcy, void* vconfig) int nb = buffer_read(&pcy->ibuf, pcy->fd, -1); const char *eoq; query_t *query = pcy->data; - config_t *config = vconfig; + const config_t *config = vconfig; if (nb < 0) { if (errno == EAGAIN || errno == EINTR) @@ -218,8 +217,7 @@ static int policy_run(server_t *pcy, void* vconfig) return -1; query->eoq = eoq + strlen("\n\n"); epoll_modify(pcy->fd, 0, pcy); - policy_process(pcy, config); - return 0; + return policy_process(pcy, config) ? 0 : -1; } int start_listener(int port) diff --git a/postlicyd/rbl.c b/postlicyd/rbl.c index 3177334..131b095 100644 --- a/postlicyd/rbl.c +++ b/postlicyd/rbl.c @@ -383,6 +383,7 @@ static int rbl_init(void) rbl_filter_destructor, rbl_filter); /* Hooks. */ + (void)filter_hook_register(type, "abort"); (void)filter_hook_register(type, "error"); (void)filter_hook_register(type, "fail"); (void)filter_hook_register(type, "hard_match"); -- 2.20.1