DKIM DNS TXT record bug fix. Fixes: #967
authorNigel Metheringham <nigel@exim.org>
Sat, 29 May 2010 19:23:25 +0000 (19:23 +0000)
committerNigel Metheringham <nigel@exim.org>
Sat, 29 May 2010 19:23:25 +0000 (19:23 +0000)
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/lookups/dnsdb.c

index 6a1d7ce12f5c1ce51b418a626e9b9fbaf40f8f9e..5385d8ead1aec1a2bd99515322940a5a0a08b292 100644 (file)
@@ -1,4 +1,4 @@
-. $Cambridge: exim/doc/doc-docbook/spec.xfpt,v 1.72 2010/03/05 16:26:46 nm4 Exp $
+. $Cambridge: exim/doc/doc-docbook/spec.xfpt,v 1.73 2010/05/29 19:23:25 nm4 Exp $
 .
 . /////////////////////////////////////////////////////////////////////////////
 . This is the primary source of the Exim Manual. It is an xfpt document that is
 .
 . /////////////////////////////////////////////////////////////////////////////
 . This is the primary source of the Exim Manual. It is an xfpt document that is
@@ -6628,6 +6628,20 @@ ${lookup dnsdb{>: a=host1.example}}
 It is permitted to specify a space as the separator character. Further
 white space is ignored.
 
 It is permitted to specify a space as the separator character. Further
 white space is ignored.
 
+.new
+.cindex "TXT record" "in &(dnsdb)& lookup"
+For TXT records with multiple items of data, only the first item is returned,
+unless a separator for them is specified using a comma after the separator
+character followed immediately by the TXT record item separator. To concatenate
+items without a separator, use a semicolon instead.
+.code
+${lookup dnsdb{>\n,: txt=a.b.example}}
+${lookup dnsdb{>\n; txt=a.b.example}}
+.endd
+It is permitted to specify a space as the separator character. Further
+white space is ignored.
+.wen
+
 .section "Pseudo dnsdb record types" "SECID66"
 .cindex "MX record" "in &(dnsdb)& lookup"
 By default, both the preference value and the host name are returned for
 .section "Pseudo dnsdb record types" "SECID66"
 .cindex "MX record" "in &(dnsdb)& lookup"
 By default, both the preference value and the host name are returned for
index a2434129c19b894c1f813dc09909418dc28d529d..372be8fdf3ca683c89d47aa1b46e43af79ea0189 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.610 2010/05/29 19:16:50 nm4 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.611 2010/05/29 19:23:26 nm4 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -39,6 +39,9 @@ MH/01 Treat the transport option dkim_domain as a colon separated
 NM/07 Null terminate DKIM strings, Null initialise DKIM variable
       Bugzilla 985, 986.  Patch by Simon Arlott
 
 NM/07 Null terminate DKIM strings, Null initialise DKIM variable
       Bugzilla 985, 986.  Patch by Simon Arlott
 
+NM/08 Bugzilla 967. DKIM DNS TXT record bug fix
+      Patch by Simon Arlott
+
 
 Exim version 4.71
 -----------------
 
 Exim version 4.71
 -----------------
index 5e9741beaca053e29207858aff1d078ce43ea5c0..89ad67d286bb39232568c89921fe0d9d021b7aa6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.19 2009/11/16 19:50:38 nm4 Exp $ */
+/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.20 2010/05/29 19:23:26 nm4 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -88,17 +88,23 @@ consist of a number of parts.
 separator character that is used when multiple records are found. The default
 separator is newline.
 
 separator character that is used when multiple records are found. The default
 separator is newline.
 
