# HG changeset patch # User Carl Byington # Date 1492619174 25200 # Node ID e63c6b4835efeddf5d36a82b7a9a7b1eb2b71e8c # Parent 701ae46d9742a049f3a93beb09f0ce962c993bba refactor spf code; allow wildcard *.example.com in dkim signing restrictions diff -r 701ae46d9742 -r e63c6b4835ef ChangeLog --- a/ChangeLog Sun Apr 16 09:16:37 2017 -0700 +++ b/ChangeLog Wed Apr 19 09:26:14 2017 -0700 @@ -1,3 +1,7 @@ +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 701ae46d9742 -r e63c6b4835ef NEWS --- a/NEWS Sun Apr 16 09:16:37 2017 -0700 +++ b/NEWS Wed Apr 19 09:26:14 2017 -0700 @@ -1,3 +1,4 @@ +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. 6.54 2017-03-30 document dmarc vs dnsbl dkim/spf; switch to . rather than " " for dkim impossible signer 6.53 2017-03-17 suppress duplicate calls to acceptable_content(); redirect= in spf diff -r 701ae46d9742 -r e63c6b4835ef configure.in --- a/configure.in Sun Apr 16 09:16:37 2017 -0700 +++ b/configure.in Wed Apr 19 09:26:14 2017 -0700 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(dnsbl,6.55,carl@five-ten-sg.com) +AC_INIT(dnsbl,6.56,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) diff -r 701ae46d9742 -r e63c6b4835ef dnsbl.spec.in --- a/dnsbl.spec.in Sun Apr 16 09:16:37 2017 -0700 +++ b/dnsbl.spec.in Wed Apr 19 09:26:14 2017 -0700 @@ -155,6 +155,10 @@ %changelog +* Wed Apr 19 2017 Carl Byington - 6.56-1 +- refactor spf code +- allow wildcard *.example.com in dkim signing restrictions + * Sun Apr 16 2017 Carl Byington - 6.55-1 - require 3 dots in bare ip addresses. diff -r 701ae46d9742 -r e63c6b4835ef src/context.cpp --- a/src/context.cpp Sun Apr 16 09:16:37 2017 -0700 +++ b/src/context.cpp Wed Apr 19 09:26:14 2017 -0700 @@ -1112,13 +1112,20 @@ bool CONTEXT::in_signing_set(const char *s, const char *signers) { + // s is an actual signer + // signers is the set of acceptable signers, separated by commas size_t n = strlen(s); const char *p = signers; do { - if ((strncasecmp(p, s, n) == 0) && ((p[n] == '\0') || (p[n] == ','))) return true; - p = strchr(p, ','); - if (!p) return false; - p++; + const char *c = strchr(p, ','); + size_t m = (c) ? c-p : strlen(p); // length of this element in the signing set + if ((m == n) && (strncasecmp(p, s, n) == 0)) return true; // exact match + if ((*p == '*') && (n >= m)) { + // try for wildcard match + if (strncasecmp(p+1, s+n-(m-1), m-1) == 0) return true; + } + if (!c) return false; + p = c + 1; } while (true); } @@ -1131,12 +1138,18 @@ dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen); if (*buf) { log(priv->queueid, "found txt record %s", buf); - char *p = buf; + char *p = strchr(buf, ' '); // must start with 'v=spf1 ' + if (!p) return false; // broken spf char *e = p + strlen(p); // point to trailing null - while ((p = strstr(p, " ip4:"))) { - p += 5; + while (true) { + while (*p == ' ') p++; + if (p >= e) break; char *b = strchr(p, ' '); if (b) *b = '\0'; + if ((*p != '-') && (*p != '~')) { + if (*p == '+') p++; + if (strncmp(p, "ip4:", 4) == 0) { + p += 4; char *s = strchr(p, '/'); if (s) *s = '\0'; in_addr ipx; @@ -1153,51 +1166,32 @@ } } } - if (b) *b = ' '; - if (s) *s = '/'; - p = (b) ? b : e; } - p = buf; - while ((p = strstr(p, " a:"))) { - p += 3; - char *b = strchr(p, ' '); - if (b) *b = '\0'; + else if (strncmp(p, "a:", 2) == 0) { + p += 2; uint32_t ipy = ntohl(dns_interface(*priv, p, ns_t_a)); if (ipy == ip) { log(priv->queueid, "match %s", p); return true; } - if (b) *b = ' '; - p = (b) ? b : e; } - p = buf; - while ((p = strstr(p, " a"))) { - p += 2; - if ((*p == ' ') || (*p == '\0')) { + else if (strcmp(p, "a") == 0) { uint32_t ipy = ntohl(dns_interface(*priv, from, ns_t_a)); if (ipy == ip) { log(priv->queueid, "match %s", from); return true; } } - } - p = buf; - while ((level < 5) && ((p = strstr(p, " redirect=")))) { - p += 10; - char *b = strchr(p, ' '); - if (b) *b = '\0'; + else if ((level < 5) && (strncmp(p, "redirect=", 9) == 0)) { + p += 9; if (resolve_spf(p, ip, priv, level+1)) return true; - if (b) *b = ' '; - p = (b) ? b : e; } - p = buf; - while ((level < 5) && ((p = strstr(p, " include:")))) { - p += 9; - char *b = strchr(p, ' '); - if (b) *b = '\0'; + else if ((level < 5) && (strncmp(p, "include:", 8) == 0)) { + p += 8; if (resolve_spf(p, ip, priv, level+1)) return true; - if (b) *b = ' '; - p = (b) ? b : e; + } + } + p = (b) ? b+1 : e; } } return false;