changeset 331:9800776436b9

allow dkim whitelisting to override uribl hosts in the mail body
author Carl Byington <carl@five-ten-sg.com>
date Mon, 19 Dec 2016 15:32:32 -0800
parents b5b93a7e1e6d
children ed04479a8e12
files dnsbl.conf src/context.cpp src/context.h src/dnsbl.cpp
diffstat 4 files changed, 44 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- 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;
         };
--- 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;
 }
 
 
--- 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);
--- 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<n; i++) key[i] = tolower(key[i]);
+    for (size_t i=0; i<n; i++) key[i] = tolower(key[i]);
     if ((n > 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);
             }