# HG changeset patch # User Carl Byington # Date 1482190352 28800 # Node ID 9800776436b954190a33000985a5ca58988e929f # Parent b5b93a7e1e6dd75d37a2f46503d88aeccfec349c allow dkim whitelisting to override uribl hosts in the mail body diff -r b5b93a7e1e6d -r 9800776436b9 dnsbl.conf --- a/dnsbl.conf Mon Dec 19 12:05:06 2016 -0800 +++ b/dnsbl.conf Mon Dec 19 15:32:32 2016 -0800 @@ -67,15 +67,25 @@ // forged bulk senders like ebay and paypal. some.spammer require_signed some.spammer // reject if not signed + adp.com require_signed adp.com; billpay.bankofamerica.com require_signed billpay.bankofamerica.com; + e.statefarm.com require_signed e.statefarm.com; ealerts.bankofamerica.com require_signed ealerts.bankofamerica.com; ebay.com require_signed ebay.com; + ecommail.walgreens.com require_signed ecommail.walgreens.com; + email.travelzoo.com require_signed email.travelzoo.com; + email.jetblue.com require_signed email.jetblue.com; facebookmail.com require_signed facebookmail.com; + fedex.com require_signed fedex.com; healthcare.gov require_signed healthcare.gov; + iheartmedia.com require_signed iheartmedia.onmicrosoft.com; linkedin.com require_signed linkedin.com; + monster.com require_signed monster.com; paypal.com require_signed paypal.com; + r.groupon.com require_signed r.groupon.com; service.capitalone.com require_signed capitalone.com; support.facebook.com require_signed support.facebook.com; + twitter.com require_signed twitter.com; ups.com require_signed ups.com; wellsfargo.com require_signed wellsfargo.com; }; diff -r b5b93a7e1e6d -r 9800776436b9 src/context.cpp --- a/src/context.cpp Mon Dec 19 12:05:06 2016 -0800 +++ b/src/context.cpp Mon Dec 19 15:32:32 2016 -0800 @@ -1108,7 +1108,7 @@ } -bool CONTEXT::acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, string& msg) { +const char *CONTEXT::acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, string& msg) { DKIMP dk = find_dkim_from(from); bool requirement = false; for (string_set::iterator s=signers.begin(); s!=signers.end(); s++) { @@ -1116,14 +1116,14 @@ // signed by a white listed signer if (st == token_white) { log(queueid, "whitelisted dkim signer %s", *s); - return true; + return token_white; } // signed by a black listed signer if (st == token_black) { char buf[maxlen]; snprintf(buf, sizeof(buf), "Mail rejected - dkim signed by %s", *s); msg = string(buf); - return false; + return token_black; } if (dk) { @@ -1131,7 +1131,7 @@ // signed by a white listed signer if ((st == token_signed_white) && (strcasecmp(*s,dk->signer) == 0)) { log(queueid, "whitelisted dkim signer %s", *s); - return true; + return token_white; } // signed by the required signer if ((st == token_require_signed) && (strcasecmp(*s,dk->signer) == 0)) { @@ -1143,39 +1143,42 @@ char buf[maxlen]; snprintf(buf, sizeof(buf), "Mail rejected - dkim signed by %s", dk->signer); msg = string(buf); - return false; + return token_black; } } } - if (dk && (dk->action == token_require_signed) && !requirement) { + if (dk && (dk->action == token_require_signed)) { + if (requirement) return token_white; + else { char buf[maxlen]; snprintf(buf, sizeof(buf), "Mail rejected - not dkim signed by %s", dk->signer); msg = string(buf); - return false; + return token_black; + } } if (spamassassin_limit && (score > spamassassin_limit)) { char buf[maxlen]; snprintf(buf, sizeof(buf), "Mail rejected - spam assassin score %d", score); msg = string(buf); - return false; + return token_black; } if (dcc_bulk_threshold && (bulk >= dcc_bulk_threshold)) { char buf[maxlen]; snprintf(buf, sizeof(buf), "Mail rejected - dcc score %d", bulk); msg = string(buf); - return false; + return token_black; } if (memory.excessive_bad_tags(tag_limit)) { msg = string(tag_limit_message); - return false; + return token_black; } if (!host_random && memory.excessive_hosts(host_limit)) { msg = string(host_limit_message); - return false; + return token_black; } - return true; + return token_unknown; } diff -r b5b93a7e1e6d -r 9800776436b9 src/context.h --- a/src/context.h Mon Dec 19 12:05:06 2016 -0800 +++ b/src/context.h Mon Dec 19 15:32:32 2016 -0800 @@ -313,7 +313,7 @@ dnswlp_list& get_dnswl_list(); void log(const char *queueid, const char *msg, const char *v); - bool acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, string& msg); + const char *acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, string& msg); bool ignore_host(const char *host); void dump(bool isdefault, bool &spamass, int level = 0); diff -r b5b93a7e1e6d -r 9800776436b9 src/dnsbl.cpp --- a/src/dnsbl.cpp Mon Dec 19 12:05:06 2016 -0800 +++ b/src/dnsbl.cpp Mon Dec 19 15:32:32 2016 -0800 @@ -1116,7 +1116,7 @@ if (n ==0) return strdup("<>"); char *key = strdup(email); key[n] = '\0'; - for (int i=0; i 14) && (strncmp(key, "srs", 3) == 0)) { // might have srs coding to be removed const int nmatch = 7; @@ -1594,7 +1594,8 @@ char buf[maxlen]; string msg; - string_set alive; + string_set unknowns; + string_set whites; bool random = false; int limit = 0; if (priv.dkim_signers.empty()) { @@ -1613,21 +1614,26 @@ for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { const char *rcpt = (*i).first; CONTEXT &con = *((*i).second); - if (!con.acceptable_content(*priv.memory, score, bulk, priv.queueid, priv.dkim_signers, priv.fromaddr, msg)) { + const char *st = con.acceptable_content(*priv.memory, score, bulk, priv.queueid, priv.dkim_signers, priv.fromaddr, msg); + if (st == token_black) { // bad html tags or excessive hosts or // high spam assassin score or dcc bulk threshold exceedeed // or signed by a dkim signer that we don't like // or header from requires dkim signer that is missing smfi_delrcpt(ctx, (char*)rcpt); } - else { - alive.insert(rcpt); + else if (st == token_unknown) { + unknowns.insert(rcpt); random |= con.get_host_random(); limit = max(limit, con.get_host_limit()); } + else if (st == token_white) { + whites.insert(rcpt); } - bool rejecting = alive.empty(); // if alive is empty, we must have set msg above in acceptable_content() - if (!rejecting) { + } + bool rejecting = unknowns.empty() && whites.empty(); + if (!unknowns.empty()) { + // check hosts for those recipients const char *fmt; const char *found; if (check_hosts(priv, random, limit, fmt, host, ip, found)) { @@ -1653,7 +1659,7 @@ } else rc = SMFIS_CONTINUE; } - else if (!priv.have_whites) { + else if (!priv.have_whites && whites.empty()) { // can reject the entire message snprintf(buf, sizeof(buf), "%s", msg.c_str()); smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", buf); @@ -1661,7 +1667,7 @@ } else { // need to accept it but remove the recipients that don't want it - for (string_set::iterator i=alive.begin(); i!=alive.end(); i++) { + for (string_set::iterator i=unknowns.begin(); i!=unknowns.end(); i++) { const char *rcpt = *i; smfi_delrcpt(ctx, (char*)rcpt); }