Mercurial > dnsbl
diff src/dnsbl.cpp @ 136:f4746d8a12a3
add smtp auth rate limits
author | carl |
---|---|
date | Tue, 26 Sep 2006 13:59:14 -0700 |
parents | f9917ce924a3 |
children | a6190f7798f4 |
line wrap: on
line diff
--- a/src/dnsbl.cpp Wed Aug 02 21:33:34 2006 -0700 +++ b/src/dnsbl.cpp Tue Sep 26 13:59:14 2006 -0700 @@ -86,6 +86,7 @@ pthread_mutex_t syslog_mutex; pthread_mutex_t resolve_mutex; pthread_mutex_t fd_pool_mutex; +pthread_mutex_t rate_mutex; std::set<int> fd_pool; int NULL_SOCKET = -1; @@ -95,6 +96,7 @@ time_t last_error_time; int resolver_sock_count = 0; // protected with fd_pool_mutex int resolver_pool_size = 0; // protected with fd_pool_mutex +rcpt_rates rcpt_counts; // protected with rate_mutex struct ns_map { @@ -141,6 +143,19 @@ //////////////////////////////////////////////// +// helper to manipulate recipient counts +// +int incr_rcpt_count(char *user); +int incr_rcpt_count(char *user) { + pthread_mutex_lock(&rate_mutex); + rcpt_rates::iterator i = rcpt_counts.find(user); + int c = (i == rcpt_counts.end()) ? 0 : (*i).second; + rcpt_counts[user] = c++; + pthread_mutex_unlock(&rate_mutex); + return c; +} + +//////////////////////////////////////////////// // helper to discard the strings held by a context_map // void discard(context_map &cm); @@ -224,7 +239,7 @@ ip = 0; mailaddr = NULL; queueid = NULL; - authenticated = false; + authenticated = NULL; have_whites = false; only_whites = true; memory = NULL; @@ -247,13 +262,14 @@ void mlfiPriv::reset(bool final) { if (mailaddr) free(mailaddr); if (queueid) free(queueid); + if (authenticated) free(authenticated); discard(env_to); if (memory) delete memory; if (scanner) delete scanner; if (!final) { mailaddr = NULL; queueid = NULL; - authenticated = false; + authenticated = NULL; have_whites = false; only_whites = true; memory = NULL; @@ -912,7 +928,8 @@ { mlfiPriv &priv = *MLFIPRIV; priv.mailaddr = to_lower_string(from[0]); - priv.authenticated = (smfi_getsymval(ctx, "{auth_authen}") != NULL); + priv.authenticated = smfi_getsymval(ctx, "{auth_authen}"); + if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); return SMFIS_CONTINUE; } @@ -936,8 +953,22 @@ char *fromvalue = con.find_from(priv.mailaddr); status st; if (priv.authenticated) { + int c = incr_rcpt_count(priv.authenticated); + int l = dc.default_context->find_rate(priv.authenticated); + if (c > l) { + smfi_setreply(ctx, "550", "5.7.1", "recipient rate limit exceeded"); + return SMFIS_REJECT; + } + else { + if (debug_syslog > 1) { + char buf[maxlen]; + char msg[maxlen]; + snprintf(msg, sizeof(msg), "authenticated id %s (%d recipients, %d limit)", priv.authenticated, c, l); + my_syslog(&priv, msg); + } st = white; } + } else if (fromvalue == token_black) { st = black; } @@ -1127,14 +1158,24 @@ // thread to watch the old config files for changes // and reload when needed. we also cleanup old // configs whose reference count has gone to zero. +// we also clear the SMTP AUTH recipient counts hourly // void* config_loader(void *arg); void* config_loader(void *arg) { + int loop = 0; typedef set<CONFIG *> configp_set; configp_set old_configs; while (loader_run) { sleep(180); // look for modifications every 3 minutes if (!loader_run) break; + loop++; + if (loop == 20) { + // three minutes thru each loop, 20 loops per hour + // clear the recipient counts + pthread_mutex_lock(&rate_mutex); + rcpt_counts.clear(); + pthread_mutex_unlock(&rate_mutex); + } CONFIG &dc = *config; time_t then = dc.load_time; struct stat st;