changeset 421:22027ad2a28f stable-6-0-58

spf code now handles %{d} and %{h} macros; use envelope from value for spf if it is a subdomain of the header from domain
author Carl Byington <carl@five-ten-sg.com>
date Fri, 19 May 2017 13:44:13 -0700
parents 4901cdbc1fca
children 9f47c3ad6443
files ChangeLog NEWS configure.in dnsbl.spec.in src/context.cpp src/context.h
diffstat 6 files changed, 54 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Apr 26 09:27:01 2017 -0700
+++ b/ChangeLog	Fri May 19 13:44:13 2017 -0700
@@ -1,3 +1,7 @@
+6.58 2017-05-19
+    spf code now handles %{d} and %{h} macros.
+    use envelope from value for spf if it is a subdomain of the header from domain.
+
 6.57 2017-04-25
     spf code now handles mx,exists,ptr tags, multiple A records,
     %{i} macro
--- a/NEWS	Wed Apr 26 09:27:01 2017 -0700
+++ b/NEWS	Fri May 19 13:44:13 2017 -0700
@@ -1,3 +1,4 @@
+6.58 2017-05-19 spf code now handles %{d} and %{h} macros, use envelope from value for spf if it is a subdomain of the header from domain.
 6.57 2017-04-25 spf code now handles mx,exists,ptr tags, multiple A records, %{i} macro
 6.56 2017-04-19 refactor spf code; allow wildcard *.example.com in dkim signing restrictions
 6.55 2017-04-16 require 3 dots in bare ip addresses.
--- a/configure.in	Wed Apr 26 09:27:01 2017 -0700
+++ b/configure.in	Fri May 19 13:44:13 2017 -0700
@@ -1,6 +1,6 @@
 
 AC_PREREQ(2.59)
-AC_INIT(dnsbl,6.57,carl@five-ten-sg.com)
+AC_INIT(dnsbl,6.58,carl@five-ten-sg.com)
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 AC_CONFIG_MACRO_DIR([m4])
--- a/dnsbl.spec.in	Wed Apr 26 09:27:01 2017 -0700
+++ b/dnsbl.spec.in	Fri May 19 13:44:13 2017 -0700
@@ -155,6 +155,11 @@
 
 
 %changelog
+* Fri May 19 2017 Carl Byington <carl@five-ten-sg.com> - 6.58-1
+- spf code now handles %{d} and %{h} macros.
+- use envelope from value for spf if it is a subdomain of the header
+  from domain.
+
 * Tue Apr 25 2017 Carl Byington <carl@five-ten-sg.com> - 6.57-1
 - spf code now handles mx,exists,ptr tags, multiple A records, %{i} macro
 
--- a/src/context.cpp	Wed Apr 26 09:27:01 2017 -0700
+++ b/src/context.cpp	Fri May 19 13:44:13 2017 -0700
@@ -1130,31 +1130,62 @@
 }
 
 
+void CONTEXT::replace(char *buf, char *p, const char *what)
+{
+    // replace 4 chars in buf starting at p with what
+    char repl[maxlen];
+    size_t bn = strlen(buf);
+    size_t wn = strlen(what);
+    if ((bn - 4 + wn) < (size_t)maxlen) {
+        size_t n = p - buf;         // leading part length
+        strncpy(repl, buf, n);      // leading part
+        strcpy(repl+n, what);       // replacement
+        strcpy(repl+n+wn, buf+n+4); // trailing part
+        strcpy(buf, repl);
+    }
+}
+
 bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level)
 {
     // ip is in host order
+    if ((level == 0) && (priv->mailaddr)) {
+        const char *f = strchr(priv->mailaddr, '@');
+        if (f) {
+            f++;
+            size_t efl = strlen(f);        // envelope from domain
+            size_t hfl = strlen(from);     // header from domain
+            if (efl > hfl) {
+                size_t off = efl - hfl;
+                if ((f[off-1] == '.') && (strcmp(f+off,from) == 0)) {
+                    // envelope from is a strict child of header from
+                    from = f;   // use envelope from rather than header from
+                }
+            }
+        }
+    }
     char buf[maxlen];
     log(priv->queueid, "looking for %s txt record", from);
     dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen);
     if (*buf) {
         log(priv->queueid, "found txt record %s", buf);
         // expand some macros here - a very restricted subset of all possible spf macros
-        // only expand the first one.
+        // only expand the first instance of each.
         char *p = strstr(buf, "%{i}");
         if (p) {
-            char repl[maxlen];
             char adr[sizeof "255.255.255.255   "];
             adr[0] = '\0';
             inet_ntop(AF_INET, (const u_char *)&priv->ip, adr, sizeof(adr));
-            size_t bn = strlen(buf);
-            size_t an = strlen(adr);
-            if ((bn - 4 + an) < (size_t)maxlen) {
-                size_t n = p - buf;         // leading part length
-                strncpy(repl, buf, n);      // leading part
-                strcpy(repl+n, adr);        // replacement
-                strcpy(repl+n+an, buf+n+4); // trailing part
-                strcpy(buf, repl);
+            replace(buf, p, adr);
+            log(priv->queueid, "have txt record %s", buf);
             }
+        p = strstr(buf, "%{h}");
+        if (p) {
+            replace(buf, p, priv->helo);
+            log(priv->queueid, "have txt record %s", buf);
+        }
+        p = strstr(buf, "%{d}");
+        if (p) {
+            replace(buf, p, from);
             log(priv->queueid, "have txt record %s", buf);
         }
         //
--- a/src/context.h	Wed Apr 26 09:27:01 2017 -0700
+++ b/src/context.h	Fri May 19 13:44:13 2017 -0700
@@ -317,6 +317,7 @@
 
     void        log(const char *queueid, const char *msg, const char *v);
     bool        in_signing_set(const char *s, const char *signers);
+    void        replace(char *buf, char *p, const char *what);
     bool        resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level = 0);
     const char *acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, mlfiPriv *priv, string& msg);
     bool        ignore_host(const char *host);