[exim-cvs] Fix DKIM signing to always ;-terminate. Bug 2295

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] Fix DKIM signing to always ;-terminate. Bug 2295
Gitweb: https://git.exim.org/exim.git/commitdiff/65fe780259d0009354b5dfc9a4f1b48ad6513db2
Commit:     65fe780259d0009354b5dfc9a4f1b48ad6513db2
Parent:     5f17d2f09733cc77355841fbf095a95186cc9fe5
Author:     Guillaume Outters <guillaume-exim@???>
AuthorDate: Mon Jul 6 22:31:51 2020 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Mon Jul 6 23:28:30 2020 +0100


    Fix DKIM signing to always ;-terminate.  Bug 2295
---
 doc/doc-txt/ChangeLog |   5 +++
 src/src/pdkim/pdkim.c | 116 +++++++++++++++++++-------------------------------
 test/mail/4520.b12    |   6 +--
 test/mail/4545.a      |   6 +--
 4 files changed, 55 insertions(+), 78 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 7372ac2..8d368c8 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -81,6 +81,11 @@ JH/16 Bug 2615: Fix pause during message reception, on systems that have been
       post-message next-tick-wait.  Also change to using CLOCK_BOOTTIME if it
       exists, just to get a clock slightly more aligned to reality.


+JH/17 Bug 2295: Fix DKIM signing to always semicolon-terminate.  Although the
+      RFC says it is optional some validators care.  The missing char was not
+      intended but triggered by a line-wrap alignement.  Discovery and fix by
+      Guillaume Outters, hacked on by JH.
+


Exim version 4.94
-----------------
diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c
index 7712409..3a6ca4e 100644
--- a/src/src/pdkim/pdkim.c
+++ b/src/src/pdkim/pdkim.c
@@ -1111,14 +1111,14 @@ return string_catn(str, US"\r\n\t", 3);

 /*
  * RFC 5322 specifies that header line length SHOULD be no more than 78
- * lets make it so!
  *  pdkim_headcat
  *
- * returns uschar * (not nul-terminated)
+ * Returns gstring (not nul-terminated) appending to one supplied
  *
  * col: this int holds and receives column number (octets since last '\n')
  * str: partial string to append to
- * pad: padding, split line or space after before or after eg: ";"
+ * pad: padding, split line or space after before or after eg: ";".
+ *               Only the initial charater is used.
  * intro: - must join to payload eg "h=", usually the tag name
  * payload: eg base64 data - long data can be split arbitrarily.
  *
@@ -1127,7 +1127,7 @@ return string_catn(str, US"\r\n\t", 3);
  * pairs and inside long values. it also always spaces or breaks after the
  * "pad"
  *
- * no guarantees are made for output given out-of range input. like tag
+ * No guarantees are made for output given out-of range input. like tag
  * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
  */


