DKIM: better syntax for control of oversigning. Bug 2180
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 3 Nov 2017 11:02:19 +0000 (11:02 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Fri, 3 Nov 2017 12:10:32 +0000 (12:10 +0000)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/pdkim/pdkim.c
test/log/4520
test/scripts/4500-DKIM/4520
test/stderr/4520

index 13fcad7244359f9ac7be40b59b0d87be08527688..a0eb53c58e3d12c662a6a11cdc9446aae78d96f5 100644 (file)
@@ -38608,6 +38608,17 @@ When unspecified, the header names listed in RFC4871 will be used,
 whether or not each header is present in the message.
 The default list is available for the expansion in the macro
 "_DKIM_SIGN_HEADERS".
+
+If a name is repeated, multiple headers by that name (or the absence therof)
+will be signed.  The textually later headers in the headers part of the
+message are signed first, if there are multiples.
+
+A name can be prefixed with either an '=' or a '+' character.
+If an '=' prefix is used, all headers that are present with this name
+will be signed.
+If a '+' prefix if used, all headers that are present with this name
+will be signed, and one signtature added for a missing header with the
+name will be appended.
 .wen
 
 
index 22af13554e3f75f98e766c564c1f768bd62a8894..e77095c8df2a03f43f90e36c736962c03a21d944 100644 (file)
@@ -54,6 +54,7 @@ Version 4.90
 13. DKIM support for multiple signing, by domain and/or key-selector.
     DKIM support for multiple hashes, and for alternate-identity tags.
     Builtin macro with default list of signed headers.
+    Better syntax for specifying oversigning.
 
 14. Exipick understands -C|--config for an alternative Exim
     configuration file.
index 1420b1a795d32944f624bfecd2277f0a24033bc1..1388618151ad2d5eca653a0827de1d9994c7c0fd 100644 (file)
@@ -250,16 +250,19 @@ pdkim_free_ctx(pdkim_ctx *ctx)
 /* -------------------------------------------------------------------------- */
 /* Matches the name of the passed raw "header" against
    the passed colon-separated "tick", and invalidates
-   the entry in tick. Returns OK or fail-code */
-/*XXX might be safer done using a pdkim_stringlist for "tick" */
+   the entry in tick.  Entries can be prefixed for multi- or over-signing,
+   in which case do not invalidate.
+
+   Returns OK for a match, or fail-code
+*/
 
 static int
 header_name_match(const uschar * header, uschar * tick)
 {
-uschar * hname;
-uschar * lcopy;
-uschar * p;
-uschar * q;
+const uschar * ticklist = tick;
+int sep = ':';
+BOOL multisign;
+uschar * hname, * p, * ele;
 uschar * hcolon = Ustrchr(header, ':');                /* Get header name */
 
 if (!hcolon)
@@ -268,27 +271,22 @@ if (!hcolon)
 /* if we had strncmpic() we wouldn't need this copy */
 hname = string_copyn(header, hcolon-header);
 
-/* Copy tick-off list locally, so we can punch zeroes into it */
-p = lcopy = string_copy(tick);
-
-for (q = Ustrchr(p, ':'); q; q = Ustrchr(p, ':'))
+while (p = US ticklist, ele = string_nextinlist(&ticklist, &sep, NULL, 0))
   {
-  *q = '\0';
-  if (strcmpic(p, hname) == 0)
-    goto found;
-
-  p = q+1;
+  switch (*ele)
+  {
+  case '=': case '+':  multisign = TRUE; ele++; break;
+  default:             multisign = FALSE; break;
   }
 
-if (strcmpic(p, hname) == 0)
-  goto found;
-
+  if (strcmpic(ele, hname) == 0)
+    {
+    if (!multisign)
+      *p = '_';        /* Invalidate this header name instance in tick-off list */
+    return PDKIM_OK;
+    }
+  }
 return PDKIM_FAIL;
-
-found:
-  /* Invalidate header name instance in tick-off list */
-  tick[p-lcopy] = '_';
-  return PDKIM_OK;
 }
 
 
@@ -1445,11 +1443,17 @@ for (sig = ctx->sig; sig; sig = sig->next)
        }
       }
 
-    /* Any headers we wanted to sign but were not present must also be listed */
+    /* Any headers we wanted to sign but were not present must also be listed.
+    Ignore elements that have been ticked-off or are marked as never-oversign. */
+
     l = sig->sign_headers;
     while((s = string_nextinlist(&l, &sep, NULL, 0)))
-      if (*s != '_')
+      {
+      if (*s == '+')                   /* skip oversigning marker */
+        s++;
+      if (*s != '_' && *s != '=')
        g = string_append_listele(g, ':', s);
+      }
     sig->headernames = string_from_gstring(g);
 
     /* Create signature header with b= omitted */
