Merge branch 'exim-4.96+security' into master+security
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Sun, 15 Oct 2023 17:53:25 +0000 (19:53 +0200)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Sun, 15 Oct 2023 17:53:25 +0000 (19:53 +0200)
* exim-4.96+security:
  docs: Changelog
  Harden dnsdb against crafted DNS responses.  Bug 3033
  SPF: harden against crafted DNS responses
  fix: string_is_ip_address (CVE-2023-42117) Bug 3031
  Testsuite: Add testcases for string_is_ip_address (CVE-2023-42117)

1  2 
doc/doc-txt/ChangeLog
src/src/dns.c
src/src/expand.c
src/src/functions.h
src/src/lookups/dnsdb.c
src/src/string.c
test/scripts/0000-Basic/0002
test/stdout/0002

index a78ec386fc59047195869947c4a0d62d022a0bac,fb70203ed6f7e914cf500233aca4b53a80e52faa..4306cabc0c7693313451ba43bc062c0ae6599e88
@@@ -205,6 -28,10 +205,14 @@@ JH/42 Bug 3001: Fix a possible OOB rea
        be triggered by externally-controlled input.  Found by Trend Micro.
        CVE-2023-42114
  
 -JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
++JH/43 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
+       Make the rewrite never match and keep the logging.  Trust the
+       admin to be using verify=header-syntax (to actually reject the message).
++JH/44 Bug 3033: Harden dnsdb lookups against crafted DNS responses.
++      CVE-2023-42219
++
++HS/02 Fix string_is_ip_address() CVE-2023-42117 (Bug 3031)
  
  Exim version 4.96
  -----------------
diff --cc src/src/dns.c
Simple merge
Simple merge
Simple merge
index 1563eda56d0a73b2172f8a4d8cd6b22ccdb845ee,020dc9a526ad87c68049402dbc9ad70e45ae2a36..35a9464470e983a7e71de5a4e87c4a63cc45b0ae
@@@ -394,38 -399,59 +394,55 @@@ while ((domain = string_nextinlist(&key
        if (type == T_TXT || type == T_SPF)
          {
          if (!outsep2)                 /* output only the first item of data */
-           yield = string_catn(yield, US (rr->data+1), (rr->data)[0]);
+         {
+         uschar n = (rr->data)[0];
+         /* size byte + data bytes must not excced the RRs length */
+         if (n + 1 <= rr->size)
+           yield = string_catn(yield, US (rr->data+1), n);
+         }
          else
 -          {
 -          /* output all items */
 -          int data_offset = 0;
 -          while (data_offset < rr->size)
 +          for (unsigned data_offset = 0; data_offset < rr->size; )
              {
              uschar chunk_len = (rr->data)[data_offset];
+           int remain = rr->size - data_offset;
+           /* Apparently there are resolvers that do not check RRs before passing
+           them on, and glibc fails to do so.  So every application must...
+           Check for chunk len exceeding RR */
+           if (chunk_len > remain)
+             chunk_len = remain;
              if (*outsep2  && data_offset != 0)
                yield = string_catn(yield, outsep2, 1);
-             yield = string_catn(yield, US ((rr->data) + ++data_offset), chunk_len);
+             yield = string_catn(yield, US ((rr->data) + ++data_offset), --chunk_len);
              data_offset += chunk_len;
              }
 -          }
          }
        else if (type == T_TLSA)
-         {
-         uint8_t usage, selector, matching_type;
-         uint16_t payload_length;
-         uschar s[MAX_TLSA_EXPANDED_SIZE];
-       uschar * sp = s;
-         uschar * p = US rr->data;
+       if (rr->size < 3)
+         continue;
+       else
+         {
+         uint8_t usage, selector, matching_type;
+         uint16_t payload_length;
+         uschar s[MAX_TLSA_EXPANDED_SIZE];
+         uschar * sp = s;
+         uschar * p = US rr->data;
+         usage = *p++;
+         selector = *p++;
+         matching_type = *p++;
+         /* What's left after removing the first 3 bytes above */
+         payload_length = rr->size - 3;
+         sp += sprintf(CS s, "%d%c%d%c%d%c", usage, *outsep2,
+                 selector, *outsep2, matching_type, *outsep2);
+         /* Now append the cert/identifier, one hex char at a time */
+         while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4))
+           sp += sprintf(CS sp, "%02x", *p++);
  
-         usage = *p++;
-         selector = *p++;
-         matching_type = *p++;
-         /* What's left after removing the first 3 bytes above */
-         payload_length = rr->size - 3;
-         sp += sprintf(CS s, "%d%c%d%c%d%c", usage, *outsep2,
-               selector, *outsep2, matching_type, *outsep2);
-         /* Now append the cert/identifier, one hex char at a time */
-       while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4))
-           sp += sprintf(CS sp, "%02x", *p++);
-         yield = string_cat(yield, s);
-         }
+         yield = string_cat(yield, s);
+         }
        else   /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SOA, T_SRV */
          {
          int priority, weight, port;
Simple merge
Simple merge
Simple merge