diff src/context.cpp @ 321:e172dc10fe24

add dkim white/black listing
author Carl Byington <carl@five-ten-sg.com>
date Sat, 17 Dec 2016 13:47:28 -0800
parents e27c24c1974a
children 9f8411f3919c
line wrap: on
line diff
--- a/src/context.cpp	Sat Dec 17 09:46:40 2016 -0800
+++ b/src/context.cpp	Sat Dec 17 13:47:28 2016 -0800
@@ -69,6 +69,11 @@
 const char *token_white;
 const char *token_white_regex;
 const char *token_yes;
+const char *token_dkim_signer;
+const char *token_dkim_from;
+const char *token_signed_white;
+const char *token_signed_black;
+const char *token_require_signed;
 
 const char *token_myhostname;
 #ifndef HOST_NAME_MAX
@@ -610,6 +615,12 @@
 }
 
 
+DKIM::DKIM(const char *action_, const char *signer_) {
+    action = action_;
+    signer = signer_;
+}
+
+
 DNSBL::DNSBL(const char *n, const char *s, const char *m) {
     name    = n;
     suffix  = s;
@@ -763,6 +774,11 @@
 
 
 CONTEXT::~CONTEXT() {
+    for (dkimp_map::iterator i=dkim_from_names.begin(); i!=dkim_from_names.end(); i++) {
+        DKIMP d = (*i).second;
+        // delete the underlying DKIM objects.
+        delete d;
+    }
     for (dnsblp_map::iterator i=dnsbl_names.begin(); i!=dnsbl_names.end(); i++) {
         DNSBLP d = (*i).second;
         // delete the underlying DNSBL objects.
@@ -985,6 +1001,22 @@
 }
 
 
+const char *CONTEXT::find_dkim_signer(const char *name) {
+    string_map::iterator i = dkim_signer_names.find(name);
+    if (i != dkim_signer_names.end()) return (*i).second;
+    if (parent) return parent->find_dkim_signer(name);
+    return NULL;
+}
+
+
+DKIMP CONTEXT::find_dkim_from(const char *name) {
+    dkimp_map::iterator i = dkim_from_names.find(name);
+    if (i != dkim_from_names.end()) return (*i).second;
+    if (parent) return parent->find_dkim_from(name);
+    return NULL;
+}
+
+
 DNSBLP CONTEXT::find_dnsbl(const char *name) {
     dnsblp_map::iterator i = dnsbl_names.find(name);
     if (i != dnsbl_names.end()) return (*i).second;
@@ -1199,6 +1231,23 @@
         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);
@@ -1810,6 +1859,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_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent);
 bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent) {
     const char *name = tok.next();
@@ -1832,9 +1937,6 @@
         else if (have == token_dnswll) {
             if (!parse_dnswll(tok, dc, *con)) return false;
         }
-        else if (have == token_requirerdns) {
-            if (!parse_requirerdns(tok, dc, *con)) return false;
-        }
         else if (have == token_content) {
             if (!parse_content(tok, dc, *con)) return false;
         }
@@ -1856,10 +1958,19 @@
         else if (have == token_envfrom) {
             if (!parse_envfrom(tok, dc, *con)) return false;
         }
+        else if (have == token_dkim_signer) {
+            if (!parse_dkim_signer(tok, dc, *con)) return false;
+        }
+        else if (have == token_dkim_from) {
+            if (!parse_dkim_from(tok, dc, *con)) return false;
+        }
         else if (have == token_rate) {
             if (parent || dc.default_context) tok.token_error("rate limit ignored in non default context");
             if (!parse_rate(tok, dc, *con)) return false;
         }
+        else if (have == token_requirerdns) {
+            if (!parse_requirerdns(tok, dc, *con)) return false;
+        }
         else if (have == token_context) {
             if (!parse_context(tok, dc, con)) return false;
         }
@@ -1958,6 +2069,11 @@
     token_white         = register_string("white");
     token_white_regex   = register_string("white_regex");
     token_yes           = register_string("yes");
+    token_dkim_signer       = register_string("dkim_signer");
+    token_dkim_from         = register_string("dkim_from");
+    token_signed_white      = register_string("signed_white");
+    token_signed_black      = register_string("signed_black");
+    token_require_signed    = register_string("require_signed");
 
     if (gethostname(myhostname, HOST_NAME_MAX+1) != 0) {
         strncpy(myhostname, "localhost", HOST_NAME_MAX+1);