changeset 464:428de28b34b7

cleanup code for adding extra spf data in dkim_from
author Carl Byington <carl@five-ten-sg.com>
date Sun, 10 Mar 2019 08:49:27 -0700
parents 95b4666a2a0b
children 79e944269c0b
files ChangeLog NEWS dnsbl.dkim.conf dnsbl.spec.in src/context.cpp src/context.h
diffstat 6 files changed, 86 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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;
--- 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 <carl@five-ten-sg.com> - 6.75-1
+* Sun Mar 10 2019 Carl Byington <carl@five-ten-sg.com> - 6.75-1
 - change dkim_from syntax to allow "signer1,signer2;spf data"
 
 * Mon Dec 24 2018 Carl Byington <carl@five-ten-sg.com> - 6.74-1
--- 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);
--- 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);