index b0ddcd64e551d5a50a7d141c8c9f1a7870f94125..7bee5d786a71f931a8df4da62c9e1cabbb61aaea 100644 (file)
@@ -5,11 +5,23 @@
 1999-03-02 09:44:33 10HmaZ-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbA-0005vi-00"
 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00"
+1999-03-02 09:44:33 10HmbB-0005vi-00 => b10@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00"
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbD-0005vi-00 => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 => b12@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbF-0005vi-00 => b20@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbG-0005vi-00"
+1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbH-0005vi-00 => b22@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbI-0005vi-00"
+1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbJ-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbK-0005vi-00"
+1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbL-0005vi-00 => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbM-0005vi-00"
+1999-03-02 09:44:33 10HmbL-0005vi-00 Completed
 
 ******** SERVER ********
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <b@test.ex> R=server_dump
 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
 1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
-1999-03-02 09:44:33 10HmbC-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 i=allheaders@test.ex [verification succeeded]
-1999-03-02 09:44:33 10HmbC-0005vi-00 signer: test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
-1999-03-02 09:44:33 10HmbC-0005vi-00 signer: allheaders@test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbC-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmbC-0005vi-00 signer: test.ex bits: 1024 h=From
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbB-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <c@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <b10@test.ex> R=server_dump
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
-1999-03-02 09:44:33 10HmbE-0005vi-00 DKIM: d=test.ex s=sel_bad c=relaxed/relaxed a=rsa-sha256 b=1024 [invalid - syntax error in public key record]
-1999-03-02 09:44:33 10HmbE-0005vi-00 signer: test.ex bits: 1024 h=From
+1999-03-02 09:44:33 10HmbE-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmbE-0005vi-00 signer: test.ex bits: 1024 h=X-mine:X-mine:From
 1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbD-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <d@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <b12@test.ex> R=server_dump
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbG-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmbG-0005vi-00 signer: test.ex bits: 1024 h=X-Mine
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbF-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 => :blackhole: <b20@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbI-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmbI-0005vi-00 signer: test.ex bits: 1024 h=X-mine:X-mine:X-Mine
+1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbH-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbI-0005vi-00 => :blackhole: <b22@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
+1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbK-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 i=allheaders@test.ex [verification succeeded]
+1999-03-02 09:44:33 10HmbK-0005vi-00 signer: test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbK-0005vi-00 signer: allheaders@test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbJ-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbK-0005vi-00 => :blackhole: <c@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbK-0005vi-00 Completed
+1999-03-02 09:44:33 macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbM-0005vi-00 DKIM: d=test.ex s=sel_bad c=relaxed/relaxed a=rsa-sha256 b=1024 [invalid - syntax error in public key record]
+1999-03-02 09:44:33 10HmbM-0005vi-00 signer: test.ex bits: 1024 h=From
+1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbL-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbM-0005vi-00 => :blackhole: <d@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
index 3e58799729613ce5db6d1dadd03f619cb068d152..1bc4c603038ffbf25d16965a3426c485f7675704 100644 (file)
@@ -15,6 +15,39 @@ content
 exim -DOPT=From:From -odf b@test.ex
 From: nobody@example.com
 
+content
+****
+#
+# no header, multi-sign
+exim -DOPT=From:=X-Mine -odf b10@test.ex
+From: nobody@example.com
+
+content
+****
+#
+# double header, multi-sign
+exim -DOPT=From:=X-Mine -odf b12@test.ex
+From: nobody@example.com
+X-mine: one
+X-mine: two
+
+content
+****
+#
+#
+# no header, always-oversign
+exim -DOPT=+X-Mine -odf b20@test.ex
+From: nobody@example.com
+
+content
+****
+#
+# double header, always-oversign
+exim -DOPT=+X-Mine -odf b22@test.ex
+From: nobody@example.com
+X-mine: one
+X-mine: two
+
 content
 ****
 #
index 3d7957c032a24c1e0a0e150d43aba3218273c970..499716fc189946612e8137105927b9d4a3278f78 100644 (file)
@@ -45,12 +45,12 @@ DKIM-Signature:{SP}v=1;{SP}a=rsa-sha256;{SP}q=dns/txt;{SP}c=relaxed/relaxed;{SP}
 PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>
 dkim-signature:v=1;{SP}a=rsa-sha256;{SP}q=dns/txt;{SP}c=relaxed/relaxed;{SP}d=test.ex;{SP}s=sel_bad;{SP}h=From;{SP}bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=;{SP}b=;
 PDKIM [test.ex] Header sha256 computed: 241e16230df5723d899cfae9474c6b376a2ab1f81d1094e358f50ffd0e0067b3
-  SMTP<< 250 OK id=10HmbE-0005vi-00
+  SMTP<< 250 OK id=10HmbM-0005vi-00
   SMTP>> QUIT
 cmd buf flush ddd bytes
   SMTP(close)>>
 LOG: MAIN
-  => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
+  => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbM-0005vi-00"
 LOG: MAIN
   Completed
 >>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>