diff src/context.cpp @ 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 91f2a127ec69
children c9b7b6dd1206
line wrap: on
line diff
--- 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);
         }
         //