X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fgreylist.c;h=fe5188c6c4443d60b46fb07ca529c2694019badc;hb=7e6264b4c2833ad719899b571ba10e6f4cf89508;hp=b5dcb7b4f2f50d891182766ba2db23df8e8172ba;hpb=fa576db63fb43d41bd1fa17fb58afa2a99e45f05;p=apps%2Fpfixtools.git diff --git a/postlicyd/greylist.c b/postlicyd/greylist.c index b5dcb7b..fe5188c 100644 --- a/postlicyd/greylist.c +++ b/postlicyd/greylist.c @@ -44,6 +44,7 @@ typedef struct greylist_config_t { int delay; int retry_window; int client_awl; + int max_age; TCBDB *awl_db; TCBDB *obj_db; @@ -51,8 +52,9 @@ typedef struct greylist_config_t { #define GREYLIST_INIT { .lookup_by_host = false, \ .delay = 300, \ - .retry_window = 2 * 24 * 2600, \ + .retry_window = 2 * 24 * 3600, \ .client_awl = 5, \ + .max_age = 35 * 3600, \ .awl_db = NULL, \ .obj_db = NULL } @@ -180,6 +182,20 @@ static const char *c_net(const greylist_config_t *config, return cnet; } +static inline bool greylist_check_awlentry(const greylist_config_t *config, + struct awl_entry *aent, time_t now) +{ + return !(now - aent->last > config->max_age); +} + +static inline bool greylist_check_object(const greylist_config_t *config, + const struct obj_entry *oent, time_t now) +{ + return !(now - oent->last > config->max_age + || (oent->last - oent->first < config->delay + && now - oent->last > config->retry_window)); +} + static bool try_greylist(const greylist_config_t *config, const char *sender, const char *c_addr, const char *c_name, const char *rcpt) @@ -207,16 +223,21 @@ static bool try_greylist(const greylist_config_t *config, memcpy(&aent, res, len); } + if (!greylist_check_awlentry(config, &aent, now)) { + aent.count = 0; + aent.last = 0; + } + /* Whitelist if count is enough. */ - if (aent.count > config->client_awl) { + if (aent.count >= config->client_awl) { if (now < aent.last + 3600) { INCR_AWL } /* OK. */ - syslog(LOG_INFO, "client whitelisted"); + //syslog(LOG_INFO, "client whitelisted"); return true; } } @@ -231,13 +252,13 @@ static bool try_greylist(const greylist_config_t *config, res = tcbdbget3(config->obj_db, key, klen, &len); if (res && len == sizeof(oent)) { memcpy(&oent, res, len); + greylist_check_object(config, &oent, now); } /* Discard stored first-seen if it is the first retrial and - * it is beyong the retry window. + * it is beyong the retry window and too old entries. */ - if (oent.last - oent.first < config->delay - && now - oent.first > config->retry_window) { + if (!greylist_check_object(config, &oent, now)) { oent.first = now; } @@ -260,13 +281,13 @@ static bool try_greylist(const greylist_config_t *config, /* OK */ - syslog(LOG_INFO, "client whitelisted"); + //syslog(LOG_INFO, "client whitelisted"); return true; } /* DUNNO */ - syslog(LOG_INFO, "client greylisted"); + //syslog(LOG_INFO, "client greylisted"); return false; } @@ -306,25 +327,13 @@ static bool greylist_filter_constructor(filter_t *filter) foreach (filter_param_t *param, filter->params) { switch (param->type) { - case ATK_PATH: - path = param->value; - break; - - case ATK_PREFIX: - prefix = param->value; - break; - - case ATK_LOOKUP_BY_HOST: - config->lookup_by_host = (atoi(param->value) != 0); - break; - - case ATK_RETRY_WINDOW: - config->retry_window = atoi(param->value); - break; - - case ATK_CLIENT_AWL: - config->client_awl = atoi(param->value); - break; + FILTER_PARAM_PARSE_STRING(PATH, path); + FILTER_PARAM_PARSE_STRING(PREFIX, prefix); + FILTER_PARAM_PARSE_BOOLEAN(LOOKUP_BY_HOST, config->lookup_by_host); + FILTER_PARAM_PARSE_INT(RETRY_WINDOW, config->retry_window); + FILTER_PARAM_PARSE_INT(CLIENT_AWL, config->client_awl); + FILTER_PARAM_PARSE_INT(DELAY, config->delay); + FILTER_PARAM_PARSE_INT(MAX_AGE, config->max_age); default: break; } @@ -349,9 +358,14 @@ 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_MATCH : HTK_FAIL; + HTK_WHITELIST : HTK_GREYLIST; } static int greylist_init(void) @@ -361,9 +375,10 @@ 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, "fail"); - (void)filter_hook_register(type, "match"); + (void)filter_hook_register(type, "greylist"); + (void)filter_hook_register(type, "whitelist"); /* Parameters. */ @@ -371,6 +386,7 @@ static int greylist_init(void) (void)filter_param_register(type, "delay"); (void)filter_param_register(type, "retry_window"); (void)filter_param_register(type, "client_awl"); + (void)filter_param_register(type, "max_age"); (void)filter_param_register(type, "path"); (void)filter_param_register(type, "prefix"); return 0;