@@ -1135,92 +1135,64 @@ static gstring *
pdkim_headcat(int * col, gstring * str,
const uschar * pad, const uschar * intro, const uschar * payload)
{
-size_t l;
+int len, chomp, padded = 0;

-if (pad)
-  {
-  l = Ustrlen(pad);
-  if (*col + l > 78)
-    str = pdkim_hdr_cont(str, col);
-  str = string_catn(str, pad, l);
-  *col += l;
-  }
-
-l = (pad?1:0) + (intro?Ustrlen(intro):0);
+/* If we can fit at least the pad at the end of current line, do it now.
+Otherwise, wrap if there is a pad. */


-if (*col + l > 78)
-  { /*can't fit intro - start a new line to make room.*/
-  str = pdkim_hdr_cont(str, col);
-  l = intro?Ustrlen(intro):0;
-  }
-
-l += payload ? Ustrlen(payload):0 ;
-
-while (l>77)
-  { /* this fragment will not fit on a single line */
-  if (pad)
-    {
-    str = string_catn(str, US" ", 1);
-    *col += 1;
-    pad = NULL; /* only want this once */
-    l--;
-    }
-
-  if (intro)
-    {
-    size_t sl = Ustrlen(intro);
-
-    str = string_catn(str, intro, sl);
-    *col += sl;
-    l -= sl;
-    intro = NULL; /* only want this once */
-    }
-
-  if (payload)
+if (pad)
+  if (*col + 1 <= 78)
     {
-    size_t sl = Ustrlen(payload);
-    size_t chomp = *col+sl < 77 ? sl : 78-*col;
-
-    str = string_catn(str, payload, chomp);
-    *col += chomp;
-    payload += chomp;
-    l -= chomp-1;
+    str = string_catn(str, pad, 1);
+    (*col)++;
+    pad = NULL;
+    padded = 1;
     }
+  else
+    str = pdkim_hdr_cont(str, col);


- /* the while precondition tells us it didn't fit. */
- str = pdkim_hdr_cont(str, col);
- }
+/* Special case: if the whole addition does not fit at the end of the current
+line, but could fit on a new line, wrap to give it its full, dedicated line. */

-if (*col + l > 78)
+len = (pad ? 2 : padded)
+    + (intro ? Ustrlen(intro) : 0)
+    + (payload ? Ustrlen(payload) : 0);
+if (len <= 77 && *col+len > 78)
   {
   str = pdkim_hdr_cont(str, col);
-  pad = NULL;
+  padded = 0;
   }


+/* Either we already dealt with the pad or we know there is room */
+
if (pad)
{
+ str = string_catn(str, pad, 1);
str = string_catn(str, US" ", 1);
- *col += 1;
- pad = NULL;
+ *col += 2;
}
-
-if (intro)
+else if (padded && *col < 78)
{
- size_t sl = Ustrlen(intro);
-
- str = string_catn(str, intro, sl);
- *col += sl;
- l -= sl;
- intro = NULL;
+ str = string_catn(str, US" ", 1);
+ (*col)++;
}

-if (payload)
- {
- size_t sl = Ustrlen(payload);
+/* Call recursively with intro as payload: it gets the same, special treatment
+(that is, not split if < 78). */

-  str = string_catn(str, payload, sl);
-  *col += sl;
-  }
+if (intro)
+  str = pdkim_headcat(col, str, NULL, NULL, intro);
+
+if (payload)
+  for (len = Ustrlen(payload); len; len -= chomp)
+    {
+    if (*col >= 78)
+      str = pdkim_hdr_cont(str, col);
+    chomp = *col+len > 78 ? 78 - *col : len;
+    str = string_catn(str, payload, chomp);
+    *col += chomp;
+    payload += chomp;
+    }


 return str;
 }
diff --git a/test/mail/4520.b12 b/test/mail/4520.b12
index e327a0d..392cee3 100644
--- a/test/mail/4520.b12
+++ b/test/mail/4520.b12
@@ -6,9 +6,9 @@ Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
     for b12@???; Tue, 2 Mar 1999 09:44:33 +0000
 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex;
     s=sel; h=X-mine:X-mine:From; bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=;
-     b=VSF3Fmf7fHLpqKWgaG0t/RJdd+7JJNRN/+q7Gcz0xtIOjt5tL4Pfc4VDSeQYPq6e1pCcjvj79k
-    57of1wr0KIfk5FAvUZXPu3OtRm71y1X2rUaQB8c2Y2SROSMyaT3tsPzaEigiptIeeOkULYkFl2Hln
-    15ssCcfufIlOx4EQ9fQA=;
+    b=VSF3Fmf7fHLpqKWgaG0t/RJdd+7JJNRN/+q7Gcz0xtIOjt5tL4Pfc4VDSeQYPq6e1pCcjvj79k5
+    7of1wr0KIfk5FAvUZXPu3OtRm71y1X2rUaQB8c2Y2SROSMyaT3tsPzaEigiptIeeOkULYkFl2Hln1
+    5ssCcfufIlOx4EQ9fQA=;
 Received: from CALLER by myhost.test.ex with local (Exim x.yz)
     (envelope-from <CALLER@???>)
     id 10HmbE-0005vi-00
diff --git a/test/mail/4545.a b/test/mail/4545.a
index b4a931f..18752a7 100644
--- a/test/mail/4545.a
+++ b/test/mail/4545.a
@@ -5,9 +5,9 @@ Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
     id 10HmaY-0005vi-00
     for a@???; Tue, 2 Mar 1999 09:44:33 +0000
 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex
-    ; s=sed; h=From:To:Subject; bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=;
-     b=5fhyD3EILDrnL4DnkD4hDaeis7+GSzL9GMHrhIDZJjuJ00WD5iI8SQ1q9rDfzFL/Kdw0VIyB4R
-    Dq0a4H6HI+Bw==;
+    ; s=sed; h=From:To:Subject; bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=; 
+    b=5fhyD3EILDrnL4DnkD4hDaeis7+GSzL9GMHrhIDZJjuJ00WD5iI8SQ1q9rDfzFL/Kdw0VIyB4RD
+    q0a4H6HI+Bw==;
 Received: from CALLER by myhost.test.ex with local (Exim x.yz)
     (envelope-from <CALLER@???>)
     id 10HmaX-0005vi-00