-(b) If the next sequence of characters is 'defer_FOO' followed by a comma,
+(b) If the next character is ',' then the next character is the separator
+character used for multiple items of text in "TXT" records. Alternatively,
+if the next character is ';' then these multiple items are concatenated with
+no separator. With neither of these options specified, only the first item
+is output.
+
+(c) If the next sequence of characters is 'defer_FOO' followed by a comma,
 the defer behaviour is set to FOO. The possible behaviours are: 'strict', where
 any defer causes the whole lookup to defer; 'lax', where a defer causes the
 whole lookup to defer only if none of the DNS queries succeeds; and 'never',
 where all defers are as if the lookup failed. The default is 'lax'.
 
 the defer behaviour is set to FOO. The possible behaviours are: 'strict', where
 any defer causes the whole lookup to defer; 'lax', where a defer causes the
 whole lookup to defer only if none of the DNS queries succeeds; and 'never',
 where all defers are as if the lookup failed. The default is 'lax'.
 
-(c) If the next sequence of characters is a sequence of letters and digits
+(d) If the next sequence of characters is a sequence of letters and digits
 followed by '=', it is interpreted as the name of the DNS record type. The
 default is "TXT".
 
 followed by '=', it is interpreted as the name of the DNS record type. The
 default is "TXT".
 
-(d) Then there follows list of domain names. This is a generalized Exim list,
+(e) Then there follows list of domain names. This is a generalized Exim list,
 which may start with '<' in order to set a specific separator. The default
 separator, as always, is colon. */
 
 which may start with '<' in order to set a specific separator. The default
 separator, as always, is colon. */
 
@@ -114,6 +120,7 @@ int defer_mode = PASS;
 int type = T_TXT;
 int failrc = FAIL;
 uschar *outsep = US"\n";
 int type = T_TXT;
 int failrc = FAIL;
 uschar *outsep = US"\n";
+uschar *outsep2 = NULL;
 uschar *equals, *domain, *found;
 uschar buffer[256];
 
 uschar *equals, *domain, *found;
 uschar buffer[256];
 
@@ -131,13 +138,24 @@ filename = filename;
 length = length;
 do_cache = do_cache;
 
 length = length;
 do_cache = do_cache;
 
-/* If the string starts with '>' we change the output separator */
+/* If the string starts with '>' we change the output separator.
+If it's followed by ';' or ',' we set the TXT output separator. */
 
 while (isspace(*keystring)) keystring++;
 if (*keystring == '>')
   {
   outsep = keystring + 1;
   keystring += 2;
 
 while (isspace(*keystring)) keystring++;
 if (*keystring == '>')
   {
   outsep = keystring + 1;
   keystring += 2;
+  if (*keystring == ',')
+    {
+    outsep2 = keystring + 1;
+    keystring += 2;
+    }
+  else if (*keystring == ';')
+    {
+    outsep2 = US"";
+    keystring++;
+    }
   while (isspace(*keystring)) keystring++;
   }
 
   while (isspace(*keystring)) keystring++;
   }
 
@@ -303,13 +321,25 @@ while ((domain = string_nextinlist(&keystring, &sep, buffer, sizeof(buffer)))
 
     if (type == T_TXT)
       {
 
     if (type == T_TXT)
       {
-      int data_offset = 0;
-      while (data_offset < rr->size)
+      if (outsep2 == NULL)
         {
         {
-        uschar chunk_len = (rr->data)[data_offset++];
-        yield = string_cat(yield, &size, &ptr,
-                           (uschar *)((rr->data)+data_offset), chunk_len);
-        data_offset += chunk_len;
+        /* output only the first item of data */
+        yield = string_cat(yield, &size, &ptr, (uschar *)(rr->data+1),
+          (rr->data)[0]);
+        }
+      else
+        {
+        /* output all items */
+        int data_offset = 0;
+        while (data_offset < rr->size)
+          {
+          uschar chunk_len = (rr->data)[data_offset++];
+          if (outsep2[0] != '\0' && data_offset != 1)
+            yield = string_cat(yield, &size, &ptr, outsep2, 1);
+          yield = string_cat(yield, &size, &ptr,
+                             (uschar *)((rr->data)+data_offset), chunk_len);
+          data_offset += chunk_len;
+          }
         }
       }
     else   /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SRV */
         }
       }
     else   /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SRV */