diff src/context.cpp @ 322:9f8411f3919c

add dkim white/black listing
author Carl Byington <carl@five-ten-sg.com>
date Sat, 17 Dec 2016 17:04:52 -0800
parents e172dc10fe24
children b6f173ac5209
line wrap: on
line diff
--- a/src/context.cpp	Sat Dec 17 13:47:28 2016 -0800
+++ b/src/context.cpp	Sat Dec 17 17:04:52 2016 -0800
@@ -74,8 +74,8 @@
 const char *token_signed_white;
 const char *token_signed_black;
 const char *token_require_signed;
+const char *token_myhostname;
 
-const char *token_myhostname;
 #ifndef HOST_NAME_MAX
     #define HOST_NAME_MAX 255
 #endif
@@ -1099,7 +1099,41 @@
 }
 
 
-bool CONTEXT::acceptable_content(recorder &memory, int score, int bulk, string& msg) {
+bool CONTEXT::acceptable_content(recorder &memory, int score, int bulk, const char *signer, const char *from, string& msg) {
+    char buf[maxlen];
+    snprintf(buf, sizeof(buf), "acceptable content from %s signer %s", (signer) ? signer : token_asterisk, (from) ? from : token_asterisk);
+    my_syslog(buf);
+
+    const char *st = find_dkim_signer(signer);
+    if (st == token_white) return true;
+    if (st == token_black) {
+        char buf[maxlen];
+        snprintf(buf, sizeof(buf), "Mail rejected - dkim signed by %s", signer);
+        msg = string(buf);
+        return false;
+    }
+
+    DKIMP dk = find_dkim_from(from);
+    if (dk) {
+        st = dk->action;
+        // signed by a white listed signer
+        if ((st == token_signed_white)   && (strcasecmp(signer,dk->signer) == 0)) return true;
+        // not signed by the required signer
+        if ((st == token_require_signed) && (strcasecmp(signer,dk->signer) != 0)) {
+            char buf[maxlen];
+            snprintf(buf, sizeof(buf), "Mail rejected - not dkim signed by %s", dk->signer);
+            msg = string(buf);
+            return false;
+        }
+        // signed by a black listed signer
+        if ((st == token_signed_black)   && (strcasecmp(signer,dk->signer) == 0)) {
+            char buf[maxlen];
+            snprintf(buf, sizeof(buf), "Mail rejected - dkim signed by %s", dk->signer);
+            msg = string(buf);
+            return false;
+        }
+    }
+
     if (spamassassin_limit && (score > spamassassin_limit)) {
         char buf[maxlen];
         snprintf(buf, sizeof(buf), "Mail rejected - spam assassin score %d", score);
@@ -1168,6 +1202,20 @@
 
     if (content_filtering) {
         printf("%s     content on { \n", indent);
+        printf("%s         dkim_signer { \n", indent);
+        for (string_map::iterator i=dkim_signer_names.begin(); i!=dkim_signer_names.end(); i++) {
+            const char *n = (*i).first;
+            const char *a = (*i).second;
+            printf("%s             %s %s; \n", indent, n, a);
+        }
+        printf("%s         } \n", indent);
+        printf("%s         dkim_from { \n", indent);
+        for (dkimp_map::iterator i=dkim_from_names.begin(); i!=dkim_from_names.end(); i++) {
+            const char *n = (*i).first;
+            DKIM &d = *(*i).second;
+            printf("%s             %s %s %s; \n", indent, n, d.action, d.signer);
+        }
+        printf("%s         } \n", indent);
         if (content_suffix) {
             printf("%s         filter %s \"%s\"; \n", indent, content_suffix, content_message);
         }
@@ -1231,23 +1279,6 @@
         printf("%s     content off {}; \n", indent);
     }
 
-    printf("%s     dkim_signer { \n", indent);
-    for (string_map::iterator i=dkim_signer_names.begin(); i!=dkim_signer_names.end(); i++) {
-        const char *n = (*i).first;
-        const char *a = (*i).second;
-        printf("%s         %s %s; \n", indent, n, a);
-    }
-    printf("%s     } \n", indent);
-
-    printf("%s     dkim_from { \n", indent);
-    for (dkimp_map::iterator i=dkim_from_names.begin(); i!=dkim_from_names.end(); i++) {
-        const char *n = (*i).first;
-        DKIM &d = *(*i).second;
-        printf("%s         %s %s %s; \n", indent, n, d.action, d.signer);
-    }
-
-    printf("%s     } \n", indent);
-
     printf("%s     env_to { \t// %s\n", indent, fullname);
     for (string_set::iterator i=env_to.begin(); i!=env_to.end(); i++) {
         printf("%s         %s; \n", indent, *i);
@@ -1463,6 +1494,62 @@
 
 ////////////////////////////////////////////////
 //
+bool parse_dkim_signer(TOKEN &tok, CONFIG &dc, CONTEXT &me);
+bool parse_dkim_signer(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
+    if (!tsa(tok, token_lbrace)) return false;
+    while (true) {
+        const char *have = tok.next();
+        if (!have) break;
+        if (have == token_rbrace) break;
+        if (have == token_semi) {
+            // optional separators
+        }
+        else {
+            const char *signer = have;
+            const char *action = tok.next();
+            if ((action == token_white) || (action == token_black)) {
+                me.add_dkim_signer(signer, action);
+            }
+            else {
+                tok.token_error("white/black", action);
+            }
+        }
+    }
+    return tsa(tok, token_semi);
+}
+
+
+////////////////////////////////////////////////
+//
+bool parse_dkim_from(TOKEN &tok, CONFIG &dc, CONTEXT &me);
+bool parse_dkim_from(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
+    if (!tsa(tok, token_lbrace)) return false;
+    while (true) {
+        const char *have = tok.next();
+        if (!have) break;
+        if (have == token_rbrace) break;
+        if (have == token_semi) {
+            // optional separators
+        }
+        else {
+            const char *from   = have;
+            const char *action = tok.next();
+            if ((action == token_signed_white) || (action == token_signed_black) || (action == token_require_signed)) {
+                const char *signer = tok.next();
+                if (!signer) break;
+                else         me.add_dkim_from(from, action, signer);
+            }
+            else {
+                tok.token_error("signed_white/signed_black/require_signed", action);
+            }
+        }
+    }
+    return tsa(tok, token_semi);
+}
+
+
+////////////////////////////////////////////////
+//
 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me);
 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
     const char *setting = tok.next();
@@ -1628,6 +1715,12 @@
             }
             if (!tsa(tok, token_semi)) return false;
         }
+        else if (have == token_dkim_signer) {
+            if (!parse_dkim_signer(tok, dc, me)) return false;
+        }
+        else if (have == token_dkim_from) {
+            if (!parse_dkim_from(tok, dc, me)) return false;
+        }
         else if (have == token_rbrace) {
             break;  // done
         }
@@ -1859,62 +1952,6 @@
 
 ////////////////////////////////////////////////
 //
-bool parse_dkim_signer(TOKEN &tok, CONFIG &dc, CONTEXT &me);
-bool parse_dkim_signer(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
-    if (!tsa(tok, token_lbrace)) return false;
-    while (true) {
-        const char *have = tok.next();
-        if (!have) break;
-        if (have == token_rbrace) break;
-        if (have == token_semi) {
-            // optional separators
-        }
-        else {
-            const char *signer = have;
-            const char *action = tok.next();
-            if ((action == token_white) || (action == token_black)) {
-                me.add_dkim_signer(signer, action);
-            }
-            else {
-                tok.token_error("white/black", action);
-            }
-        }
-    }
-    return tsa(tok, token_semi);
-}
-
-
-////////////////////////////////////////////////
-//
-bool parse_dkim_from(TOKEN &tok, CONFIG &dc, CONTEXT &me);
-bool parse_dkim_from(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
-    if (!tsa(tok, token_lbrace)) return false;
-    while (true) {
-        const char *have = tok.next();
-        if (!have) break;
-        if (have == token_rbrace) break;
-        if (have == token_semi) {
-            // optional separators
-        }
-        else {
-            const char *from   = have;
-            const char *action = tok.next();
-            if ((action == token_signed_white) || (action == token_signed_black) || (action == token_require_signed)) {
-                const char *signer = tok.next();
-                if (!signer) break;
-                else         me.add_dkim_from(from, action, signer);
-            }
-            else {
-                tok.token_error("signed_white/signed_black/require_signed", action);
-            }
-        }
-    }
-    return tsa(tok, token_semi);
-}
-
-
-////////////////////////////////////////////////
-//
 bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent);
 bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent) {
     const char *name = tok.next();