# HG changeset patch # User Carl Byington # Date 1552232967 25200 # Node ID 428de28b34b79335e06845c7532213c4aa262c86 # Parent 95b4666a2a0ba8f8349859c390c1ea14c5994209 cleanup code for adding extra spf data in dkim_from diff -r 95b4666a2a0b -r 428de28b34b7 ChangeLog --- a/ChangeLog Sat Mar 09 18:53:12 2019 -0800 +++ b/ChangeLog Sun Mar 10 08:49:27 2019 -0700 @@ -1,4 +1,4 @@ -6.75 2019-03-09 +6.75 2019-03-10 change dkim_from syntax to allow "signer1,signer2;spf data" 6.74 2018-12-24 diff -r 95b4666a2a0b -r 428de28b34b7 NEWS --- a/NEWS Sat Mar 09 18:53:12 2019 -0800 +++ b/NEWS Sun Mar 10 08:49:27 2019 -0700 @@ -1,4 +1,4 @@ -6.75 2019-03-09 change dkim_from syntax to allow "signer1,signer2;spf data" +6.75 2019-03-10 change dkim_from syntax to allow "signer1,signer2;spf data" 6.74 2018-12-24 add debug code for spf check with microsoft /14 6.73 2018-09-18 ignore dnswl entries if the sender is <> 6.72 2018-06-06 add unsigned_black for enforcement of dmarc policy diff -r 95b4666a2a0b -r 428de28b34b7 dnsbl.dkim.conf --- a/dnsbl.dkim.conf Sat Mar 09 18:53:12 2019 -0800 +++ b/dnsbl.dkim.conf Sun Mar 10 08:49:27 2019 -0700 @@ -1,3 +1,23 @@ +aim.com unsigned_black "aim.com,mx.aim.com"; +aol.com unsigned_black "aol.com,mx.aol.com"; +aol.de unsigned_black aol.de; +aol.fr unsigned_black aol.fr; +emailbuybuybaby.com unsigned_black emailbuybuybaby.com; +federalreserve.com unsigned_black federalreserve.com; +jusmisiones.gov.ar unsigned_black jusmisiones.gov.ar; +my.com unsigned_black my.com; +westernunion.com unsigned_black westernunion.com; +yahoo.ca unsigned_black yahoo.ca; +yahoo.co.in unsigned_black yahoo.co.in; +yahoo.co.jp unsigned_black "yahoo.com,yahoo.co.jp"; +yahoo.com.my unsigned_black yahoo.com.my; +yahoo.com.tw unsigned_black yahoo.com.tw; +yahoo.com unsigned_black yahoo.com; +yahoo.co.uk unsigned_black yahoo.co.uk; +yahoo.de unsigned_black yahoo.de; +yahoo.fr unsigned_black yahoo.fr; +yahoo.in unsigned_black yahoo.in; +# 1039rxp.com require_signed 1039rxp-com.20150623.gappssmtp.com; 10news.com require_signed ewscripps.onmicrosoft.com; 123g.info require_signed 123g.info; @@ -107,7 +127,6 @@ aiche.org require_signed aiche.org; aiga.org require_signed "aiga.org,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; aig.com signed_white aig.com; // some unsigned mail via messagelabs -aim.com unsigned_black "aim.com,mx.aim.com"; airbnb.com require_signed email.airbnb.com; airconway.com require_signed airconway.ccsend.com; airstoc.com require_signed airstoc.com; @@ -171,9 +190,6 @@ anpanama.com require_signed anpanama.com; anthempropane.com require_signed anthempropane.com; anthemww.com require_signed matw.onmicrosoft.com -aol.com unsigned_black "aol.com,mx.aol.com"; -aol.de unsigned_black aol.de; -aol.fr unsigned_black aol.fr; apgrents.com require_signed icontactmail6.com; aplaceformom.com require_signed "aplaceformom.com,aplaceformom.onmicrosoft.com"; app.bamboohr.com require_signed app.bamboohr.com; @@ -204,7 +220,7 @@ associationvoice.com require_signed associationvoice.com; assuretyconsulting.com signed_white "assuretyconsulting.com,hubspot.com"; // some unsigned mail via salesforce, no spf record astc.org require_signed icontactmail3.com; -astm.org signed_white astm.org; // some unsigned mail from their own servers +astm.org require_signed astm.org; astrazeneca.com require_signed azcollaboration.onmicrosoft.com; asurion.com require_signed asurion.com; atautosbdc.com require_signed sg01.motosnap.com; @@ -794,7 +810,6 @@ email.bjs.com require_signed email.bjs.com; email.bostonglobe.com require_signed email.bostonglobe.com; email.box.com require_signed "email.box.com,mktdns.com"; -emailbuybuybaby.com unsigned_black emailbuybuybaby.com; email.caesars-marketing.com require_signed email.caesars-marketing.com; email.calphalon.com require_signed email.calphalon.com; email.cbssports.com require_signed email.cbssports.com; @@ -1158,7 +1173,7 @@ e.westernjournalism.com require_signed e.westernjournalism.com; e.winecountrygiftbaskets.com require_signed e.winecountrygiftbaskets.com; e.wintersilks.com require_signed e.wintersilks.com; -e.wisteria.com require_signed "e.wisteria.com,wisteria.com"; +e.wisteria.com require_signed "e.wisteria.com,wisteria.com,esp1.co"; ewomennetwork.com signed_white ewomennetwork.com; e.woolovers.com require_signed e.woolovers.com; exacttarget.change.org require_signed exacttarget.change.org; @@ -1199,7 +1214,6 @@ fastspring.com require_signed fastspring.com; fatherly.com require_signed fatherly-com.20150623.gappssmtp.com; fedbarlive.org signed_white "emsend.com,em.secureserver.net"; // emsend signing with domainkeys, not dkim -federalreserve.com unsigned_black federalreserve.com; fedex.com require_signed fedex.com; fedgovconnect.org require_signed fedgovconnect-org.20150623.gappssmtp.com; feedvisor.com require_signed "feedvisor-com.20150623.gappssmtp.com,feedvisor.com"; @@ -1225,7 +1239,7 @@ fladems.com signed_white "fladems.com,bounce.bluestatedigital.com"; fladems.org signed_white bounce.bluestatedigital.com; flagandbanner.com require_signed omktmail2.com; -flagsource.com require_signed "flagsource.ccsend.com,*.onmicrosoft.com; +flagsource.com require_signed "flagsource.ccsend.com,*.onmicrosoft.com"; flaticon.com require_signed "mandrillapp.com,mailchimpapp.net,flaticon.com"; flaviar.com require_signed flaviar.com; flexjobs.com require_signed flexjobs.com; @@ -1532,7 +1546,6 @@ joshshapiro.org signed_white bounce.bluestatedigital.com; jstor.org require_signed jstor.org; judsonsart.com require_signed icontactmail3.com; -jusmisiones.gov.ar unsigned_black jusmisiones.gov.ar; justice.org require_signed justice.org; kaarmadealer.com require_signed kaarmadealer.com; kaiserhealthnews.org require_signed kff.org; @@ -1685,7 +1698,7 @@ mailcenter.usaa.com require_signed usaa.com; mail.change.org require_signed mail.change.org; mailchimp.com require_signed mailchimp.com; -mail.citipricerewind.com require_signed mail.citipricerewind.com; // stupid banks with multiple branding; +mail.citipricerewind.com require_signed mail.citipricerewind.com; // stupid banks with multiple branding mail.crateandbarrel.com require_signed mail.crateandbarrel.com; mail.digiday.com require_signed mail.digiday.com; mail.disneydestinations.com require_signed mail.disneydestinations.com; @@ -1868,7 +1881,7 @@ momentummgt.com require_signed "mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; momscleanairforce.org require_signed server8839.e-activist.com; monotype.com require_signed monotype.com; -monster.com signed_white monster.com; // some unsigned mail via mailsorter.be.tmpw.net; +monster.com signed_white monster.com; // some unsigned mail via mailsorter.be.tmpw.net monsterequip.com require_signed icontactmail6.com; monsterscooterparts.com require_signed monsterscooterparts.com; morning7.theskimm.com require_signed morning7.theskimm.com; @@ -1900,14 +1913,13 @@ murphyforflorida.com signed_white bounce.bluestatedigital.com; musicacademy.org require_signed "mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; musictoday.com require_signed "mg.musictoday.com,musictoday.com"; -musictogether.com signed_white musictogether.ccsend.com; // some unsigned mail via mail.musictogether.com; +musictogether.com signed_white musictogether.ccsend.com; // some unsigned mail via mail.musictogether.com mvsend.com require_signed mvsend.com; mxtoolbox.com require_signed mxtoolbox.com; myamextravel.com require_signed myamextravel.com; my.ba.com require_signed my.ba.com; mybbb.org require_signed "mybbb.org,auth.ccsend.com"; mycase.com signed_white mycase.com; // some unsigned mail from salesforce fails strong spf -my.com unsigned_black my.com; my.containerstore.com require_signed my.containerstore.com; myddi.com require_signed myddi.com; myemma.com require_signed myemma.com; @@ -2152,7 +2164,7 @@ paylocity.com require_signed paylocity.com; paypal.com require_signed paypal.com; payproglobal.com require_signed email.payproglobal.com; -payrollcentric.com signed_white "smtpserver.email,smtpsendemail.com,smtpsendmail.com,smtp.com,em.evolutionhcm.com,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; // some unsigned mail via their own servers +payrollcentric.com require_signed "smtpserver.email,smtpsendemail.com,smtpsendmail.com,smtp.com,em.evolutionhcm.com,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net;ptr:shspma.com"; payrollcentric.zendesk.com require_signed "gmailmarkup.zendesk.com,zendesk.com"; payroll.fidelity.com require_signed payroll.fidelity.com; paytrace.com require_signed paytrace.com; @@ -2384,7 +2396,7 @@ salamanderresort.com require_signed "salamanderresort.com,salamanderhotels.com"; salonrunner.com require_signed salonrunner.com; samplingsupplies.com require_signed samplingsupplies.com; -sandpiperrental.com require_signed "sandpiperrental.com,amazonses.com,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net";; +sandpiperrental.com require_signed "sandpiperrental.com,amazonses.com,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; sanofi.com require_signed sanofi.com; // unsigned spam via exacttarget santamariasun.com require_signed santamariasun-com.20150623.gappssmtp.com; santander.us require_signed santander.us; @@ -2736,7 +2748,7 @@ undertone.com signed_white undertone.com; // mbmg client unionbank.com signed_white unionbank.com; // some unsigned mail via cashedge unionhomemortgage.com require_signed eeoo.co; -unionleague.org signed_white "unionleague.org,unionleague.ccsend.com"; // some unsigned mail via ppe-hosted.com, wrong spf record, include: vs a:dispatch-us.ppe-hosted.com +unionleague.org require_signed "unionleague.org,unionleague.ccsend.com;a:dispatch-us.ppe-hosted.com"; uniquephoto.com require_signed uniquephoto.com; united.com require_signed united.com; // unsigned but passes spf unitedyacht.com require_signed "mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; @@ -2843,7 +2855,6 @@ wellsfargorewards.com require_signed wellsfargorewards.com; wellspouse.org require_signed wellspouse.org; wesendit.com require_signed wesendit.com; -westernunion.com unsigned_black westernunion.com; westgermanbmw.com signed_white "westgermanbmw.com,xtime.com"; // some unsigned mail via media-mastermind westinvacations.com require_signed iilg.onmicrosoft.com; westrock.com signed_white westrockco.onmicrosoft.com; // some unsigned mail via outlook @@ -2881,8 +2892,8 @@ worldsciencefestival.com require_signed worldsciencefestival.com; wrigley.com require_signed "wrigley.com,e2ma.net"; wsdisplay.com require_signed wsdisplay-com.20150623.gappssmtp.com; -wsfsbank.com require_signed wsfsbank.com; -wsj.com signed_white "wsj.com,wsj-com.20150623.gappssmtp.com"; // some unsigned mail via iphmx.com +wsfsbank.com require_signed "wsfsbank.com;ptr:bankserv.com"; +wsj.com require_signed "wsj.com,wsj-com.20150623.gappssmtp.com;ptr:iphmx.com"; wstelecomlaw.com require_signed sapronov.onmicrosoft.com; wtcphila.org require_signed "wtcphila.onmicrosoft.com,wtcphila.ccsend.com,mandrillapp.com,mailchimpapp.net,*.mcsignup.com,*.mcsv.net,*.rsgsv.net,*.mcdlv.net"; wullo.com require_signed wullo.com; @@ -2894,17 +2905,7 @@ xks.com require_signed xks.com; xlive.tm00.com require_signed tm00.com; xode.com require_signed xode.com; -yahoo.ca unsigned_black yahoo.ca; -yahoo.co.in unsigned_black yahoo.co.in; -yahoo.co.jp unsigned_black "yahoo.com,yahoo.co.jp"; -yahoo.com.my unsigned_black yahoo.com.my; -yahoo.com.tw unsigned_black yahoo.com.tw; -yahoo.com unsigned_black yahoo.com; -yahoo.co.uk unsigned_black yahoo.co.uk; -yahoo.de unsigned_black yahoo.de; -yahoo.fr unsigned_black yahoo.fr; yahoo-inc.com require_signed yahoo-inc.com; // password resets, etc -yahoo.in unsigned_black yahoo.in; yellowstone.org require_signed mta-bbcspool.convio.net; yelp.com require_signed yelp.com; yipit.com require_signed yipit.com; diff -r 95b4666a2a0b -r 428de28b34b7 dnsbl.spec.in --- a/dnsbl.spec.in Sat Mar 09 18:53:12 2019 -0800 +++ b/dnsbl.spec.in Sun Mar 10 08:49:27 2019 -0700 @@ -151,7 +151,7 @@ %changelog -* Sat Mar 09 2019 Carl Byington - 6.75-1 +* Sun Mar 10 2019 Carl Byington - 6.75-1 - change dkim_from syntax to allow "signer1,signer2;spf data" * Mon Dec 24 2018 Carl Byington - 6.74-1 diff -r 95b4666a2a0b -r 428de28b34b7 src/context.cpp --- a/src/context.cpp Sat Mar 09 18:53:12 2019 -0800 +++ b/src/context.cpp Sun Mar 10 08:49:27 2019 -0700 @@ -616,9 +616,10 @@ } -DKIM::DKIM(const char *action_, const char *signer_) { +DKIM::DKIM(const char *action_, const char *signer_, const char*extraspf_) { action = action_; signer = signer_; + extraspf = extraspf_; } @@ -1111,58 +1112,42 @@ } -const char *CONTEXT::extra_spf_data(const char *signers) { - const char *e = strchr(signers, ';'); - if (e) e++; - return e; -} - - 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; - char *e = (char *)strchr(p, ';'); // only search up to ; which separates signers from extra spf data - if (e) *e = '\0'; - bool rc = true; do { 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)) break; // exact match + if ((m == n) && (strncasecmp(p, s, n) == 0)) return true; // exact match if ((*p == '*') && (n >= m)) { - if (strncasecmp(p+1, s+n-(m-1), m-1) == 0) break; // wildcard match + if (strncasecmp(p+1, s+n-(m-1), m-1) == 0) return true; // wildcard match } - if (!c) { - rc = false; - break; - } + if (!c) return false; p = c + 1; } while (true); - if (e) *e = ';'; - return rc; } -void CONTEXT::replace(char *buf, char *p, const char *what) +void CONTEXT::replace(char *buf, char *p, int nn, const char *what) { - // replace 4 chars in buf starting at p with what + // replace nn 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) { + if ((bn - nn + 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(repl+n+wn, buf+n+nn); // trailing part strcpy(buf, repl); } } -bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, const char *signers) +bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, const char *extraspf) { - const char *extraspf = extra_spf_data(signers); // ip is in host order if (priv->mailaddr) { const char *f = strchr(priv->mailaddr, '@'); @@ -1189,12 +1174,18 @@ char buf[maxdnslength]; log(priv->queueid, "looking for %s txt record", from); dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxdnslength); - if ((level == 0) && - extraspf && - ((strlen(buf) + strlen(extraspf) + 1) < sizeof(buf))) { - strcat(buf, " "); + if ((level == 0) && extraspf && ((strlen(buf) + strlen(extraspf) + 1) < sizeof(buf))) { + if (strlen(buf) >= 7) { + // modify existing spf record + replace(buf, buf+7, 0, extraspf); + replace(buf, buf+7+strlen(extraspf), 0, " "); + } + else { + // synthesize full spf record + strcat(buf, "v=spf1 "); strcat(buf, extraspf); } + } if (*buf) { log(priv->queueid, "found txt record %s", buf); // expand some macros here - a very restricted subset of all possible spf macros @@ -1204,17 +1195,17 @@ char adr[sizeof "255.255.255.255 "]; adr[0] = '\0'; inet_ntop(AF_INET, (const u_char *)&priv->ip, adr, sizeof(adr)); - replace(buf, p, adr); + replace(buf, p, 4, adr); log(priv->queueid, "have txt record %s", buf); } p = strstr(buf, "%{h}"); if (p) { - replace(buf, p, priv->helo); + replace(buf, p, 4, priv->helo); log(priv->queueid, "have txt record %s", buf); } p = strstr(buf, "%{d}"); if (p) { - replace(buf, p, from); + replace(buf, p, 4, from); log(priv->queueid, "have txt record %s", buf); } // @@ -1375,7 +1366,7 @@ if (st == token_unsigned_black) { // enforce dmarc if (!dmarc) { - dmarc = resolve_spf(from, ntohl(priv->ip), priv, dk->signer); + dmarc = resolve_spf(from, ntohl(priv->ip), priv, dk->extraspf); } if (!dmarc) { // not signed and does not pass spf, reject it @@ -1387,7 +1378,7 @@ } if (st == token_signed_white) { // not signed by a white listed signer, but maybe passes strong spf check - if (resolve_spf(from, ntohl(priv->ip), priv, dk->signer)) { + if (resolve_spf(from, ntohl(priv->ip), priv, dk->extraspf)) { log(queueid, "spf pass for %s rather than whitelisted dkim signer", from); return token_white; } @@ -1395,7 +1386,7 @@ if (st == token_require_signed) { // not signed by a required signer, but maybe passes strong spf check // only check spf if the list of required signers is not a single dot. - if (strcmp(dk->signer, ".") && resolve_spf(from, ntohl(priv->ip), priv, dk->signer)) { + if (strcmp(dk->signer, ".") && resolve_spf(from, ntohl(priv->ip), priv, dk->extraspf)) { log(queueid, "spf pass for %s rather than required dkim signer", from); return token_white; } @@ -1499,8 +1490,13 @@ for (dkimp_map::iterator i=dkim_from_names.begin(); i!=dkim_from_names.end(); i++) { const char *n = (*i).first; DKIM &d = *(*i).second; + if (d.extraspf) { + printf("%s %s %s \"%s;%s\"; \n", indent, n, d.action, d.signer, d.extraspf); + } + else { printf("%s %s %s \"%s\"; \n", indent, n, d.action, d.signer); } + } printf("%s }; \n", indent); if (content_suffix) { printf("%s filter %s \"%s\"; \n", indent, content_suffix, content_message); @@ -1823,7 +1819,18 @@ if ((action == token_signed_white) || (action == token_signed_black) || (action == token_unsigned_black) || (action == token_require_signed)) { const char *signer = tok.next(); if (!signer) break; - else me.add_dkim_from(from, action, signer); + else { + const char *extraspf = NULL; + if (strchr(signer, ';')) { + char *x = strdup(signer); + char *e = strchr(x, ';'); + *e = '\0'; + signer = register_string(x); + extraspf = register_string(e+1); + free(x); + } + me.add_dkim_from(from, action, signer, extraspf); + } } else { tok.token_error("signed_white/signed_black/unsigned_black/require_signed", action); diff -r 95b4666a2a0b -r 428de28b34b7 src/context.h --- a/src/context.h Sat Mar 09 18:53:12 2019 -0800 +++ b/src/context.h Sun Mar 10 08:49:27 2019 -0700 @@ -142,8 +142,9 @@ struct DKIM { const char *action; const char *signer; + const char *extraspf; public: - DKIM(const char *action_, const char *signer_); + DKIM(const char *action_, const char *signer_, const char*extraspf_); }; struct DNSBL { @@ -278,8 +279,8 @@ void add_dkim_signer(const char *signer, const char *action) {dkim_signer_names[signer] = action;}; DKIMP find_dkim_from(const char *name); - void add_dkim_from(const char *from, const char *action, const char *signer) - {dkim_from_names[from] = new DKIM(action,signer);}; + void add_dkim_from(const char *from, const char *action, const char *signer, const char *extraspf) + {dkim_from_names[from] = new DKIM(action,signer,extraspf);}; void add_dnsbl(const char *name, DNSBLP dns) {dnsbl_names[name] = dns; }; void add_dnsbl(DNSBLP dns) {dnsbl_list.push_back(dns);}; @@ -325,7 +326,7 @@ void log(const char *queueid, const char *msg, const char *v); const char *extra_spf_data(const char *signers); bool in_signing_set(const char *s, const char *signers); - void replace(char *buf, char *p, const char *what); + void replace(char *buf, char *p, int nn, const char *what); bool resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, const char *extraspf); bool resolve_one_spf(const char *from, uint32_t ip, mlfiPriv *priv, const char *extraspf, int level = 0); const char *acceptable_content(bool local_source, recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, mlfiPriv *priv, string& msg);