diff options
author | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-03 15:52:39 +0200 |
---|---|---|
committer | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-03 15:52:39 +0200 |
commit | a6a7d6ce079cabdaf2fa502b2e2cf15e5428ac6f (patch) | |
tree | b88cc7a8457658d67e0321718556ac807f6bccf3 /src/spf.c | |
parent | 00be7622c428f279872f84569f098ce16150f8a8 (diff) |
format files
Diffstat (limited to 'src/spf.c')
-rw-r--r-- | src/spf.c | 551 |
1 files changed, 310 insertions, 241 deletions
@@ -1,34 +1,36 @@ -#include "stralloc.h" +#include "spf.h" + #include "alloc.h" +#include "byte.h" +#include "case.h" +#include "fmt.h" #include "ip.h" +#include "scan.h" +#include "str.h" +#include "stralloc.h" + +#include "dns.h" #include "ipalloc.h" #include "ipme.h" -#include "str.h" -#include "fmt.h" -#include "scan.h" -#include "byte.h" #include "now.h" -#include "dns.h" -#include "case.h" -#include "spf.h" /* long lived SPF variables (output) */ -stralloc spfinfo = {0}; /* SPF results - see spf.h */ -stralloc spfrecord = {0}; /* Used for diagnostics */ +stralloc spfinfo = {0}; /* SPF results - see spf.h */ +stralloc spfrecord = {0}; /* Used for diagnostics */ /* s/qmail control SPF variables (input) */ -stralloc spflocalrules; /* Local rules provided here */ -stralloc spfexplain; /* Default SPF_EXPMSG in spf.h */ +stralloc spflocalrules; /* Local rules provided here */ +stralloc spfexplain; /* Default SPF_EXPMSG in spf.h */ -stralloc spfmf = {0}; /* aka envelopefrom = clientid */ -stralloc spfhelo = {0}; /* helo or domain part for spfmf */ -stralloc dnsname = {0}; /* FQDN of client host in DNS */ -stralloc spflocal = {0}; /* Receiving host */ +stralloc spfmf = {0}; /* aka envelopefrom = clientid */ +stralloc spfhelo = {0}; /* helo or domain part for spfmf */ +stralloc dnsname = {0}; /* FQDN of client host in DNS */ +stralloc spflocal = {0}; /* Receiving host */ -stralloc spfexpmsg = {0}; /* additional explanation given as 5xx SMTP response */ -stralloc expdomain = {0}; /* the domain, for which explanation is given */ +stralloc spfexpmsg = {0}; /* additional explanation given as 5xx SMTP response */ +stralloc expdomain = {0}; /* the domain, for which explanation is given */ int flagip6; stralloc domain = {0}; @@ -55,75 +57,81 @@ Exists+Expand: exists.com TXT "v=spf1 exists:%{ir}.%{l1r+-}._spf.%{d} -all" */ -int spf_query(const char *remoteip,const char *helo,const char *mf,const char *local,const int flagip) +int spf_query( + const char *remoteip, const char *helo, const char *mf, const char *local, const int flagip) { int at; int r = SPF_INIT; flagip6 = flagip; - if (!stralloc_copys(&spfinfo," ")) return SPF_NOMEM; - + if (!stralloc_copys(&spfinfo, " ")) return SPF_NOMEM; + switch (flagip6) { - case -1: if (!spf_info("MLocal=",remoteip)) return SPF_NOMEM; - if (!spf_info("R:","+")) return SPF_NOMEM; - break; - case 0: if (!ip4_scan(remoteip,ip4remote)) return SPF_SYNTAX; - if (ipme_is4(ip4remote) == 1) { - if (!spf_info("MLocal=",remoteip)) return SPF_NOMEM; - if (!spf_info("R:","+")) return SPF_NOMEM; - return SPF_ME; - } break; - case 1: if (!ip6_scan(remoteip,ip6remote)) return SPF_SYNTAX; - if (ipme_is6(ip6remote) == 1) { - if (!spf_info("MLocal=",remoteip)) return SPF_NOMEM; - if (!spf_info("R:","+")) return SPF_NOMEM; - return SPF_ME; - } break; + case -1: + if (!spf_info("MLocal=", remoteip)) return SPF_NOMEM; + if (!spf_info("R:", "+")) return SPF_NOMEM; + break; + case 0: + if (!ip4_scan(remoteip, ip4remote)) return SPF_SYNTAX; + if (ipme_is4(ip4remote) == 1) { + if (!spf_info("MLocal=", remoteip)) return SPF_NOMEM; + if (!spf_info("R:", "+")) return SPF_NOMEM; + return SPF_ME; + } + break; + case 1: + if (!ip6_scan(remoteip, ip6remote)) return SPF_SYNTAX; + if (ipme_is6(ip6remote) == 1) { + if (!spf_info("MLocal=", remoteip)) return SPF_NOMEM; + if (!spf_info("R:", "+")) return SPF_NOMEM; + return SPF_ME; + } + break; } if (helo && str_len(helo)) { - if (!stralloc_copys(&spfhelo,helo)) return SPF_NOMEM; + if (!stralloc_copys(&spfhelo, helo)) return SPF_NOMEM; } else { - if (!stralloc_copys(&spfhelo,"unknown")) return SPF_NOMEM; + if (!stralloc_copys(&spfhelo, "unknown")) return SPF_NOMEM; } if (!stralloc_0(&spfhelo)) return SPF_NOMEM; if (mf && str_len(mf)) { - if (!stralloc_copys(&spfmf,mf)) return SPF_NOMEM; + if (!stralloc_copys(&spfmf, mf)) return SPF_NOMEM; if (!stralloc_0(&spfmf)) return SPF_NOMEM; - at = str_rchr(spfmf.s,'@'); + at = str_rchr(spfmf.s, '@'); if (spfmf.s[at] == '@') { - if (!stralloc_copys(&domain,spfmf.s + at + 1)) return SPF_NOMEM; + if (!stralloc_copys(&domain, spfmf.s + at + 1)) return SPF_NOMEM; } else { -// if (!stralloc_0(&spfhelo)) return SPF_NOMEM; - if (!stralloc_copys(&domain,&spfhelo)) return SPF_NOMEM; + // if (!stralloc_0(&spfhelo)) return SPF_NOMEM; + if (!stralloc_copys(&domain, &spfhelo)) return SPF_NOMEM; } - if (!stralloc_copy(&identity,&domain)) return SPF_NOMEM; + if (!stralloc_copy(&identity, &domain)) return SPF_NOMEM; } if (!stralloc_0(&identity)) return SPF_NOMEM; if (local && str_len(local)) { - if (!stralloc_copys(&spflocal,local)) return SPF_NOMEM; + if (!stralloc_copys(&spflocal, local)) return SPF_NOMEM; } else { - if (!stralloc_copys(&spflocal,"localhost")) return SPF_NOMEM; + if (!stralloc_copys(&spflocal, "localhost")) return SPF_NOMEM; } if (!stralloc_0(&spflocal)) return SPF_NOMEM; - if (!spf_info("S=",remoteip)) return SPF_NOMEM; - if (!spf_info("O=",spfmf.s)) return SPF_NOMEM; - if (!spf_info("C=",identity.s)) return SPF_NOMEM; - if (!spf_info("H=",spfhelo.s)) return SPF_NOMEM; + if (!spf_info("S=", remoteip)) return SPF_NOMEM; + if (!spf_info("O=", spfmf.s)) return SPF_NOMEM; + if (!spf_info("C=", identity.s)) return SPF_NOMEM; + if (!spf_info("H=", spfhelo.s)) return SPF_NOMEM; - if (!stralloc_copy(&spfexpmsg,&spfexplain)) return SPF_NOMEM; - if (!stralloc_0(&spfexpmsg)) return SPF_NOMEM; + if (!stralloc_copy(&spfexpmsg, &spfexplain)) return SPF_NOMEM; + if (!stralloc_0(&spfexpmsg)) return SPF_NOMEM; recursion = 0; dnsname.len = 0; if (r == SPF_INIT) r = spf_lookup(&domain); if (r == SPF_LOOP) { - if (!spf_info("P=","Maximum nesting level exceeded; possible loop")) return SPF_NOMEM; - if (!spf_info("R:","e")) return SPF_NOMEM; + if (!spf_info("P=", "Maximum nesting level exceeded; possible loop")) return SPF_NOMEM; + if (!spf_info("R:", "e")) return SPF_NOMEM; } if (r < 0) r = SPF_UNKNOWN; /* return 2main */ @@ -136,14 +144,14 @@ static struct spf_aliases { char *alias; int defrc; } spf_aliases[] = { - { "allow", SPF_OK } -, { "pass", SPF_OK } -, { "deny", SPF_FAIL } -, { "softdeny",SPF_SOFTFAIL } -, { "fail", SPF_FAIL } -, { "softfail",SPF_SOFTFAIL } -, { "unknown", SPF_NEUTRAL } -, { 0, SPF_UNKNOWN } + { "allow", SPF_OK}, + { "pass", SPF_OK}, + { "deny", SPF_FAIL}, + {"softdeny", SPF_SOFTFAIL}, + { "fail", SPF_FAIL}, + {"softfail", SPF_SOFTFAIL}, + { "unknown", SPF_NEUTRAL}, + { 0, SPF_UNKNOWN} }; /** @@ -155,7 +163,7 @@ static struct spf_aliases { @return int r = SPF return code */ -int spf_lookup(stralloc *domain) +int spf_lookup(stralloc *domain) { stralloc spfdata = {0}; stralloc sa = {0}; @@ -164,7 +172,7 @@ int spf_lookup(stralloc *domain) int local_pos = -1; int localrules = 0; int q = -1; - int i, r; + int i, r; int begin, pos; int spfrc; int done; @@ -172,64 +180,64 @@ int spf_lookup(stralloc *domain) /* Fallthrough result */ - REDIRECT: - if (++recursion > LOOKUP_LIMIT) return SPF_EXHAUST; +REDIRECT: + if (++recursion > LOOKUP_LIMIT) return SPF_EXHAUST; - if (!stralloc_copys(&expdomain,domain->s)) return SPF_NOMEM; // *FIXME */ + if (!stralloc_copys(&expdomain, domain->s)) return SPF_NOMEM; // *FIXME */ - if (!stralloc_copys(&spfdata,"")) return SPF_NOMEM; - r = spf_records(&spfdata,domain); + if (!stralloc_copys(&spfdata, "")) return SPF_NOMEM; + r = spf_records(&spfdata, domain); if (!stralloc_0(domain)) return SPF_NOMEM; - if (first) if (!stralloc_copys(&spfrecord,"")) return SPF_NOMEM; - if (!stralloc_cats(&spfrecord,"(")) return SPF_NOMEM; - if (!stralloc_cat(&spfrecord,domain)) return SPF_NOMEM; - if (!stralloc_cats(&spfrecord,")")) return SPF_NOMEM; - if (!stralloc_cats(&spfrecord," => ")) return SPF_NOMEM; - if (!stralloc_cat(&spfrecord,&spfdata)) return SPF_NOMEM; - if (!stralloc_cats(&spfrecord,"\n")) return SPF_NOMEM; + if (first) + if (!stralloc_copys(&spfrecord, "")) return SPF_NOMEM; + if (!stralloc_cats(&spfrecord, "(")) return SPF_NOMEM; + if (!stralloc_cat(&spfrecord, domain)) return SPF_NOMEM; + if (!stralloc_cats(&spfrecord, ")")) return SPF_NOMEM; + if (!stralloc_cats(&spfrecord, " => ")) return SPF_NOMEM; + if (!stralloc_cat(&spfrecord, &spfdata)) return SPF_NOMEM; + if (!stralloc_cats(&spfrecord, "\n")) return SPF_NOMEM; if (!stralloc_0(&spfrecord)) return SPF_NOMEM; /* In spite of none-existing SPF data, use local rules as substitude */ - if (r == SPF_NONE) { /* No SPF records published */ - if (!first) { - return r; + if (r == SPF_NONE) { /* No SPF records published */ + if (!first) { + return r; } else { spfdata.len = 0; } - if (localrules) { /* append local ruleset */ + if (localrules) { /* append local ruleset */ local_pos = spfdata.len; - if (!stralloc_cats(&spfdata,spflocalrules.s)) return SPF_NOMEM; + if (!stralloc_cats(&spfdata, spflocalrules.s)) return SPF_NOMEM; } if (!stralloc_0(&spfdata)) return SPF_NOMEM; - if (!stralloc_copys(&expdomain,"")) return SPF_NOMEM; - - } else if (r == SPF_OK) { /* SPF records published */ + if (!stralloc_copys(&expdomain, "")) return SPF_NOMEM; + + } else if (r == SPF_OK) { /* SPF records published */ if (!stralloc_0(&spfdata)) return SPF_NOMEM; r = SPF_NEUTRAL; if (first && localrules) { /* try to add local rules before failure of all mechs */ pos = 0; - p = (char *) 0; + p = (char *)0; while (pos < spfdata.len) { - NXTOK(begin,pos,&spfdata); + NXTOK(begin, pos, &spfdata); if (!spfdata.s[begin]) continue; - if (p && spfdata.s[begin] != *p) p = (char *) 0; - if (!p && (spfdata.s[begin] == '-' || - spfdata.s[begin] == '~' || - spfdata.s[begin] == '?')) p = &spfdata.s[begin]; + if (p && spfdata.s[begin] != *p) p = (char *)0; + if (!p && (spfdata.s[begin] == '-' || spfdata.s[begin] == '~' || spfdata.s[begin] == '?')) + p = &spfdata.s[begin]; - if (p && p > spfdata.s && case_equals(spfdata.s + begin + 1,"all")) { + if (p && p > spfdata.s && case_equals(spfdata.s + begin + 1, "all")) { /* ok, we can insert the local rules at p */ local_pos = p - spfdata.s; - if (!stralloc_readyplus(&spfdata,spflocalrules.len)) return 0; + if (!stralloc_readyplus(&spfdata, spflocalrules.len)) return 0; p = spfdata.s + local_pos; - byte_copyr(p + spflocalrules.len,spfdata.len - local_pos,p); - byte_copy(p,spflocalrules.len,spflocalrules.s); + byte_copyr(p + spflocalrules.len, spfdata.len - local_pos, p); + byte_copy(p, spflocalrules.len, spflocalrules.s); spfdata.len += spflocalrules.len; pos += spflocalrules.len; @@ -241,8 +249,8 @@ int spf_lookup(stralloc *domain) for (i = 0; i < pos; i++) if (!spfdata.s[i]) spfdata.s[i] = ' '; } - - } else { /* Any other SPF return code */ + + } else { /* Any other SPF return code */ return r; } @@ -251,15 +259,15 @@ int spf_lookup(stralloc *domain) pos = 0; done = 0; while (pos < spfdata.len) { - NXTOK(begin,pos,&spfdata); + NXTOK(begin, pos, &spfdata); if (!spfdata.s[begin]) continue; - if (!done && localrules) { /* in local ruleset? */ + if (!done && localrules) { /* in local ruleset? */ if (local_pos >= 0 && begin >= local_pos) { if (begin < (local_pos + spflocalrules.len)) { - if (!stralloc_copys(&expdomain,"")) return SPF_NOMEM; + if (!stralloc_copys(&expdomain, "")) return SPF_NOMEM; } else { - if (!stralloc_copy(&expdomain,domain)) return SPF_NOMEM; + if (!stralloc_copy(&expdomain, domain)) return SPF_NOMEM; } } } @@ -270,88 +278,116 @@ int spf_lookup(stralloc *domain) if (*p == '=') { *p++ = 0; - if (case_equals(spfdata.s + begin,"redirect")) { /* modifiers are simply handled here */ + if (case_equals(spfdata.s + begin, "redirect")) { /* modifiers are simply handled here */ if (done) continue; - -// if (!stralloc_0(domain)) return SPF_NOMEM; - if (!spf_parse(&sa,p,domain->s)) return SPF_NOMEM; - if (!stralloc_copy(domain,&sa)) return SPF_NOMEM; - if (!spf_info("D=",p)) return SPF_NOMEM; + + // if (!stralloc_0(domain)) return SPF_NOMEM; + if (!spf_parse(&sa, p, domain->s)) return SPF_NOMEM; + if (!stralloc_copy(domain, &sa)) return SPF_NOMEM; + if (!spf_info("D=", p)) return SPF_NOMEM; r = SPF_UNKNOWN; goto REDIRECT; - } else if (case_equals(spfdata.s + begin,"default")) { /* we don't need those anymore */ - if (done) continue; + } else if (case_equals(spfdata.s + begin, "default")) { /* we don't need those anymore */ + if (done) continue; - for (da = spf_aliases; da->alias; ++da) - if (case_equals(da->alias,p)) break; + for (da = spf_aliases; da->alias; ++da) + if (case_equals(da->alias, p)) break; - r = da->defrc; - } else if (case_equals(spfdata.s + begin,"exp")) { /* exp= only on top level */ + r = da->defrc; + } else if (case_equals(spfdata.s + begin, "exp")) { /* exp= only on top level */ stralloc out = {0}; if (!first) continue; - if (!stralloc_copys(&sa,p)) return SPF_NOMEM; - - switch (dns_txt(&out,&sa)) { + if (!stralloc_copys(&sa, p)) return SPF_NOMEM; + + switch (dns_txt(&out, &sa)) { case -1: return SPF_NOMEM; - case 0: continue; /* nobody @home */ + case 0: continue; /* nobody @home */ } - if (!stralloc_copys(&spfexpmsg,out.s)) return SPF_NOMEM; - if (!stralloc_append(&spfexpmsg,"\n")) return SPF_NOMEM; + if (!stralloc_copys(&spfexpmsg, out.s)) return SPF_NOMEM; + if (!stralloc_append(&spfexpmsg, "\n")) return SPF_NOMEM; if (!stralloc_0(&spfexpmsg)) return SPF_NOMEM; } - } else if (!done) { /* and unknown modifiers are ignored */ - if (!stralloc_copys(&sa,spfdata.s + begin)) return SPF_NOMEM; + } else if (!done) { /* and unknown modifiers are ignored */ + if (!stralloc_copys(&sa, spfdata.s + begin)) return SPF_NOMEM; if (!stralloc_0(&sa)) return SPF_NOMEM; - + switch (spfdata.s[begin]) { - case '-': begin++; spfrc = SPF_FAIL; break; - case '~': begin++; spfrc = SPF_SOFTFAIL; break; - case '+': begin++; spfrc = SPF_OK; break; - case '?': begin++; spfrc = SPF_NEUTRAL; break; - default: spfrc = SPF_OK; + case '-': + begin++; + spfrc = SPF_FAIL; + break; + case '~': + begin++; + spfrc = SPF_SOFTFAIL; + break; + case '+': + begin++; + spfrc = SPF_OK; + break; + case '?': + begin++; + spfrc = SPF_NEUTRAL; + break; + default: spfrc = SPF_OK; } if (*p == '/') { *p++ = 0; - q = spf_mechanism(spfdata.s + begin,0,p,domain->s); + q = spf_mechanism(spfdata.s + begin, 0, p, domain->s); } else { if (*p) *p++ = 0; - i = str_chr(p,'/'); + i = str_chr(p, '/'); if (p[i] == '/') { p[i++] = 0; - q = spf_mechanism(spfdata.s + begin,p,p + i,domain->s); + q = spf_mechanism(spfdata.s + begin, p, p + i, domain->s); } else if (i > 0) { - q = spf_mechanism(spfdata.s + begin,p,0,domain->s); + q = spf_mechanism(spfdata.s + begin, p, 0, domain->s); } else { - q = spf_mechanism(spfdata.s + begin,0,0,domain->s); + q = spf_mechanism(spfdata.s + begin, 0, 0, domain->s); } } if (q == SPF_OK) q = spfrc; switch (q) { - case SPF_OK: if (!spf_info("R:","+")) return SPF_NOMEM; break; - case SPF_NEUTRAL: if (!spf_info("R:","?")) return SPF_NOMEM; break; - case SPF_SYNTAX: if (!spf_info("P=","Unknown parse error")) return SPF_NOMEM; - if (!spf_info("R:","e")) return SPF_NOMEM; break; - case SPF_SOFTFAIL: if (!spf_info("R:","~")) return SPF_NOMEM; break; - case SPF_FAIL: if (!spf_info("R:","-")) return SPF_NOMEM; break; - case SPF_EXT: if (!spf_info("P=","Unknown SPF mechanism")) return SPF_NOMEM; break; - case SPF_ERROR: if (localrules) if (local_pos >= 0 && begin >= local_pos) break; - if (!spf_info("R:","o")) return SPF_NOMEM; q = SPF_NONE; break; - case SPF_NONE: continue; + case SPF_OK: + if (!spf_info("R:", "+")) return SPF_NOMEM; + break; + case SPF_NEUTRAL: + if (!spf_info("R:", "?")) return SPF_NOMEM; + break; + case SPF_SYNTAX: + if (!spf_info("P=", "Unknown parse error")) return SPF_NOMEM; + if (!spf_info("R:", "e")) return SPF_NOMEM; + break; + case SPF_SOFTFAIL: + if (!spf_info("R:", "~")) return SPF_NOMEM; + break; + case SPF_FAIL: + if (!spf_info("R:", "-")) return SPF_NOMEM; + break; + case SPF_EXT: + if (!spf_info("P=", "Unknown SPF mechanism")) return SPF_NOMEM; + break; + case SPF_ERROR: + if (localrules) + if (local_pos >= 0 && begin >= local_pos) break; + if (!spf_info("R:", "o")) return SPF_NOMEM; + q = SPF_NONE; + break; + case SPF_NONE: continue; } r = q; - done = 1; /* we're done, no more mechanisms */ + done = 1; /* we're done, no more mechanisms */ } } /* we fell through, no local rule applied */ if (!done) - if (!stralloc_copy(&expdomain,domain)) return SPF_NOMEM; + if (!stralloc_copy(&expdomain, domain)) return SPF_NOMEM; return r; } @@ -360,23 +396,23 @@ int spf_lookup(stralloc *domain) static struct mechanisms { char *mechanism; - int (*func)(char *spfspec,char *prefix); + int (*func)(char *spfspec, char *prefix); unsigned int use_spfspec : 1; - unsigned int use_prefix : 1; - unsigned int expands : 1; - unsigned int filldomain : 1; - int defresult : 4; + unsigned int use_prefix : 1; + unsigned int expands : 1; + unsigned int filldomain : 1; + int defresult : 4; } mechanisms[] = { - { "all", 0, 0,0,0,0,SPF_OK } -, { "include", spf_include,1,0,1,0,0 } -, { "a", spf_a, 1,1,1,1,0 } -, { "mx", spf_mx, 1,1,1,1,0 } -, { "ptr", spf_ptr, 1,0,1,1,0 } -, { "ip4", spf_ip4, 1,1,0,0,0 } -, { "ip6", spf_ip6, 1,1,0,0,0 } -, { "exists", spf_exists, 1,0,1,0,0 } -, { "extension",0, 1,1,0,0,SPF_EXT } -, { 0, 0, 1,1,0,0,SPF_EXT } + { "all", 0, 0, 0, 0, 0, SPF_OK}, + { "include", spf_include, 1, 0, 1, 0, 0}, + { "a", spf_a, 1, 1, 1, 1, 0}, + { "mx", spf_mx, 1, 1, 1, 1, 0}, + { "ptr", spf_ptr, 1, 0, 1, 1, 0}, + { "ip4", spf_ip4, 1, 1, 0, 0, 0}, + { "ip6", spf_ip6, 1, 1, 0, 0, 0}, + { "exists", spf_exists, 1, 0, 1, 0, 0}, + {"extension", 0, 1, 1, 0, 0, SPF_EXT}, + { 0, 0, 1, 1, 0, 0, SPF_EXT} }; /** @@ -388,7 +424,7 @@ static struct mechanisms { @return int r */ -int spf_mechanism(char *mechanism,char *spfspec,char *prefix,char *domain) +int spf_mechanism(char *mechanism, char *spfspec, char *prefix, char *domain) { struct mechanisms *mech; stralloc sa = {0}; @@ -396,28 +432,28 @@ int spf_mechanism(char *mechanism,char *spfspec,char *prefix,char *domain) int pos; for (mech = mechanisms; mech->mechanism; mech++) - if (case_equals(mech->mechanism,mechanism)) break; + if (case_equals(mech->mechanism, mechanism)) break; if (mech->use_spfspec && !spfspec && mech->filldomain) spfspec = domain; if (!mech->use_spfspec != !spfspec) return SPF_SYNTAX; if (mech->use_prefix && !get_prefix(prefix)) return SPF_SYNTAX; if (!mech->func) return mech->defresult; - if (!stralloc_readyplus(&sa,1)) return SPF_NOMEM; + if (!stralloc_readyplus(&sa, 1)) return SPF_NOMEM; - if (mech->expands && case_diffs(spfspec,domain)) { - if (!spf_parse(&sa,spfspec,domain)) return SPF_NOMEM; + if (mech->expands && case_diffs(spfspec, domain)) { + if (!spf_parse(&sa, spfspec, domain)) return SPF_NOMEM; for (pos = 0; (sa.len - pos) > 255;) { - pos += byte_chr(sa.s + pos,sa.len - pos,'.'); + pos += byte_chr(sa.s + pos, sa.len - pos, '.'); if (pos < sa.len) pos++; } sa.len -= pos; - if (pos > 0) byte_copy(sa.s,sa.len,sa.s + pos); + if (pos > 0) byte_copy(sa.s, sa.len, sa.s + pos); if (!stralloc_0(&sa)) return SPF_NOMEM; spfspec = sa.s; } - r = mech->func(spfspec,prefix); + r = mech->func(spfspec, prefix); return r; } @@ -428,12 +464,12 @@ int spf_mechanism(char *mechanism,char *spfspec,char *prefix,char *domain) @return int r = 1 ok; 0 failure */ -int spf_include(char *spfspec,char *prefix) +int spf_include(char *spfspec, char *prefix) { stralloc sa = {0}; int r; - if (!stralloc_copys(&sa,spfspec)) return SPF_NOMEM; + if (!stralloc_copys(&sa, spfspec)) return SPF_NOMEM; r = spf_lookup(&sa); switch (r) { @@ -444,8 +480,8 @@ int spf_include(char *spfspec,char *prefix) case SPF_FAIL: r = SPF_NONE; break; } if (!stralloc_0(&sa)) return SPF_NOMEM; - if (!spf_info("I=",sa.s)) return SPF_NOMEM; - + if (!spf_info("I=", sa.s)) return SPF_NOMEM; + return r; } @@ -458,34 +494,39 @@ int spf_include(char *spfspec,char *prefix) @return int r = 1 ok; 0 failure */ -int spf_parse(stralloc *sa,char *spfspec,char *domain) +int spf_parse(stralloc *sa, char *spfspec, char *domain) { char *p; int pos; char append; - if (!stralloc_readyplus(sa,3)) return 0; - if (!stralloc_copys(sa,"")) return 0; + if (!stralloc_readyplus(sa, 3)) return 0; + if (!stralloc_copys(sa, "")) return 0; for (p = spfspec; *p; ++p) { append = *p; - if (byte_equal(p,1,"%")) { + if (byte_equal(p, 1, "%")) { p++; switch (*p) { case '%': break; case '_': append = ' '; break; - case '-': if (!stralloc_cats(sa,"%20")) return 0; continue; + case '-': + if (!stralloc_cats(sa, "%20")) return 0; + continue; case '{': - pos = str_chr(p,'}'); - if (p[pos] != '}') { p--; break; } - p[pos] = '\0'; - if (!spf_macros(sa,p + 1,domain)) return 0; + pos = str_chr(p, '}'); + if (p[pos] != '}') { + p--; + break; + } + p[pos] = '\0'; + if (!spf_macros(sa, p + 1, domain)) return 0; p += pos; continue; default: p--; } } - if (!stralloc_append(sa,&append)) return 0; + if (!stralloc_append(sa, &append)) return 0; } return 1; @@ -499,7 +540,7 @@ int spf_parse(stralloc *sa,char *spfspec,char *domain) @return int r = 1 ok; 0 failure */ -int spf_macros(stralloc *expand,char *macro,char *domain) +int spf_macros(stralloc *expand, char *macro, char *domain) { static const char hextab[] = "0123456789abcdef"; stralloc sa = {0}; @@ -509,139 +550,167 @@ int spf_macros(stralloc *expand,char *macro,char *domain) unsigned long u; char ch = {0}; char ascii; - int pos, i, n; - int start = expand->len; + int pos, i, n; + int start = expand->len; /* URL encoding - hidden in RFC 7208 Sec. 7.3 */ - if (*macro == 'x') { urlencode = -1; ++macro; } else urlencode = 0; + if (*macro == 'x') { + urlencode = -1; + ++macro; + } else + urlencode = 0; ch = *macro; - if (!ch) { return 1; } - if (ch >= 'A' && ch <= 'Z') { ch += 32; urlencode = 1; } + if (!ch) { + return 1; + } + if (ch >= 'A' && ch <= 'Z') { + ch += 32; + urlencode = 1; + } if (urlencode == -1) ch -= 32; /* No. digits determine number of printed labels */ - + i = 0; while (*macro) { i++; if (*macro == '}') break; if (*macro >= '0' && *macro <= '9') { - scan_ulong(macro,&u); ndigits = u; - } else if (i > 1 && *macro == 'r') { reverse = 1; break; } /* Reverse representation */ + scan_ulong(macro, &u); + ndigits = u; + } else if (i > 1 && *macro == 'r') { + reverse = 1; + break; + } /* Reverse representation */ macro++; } - switch (ch) { /* see RFC7208 sec. 7.2 */ - case 's': case 'S': - if (!stralloc_readyplus(&sa,spfmf.len)) return 0; - if (!stralloc_copys(&sa,spfmf.s)) return 0; + switch (ch) { /* see RFC7208 sec. 7.2 */ + case 's': + case 'S': + if (!stralloc_readyplus(&sa, spfmf.len)) return 0; + if (!stralloc_copys(&sa, spfmf.s)) return 0; break; - case 'l': case 'L': - i = byte_rchr(spfmf.s,spfmf.len,'@'); + case 'l': + case 'L': + i = byte_rchr(spfmf.s, spfmf.len, '@'); if (i < spfmf.len) { - if (!stralloc_copyb(&sa,spfmf.s,i)) return 0; + if (!stralloc_copyb(&sa, spfmf.s, i)) return 0; } else { - if (!stralloc_copys(&sa,"postmaster")) return 0; + if (!stralloc_copys(&sa, "postmaster")) return 0; } break; - case 'o': case 'O': - i = byte_rchr(spfmf.s,spfmf.len,'@') + 1; + case 'o': + case 'O': + i = byte_rchr(spfmf.s, spfmf.len, '@') + 1; if (i > spfmf.len) break; - if (!stralloc_copys(&sa,spfmf.s + i)) return 0; + if (!stralloc_copys(&sa, spfmf.s + i)) return 0; break; - case 'd': case 'D': - if (!stralloc_copys(&sa,domain)) return 0; /* the hack for 'Z'; Russions everywhere ;-) */ + case 'd': + case 'D': + if (!stralloc_copys(&sa, domain)) return 0; /* the hack for 'Z'; Russions everywhere ;-) */ break; - case 'i': case 'c': case 'I': case 'C': - if (!stralloc_ready(&sa,IPFMT)) return 0; + case 'i': + case 'c': + case 'I': + case 'C': + if (!stralloc_ready(&sa, IPFMT)) return 0; if (flagip6) { - sa.len = ip6_fmt(sa.s,ip6remote); + sa.len = ip6_fmt(sa.s, ip6remote); } else { - sa.len = ip4_fmt(sa.s,ip4remote); + sa.len = ip4_fmt(sa.s, ip4remote); } break; - case 'p': case 'P': - if (!dnsname.len) spf_ptr(domain,0); + case 'p': + case 'P': + if (!dnsname.len) spf_ptr(domain, 0); if (dnsname.len) { - if (!stralloc_copys(&sa,dnsname.s)) return 0; + if (!stralloc_copys(&sa, dnsname.s)) return 0; } else { - if (!stralloc_copys(&sa,"unknown")) return 0; + if (!stralloc_copys(&sa, "unknown")) return 0; } break; - case 'h': case 'H': - if (!stralloc_copys(&sa,spfhelo.s)) return 0; /* FIXME: FQDN? */ + case 'h': + case 'H': + if (!stralloc_copys(&sa, spfhelo.s)) return 0; /* FIXME: FQDN? */ break; - case 't': case 'T': - if (!stralloc_ready(&sa,FMT_ULONG)) return 0; - sa.len = fmt_ulong(sa.s,(unsigned long)now()); + case 't': + case 'T': + if (!stralloc_ready(&sa, FMT_ULONG)) return 0; + sa.len = fmt_ulong(sa.s, (unsigned long)now()); break; - case 'v': case 'V': + case 'v': + case 'V': if (flagip6) { - if (!stralloc_copys(&sa,"ip6")) return 0; + if (!stralloc_copys(&sa, "ip6")) return 0; } else { - if (!stralloc_copys(&sa,"in-addr")) return 0; + if (!stralloc_copys(&sa, "in-addr")) return 0; } break; - case 'r': case 'R': - if (!stralloc_copy(&sa,&spflocal)) return 0; + case 'r': + case 'R': + if (!stralloc_copy(&sa, &spflocal)) return 0; break; default: break; } - if (!stralloc_0(&sa)) return 0; // XXX + if (!stralloc_0(&sa)) return 0; // XXX if (reverse) { n = 0; for (i = 1; i <= sa.len; i++) { if ((ndigits == -1) || (n < ndigits)) { - if (!byte_diff(sa.s + sa.len - i - 1,1,".") || (i == sa.len)) { + if (!byte_diff(sa.s + sa.len - i - 1, 1, ".") || (i == sa.len)) { n++; - if (!stralloc_cats(expand,sa.s + sa.len - i)) return 0; + if (!stralloc_cats(expand, sa.s + sa.len - i)) return 0; if (i < sa.len) { sa.s[sa.len - i - 1] = 0; - if (!stralloc_cats(expand,".")) return 0; - } + if (!stralloc_cats(expand, ".")) return 0; + } } - } + } } } else if (ndigits != -1) { n = pos = 0; for (i = 1; i <= sa.len; i++) { if (n < ndigits) { - if (!byte_diff(sa.s + i,1,".")) { n++; pos = i; } + if (!byte_diff(sa.s + i, 1, ".")) { + n++; + pos = i; + } } } - if (!stralloc_catb(expand,sa.s,pos)) return 0; - } else - if (!stralloc_cats(expand,sa.s)) return 0; + if (!stralloc_catb(expand, sa.s, pos)) return 0; + } else if (!stralloc_cats(expand, sa.s)) + return 0; if (urlencode) { - stralloc_copyb(&sa,expand->s + start,expand->len - start); + stralloc_copyb(&sa, expand->s + start, expand->len - start); expand->len = start; for (i = 0; i < sa.len; ++i) { ch = sa.s[i]; if (urlchr_table[(unsigned char)ch]) { - if (!stralloc_readyplus(expand,3)) return 0; - if (!stralloc_append(expand,"%")) return 0; + if (!stralloc_readyplus(expand, 3)) return 0; + if (!stralloc_append(expand, "%")) return 0; ascii = hextab[(unsigned char)ch >> 4]; - if (!stralloc_append(expand,&ascii)) return 0; + if (!stralloc_append(expand, &ascii)) return 0; ascii = hextab[(unsigned char)ch & 0x0f]; - if (!stralloc_append(expand,&ascii)) return 0; + if (!stralloc_append(expand, &ascii)) return 0; } else { - if (!stralloc_append(expand,&ch)) return 0; + if (!stralloc_append(expand, &ch)) return 0; } } - } + } return 1; } -int spf_info(char *s,const char *t) +int spf_info(char *s, const char *t) { - if (!stralloc_cats(&spfinfo,s)) return 0; - if (!stralloc_cats(&spfinfo,t)) return 0; - if (!stralloc_cats(&spfinfo," ")) return 0; + if (!stralloc_cats(&spfinfo, s)) return 0; + if (!stralloc_cats(&spfinfo, t)) return 0; + if (!stralloc_cats(&spfinfo, " ")) return 0; return 1; } |