Mercurial > dnsbl
diff src/context.cpp @ 412:e63c6b4835ef stable-6-0-56
refactor spf code; allow wildcard *.example.com in dkim signing restrictions
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 19 Apr 2017 09:26:14 -0700 |
parents | 29d54e7028f6 |
children | d5a1ed33d3ae |
line wrap: on
line diff
--- 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;