# HG changeset patch # User Carl Byington # Date 1495226653 25200 # Node ID 22027ad2a28fa9199b0b13f8c325829cf4eddec8 # Parent 4901cdbc1fca0e9074dcd3ba358d7c9077841054 spf code now handles %{d} and %{h} macros; use envelope from value for spf if it is a subdomain of the header from domain diff -r 4901cdbc1fca -r 22027ad2a28f ChangeLog --- 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 diff -r 4901cdbc1fca -r 22027ad2a28f NEWS --- 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. diff -r 4901cdbc1fca -r 22027ad2a28f configure.in --- 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]) diff -r 4901cdbc1fca -r 22027ad2a28f dnsbl.spec.in --- 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 - 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 - 6.57-1 - spf code now handles mx,exists,ptr tags, multiple A records, %{i} macro diff -r 4901cdbc1fca -r 22027ad2a28f src/context.cpp --- 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); } // diff -r 4901cdbc1fca -r 22027ad2a28f src/context.h --- 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);