]> git.pld-linux.org Git - packages/exim.git/blobdiff - unofficial-hotfix.patch
Rel 25; unofficial hotfix for some of recent SECURITY issues (timelime for official...
[packages/exim.git] / unofficial-hotfix.patch
diff --git a/unofficial-hotfix.patch b/unofficial-hotfix.patch
new file mode 100644 (file)
index 0000000..c7cc282
--- /dev/null
@@ -0,0 +1,151 @@
+Date: Sun, 1 Oct 2023 11:33:26 +0200\r
+To: exim-dev@lists.exim.org\r
+From: Florian Zumbiehl via Exim-dev <exim-dev@lists.exim.org>\r
+\r
+Hi,\r
+\r
+below you find a patch that fixes some (probably three?) of what I guess are\r
+the vulnerabilities reported by ZDI.\r
+\r
+Please note that the patch is only mildly tested, it is developed based on\r
+the git master branch, but can be applied to older versions with minor\r
+massaging. If you go back far enough, proxy.c was part of smtp_in.c, but if\r
+you adjust for that, the patch can be made to apply there, too.\r
+\r
+Obviously, I have no idea whether this actually addresses what ZDI has\r
+reported, but if not, these probably should be fixed, too, and if so, given\r
+the fact that I managed to rather easily find these vulnerabilities based\r
+on the information that's publicly available, I don't think there is much\r
+point to trying to keep this secret any longer--if anything, it's\r
+counterproductive.\r
+\r
+Also mind you that this is a hot fix, it's neither elegant, nor does it do\r
+any useful error reporting, the goal was simply to prevent out of bounds\r
+accesses.\r
+\r
+Florian\r
+\r
+---\r
+\r
+diff --git a/src/src/auths/external.c b/src/src/auths/external.c\r
+index 078aad0..54966e6 100644\r
+--- a/src/src/auths/external.c\r
++++ b/src/src/auths/external.c\r
+@@ -101,6 +101,9 @@ if (expand_nmax == 0)      /* skip if rxd data */\r
+   if ((rc = auth_prompt(CUS"")) != OK)\r
+     return rc;\r
\r
++if (expand_nmax != 1)\r
++  return FAIL;\r
++\r
+ if (ob->server_param2)\r
+   {\r
+   uschar * s = expand_string(ob->server_param2);\r
+diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c\r
+index 222ccea..66967d6 100644\r
+--- a/src/src/auths/spa.c\r
++++ b/src/src/auths/spa.c\r
+@@ -166,12 +166,18 @@ if (auth_get_no64_data(&data, msgbuf) != OK)\r
+   return FAIL;\r
\r
+ /* dump client response */\r
+-if (spa_base64_to_bits(CS &response, sizeof(response), CCS data) < 0)\r
++int l = spa_base64_to_bits(CS &response, sizeof(response), CCS data);\r
++if (l < 0)\r
+   {\r
+   DEBUG(D_auth) debug_printf("auth_spa_server(): bad base64 data in "\r
+     "response: %s\n", data);\r
+   return FAIL;\r
+   }\r
++if(l < (char *)&response.buffer - (char *)&response)return FAIL;\r
++unsigned long o = IVAL(&response.uUser.offset, 0);\r
++if((l < o) || (l - o < SVAL(&response.uUser.len, 0)))return FAIL;\r
++o = IVAL(&response.ntResponse.offset, 0);\r
++if((l < o) || (l - o < 24))return FAIL;\r
\r
+ /***************************************************************\r
+ PH 07-Aug-2003: The original code here was this:\r
+@@ -346,7 +352,10 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout))\r
\r
+ /* convert the challenge into the challenge struct */\r
+ DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4);\r
+-spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4));\r
++int l = spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4));\r
++if((l < 0) || (l < (char *)&challenge.buffer - (char *)&challenge))return FAIL;\r
++unsigned long o = IVAL(&challenge.uDomain.offset, 0);\r
++if((l < o) || (l - o < SVAL(&challenge.uDomain.len, 0)))return FAIL;\r
\r
+ spa_build_auth_response(&challenge, &response, CS username, CS password);\r
+ spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response));\r
+diff --git a/src/src/proxy.c b/src/src/proxy.c\r
+index fbce111..8dd7034 100644\r
+--- a/src/src/proxy.c\r
++++ b/src/src/proxy.c\r
+@@ -93,6 +93,8 @@ while (capacity > 0)\r
+   do { ret = read(fd, to, 1); } while (ret == -1 && errno == EINTR && !had_command_timeout);\r
+   if (ret == -1)\r
+     return -1;\r
++  if (!ret)\r
++    break;\r
+   have++;\r
+   if (last)\r
+     return have;\r
+@@ -254,6 +256,8 @@ if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0))\r
+     goto proxyfail;\r
+     }\r
\r
++  if (ret < 16)\r
++    goto proxyfail;\r
+   /* The v2 header will always be 16 bytes per the spec. */\r
+   size = 16 + ntohs(hdr.v2.len);\r
+   DEBUG(D_receive) debug_printf("Detected PROXYv2 header, size %d (limit %d)\n",\r
+@@ -274,7 +278,7 @@ if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0))\r
+       {\r
+       retmore = read(fd, (uschar*)&hdr + ret, size-ret);\r
+       } while (retmore == -1 && errno == EINTR && !had_command_timeout);\r
+-    if (retmore == -1)\r
++    if (retmore < 1)\r
+       goto proxyfail;\r
+     DEBUG(D_receive) proxy_debug(US &hdr, ret, ret + retmore);\r
+     ret += retmore;\r
+@@ -297,6 +301,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig, 12) == 0)\r
+       switch (hdr.v2.fam)\r
+         {\r
+         case 0x11:  /* TCPv4 address type */\r
++        if (ret < 28)\r
++            goto proxyfail;\r
+           iptype = US"IPv4";\r
+           tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;\r
+           inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));\r
+@@ -323,6 +329,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig, 12) == 0)\r
+           proxy_external_port  = tmpport;\r
+           goto done;\r
+         case 0x21:  /* TCPv6 address type */\r
++        if (ret < 52)\r
++            goto proxyfail;\r
+           iptype = US"IPv6";\r
+           memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);\r
+           inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));\r
+@@ -381,10 +389,13 @@ else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0)\r
+     goto proxyfail;\r
+   ret += r2;\r
\r
++  if(ret > 107)\r
++    goto proxyfail;\r
++  hdr.v1.line[ret] = 0;\r
+   p = string_copy(hdr.v1.line);\r
+   end = memchr(p, '\r', ret - 1);\r
\r
+-  if (!end || (end == (uschar*)&hdr + ret) || end[1] != '\n')\r
++  if (!end || end[1] != '\n')\r
+     {\r
+     DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n");\r
+     goto proxyfail;\r
+\r
+-- \r
+## subscription configuration (requires account):\r
+##   https://lists.exim.org/mailman3/postorius/lists/exim-dev.lists.exim.org/\r
+## unsubscribe (doesn't require an account):\r
+##   exim-dev-unsubscribe@lists.exim.org\r
+## Exim details at http://www.exim.org/\r
+## Please use the Wiki with this list - http://wiki.exim.org/\r
This page took 0.084202 seconds and 4 git commands to generate.