summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* Avoid using CLOCK_MONOTONIC for $received_time. Bug 2615exim-4.94.2+fixesJeremy Harris2021-09-021-4/+11
| | | | (cherry picked from commit 8dcd5efb1f89d17b0b214e1face4146d3a1edd28)
* DKIM: fix verify under TLS & chunking, with pipelined next commandJeremy Harris2021-08-118-9/+23
| | | | Cherry-picked from: b367453a08
* Testsuite: testcases for DKIM under TLSJeremy Harris2021-08-1169-1/+9262
| | | | (cherry picked from commit 15a44d749b2f4097d43c2d887b6c5bca2d0d8b4a)
* Testsuite: testcase shufflingJeremy Harris2021-08-1148-6/+178
| | | | (cherry picked from commit 5078e5337323159ff8c293e7ae335a974fd0371e)
* Fix tainted message for fakerejectJeremy Harris2021-07-102-1/+7
| | | | (cherry picked from commit a9ac2d7fc219e41a353abf1f599258b9b9d21b7e)
* Fix host_name_lookup (Close 2747)Heiko Schlittermann (HS12-RIPE)2021-05-161-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Thanks to Nico R for providing a reproducing configuration. host_lookup = * message_size_limit = ${if def:sender_host_name {32M}{32M}} acl_smtp_connect = acl_smtp_connect acl_smtp_rcpt = acl_smtp_rcpt begin acl acl_smtp_connect: warn ratelimit = 256 / 1m / per_conn accept acl_smtp_rcpt: accept hosts = 127.0.0.* begin routers null: driver = accept transport = null begin transports null: driver = appendfile file = /dev/null Tested with swaks -f mailbox@example.org -t mailbox@example.org --pipe 'exim -bh 127.0.0.1 -C /opt/exim/etc/exim-bug.conf' The IP must have a PTR to "localhost." to reproduce it.
* Merge branch 'exim-4.94+fixes' into exim-4.94.2+fixesHeiko Schlittermann (HS12-RIPE)2021-05-135-2/+21
|\ | | | | | | | | How to make sure that cherry-picking to a +fixes branch goes to the *latest* +fixes branch?
| * Named Queues: fix immediate-delivery. Bug 2743Jeremy Harris2021-05-125-2/+21
| | | | | | | | (cherry picked from commit 159cf206c97f876b07829d92db2217689745c1e8)
* | Merge branch 'exim-4.94+fixes' into exim-4.94.2+fixesHeiko Schlittermann (HS12-RIPE)2021-05-094-4/+7
|\ \ | |/
| * Merge branch 'exim-4.94+fixes' of ssh://git.exim.org/home/git/exim into ↵Heiko Schlittermann (HS12-RIPE)2021-05-094-4/+7
| |\ | | | | | | | | | exim-4.94+fixes
| | * Fix ${ipv6norm:}Jeremy Harris2021-05-044-4/+7
| | | | | | | | | | | | (cherry picked from commit 8b4b6ac90766b11fa74fa3001778b49456adbe42)
* | | Fix DANE + SNI handling (Bug 2265)Heiko Schlittermann (HS12-RIPE)2021-05-031-2/+2
| | | | | | | | | | | | | | | Broken in d8e99d6047e709b35eabb1395c2046100d1a1dda Thanks to JGH and Wolfgang Breyha for contributions.
* | | Fix BDAT issue for body w/o trailing CRLF (again Bug 1974)exim-4.94.2Heiko Schlittermann (HS12-RIPE)2021-04-301-2/+3
| | |
* | | testsuite: reproduce BDAT with missing eol (Bug 1974)Heiko Schlittermann (HS12-RIPE)2021-04-303-10/+73
|/ /
* | Cleanup docs on cve-2020-qualys, point to the Exim websiteexim-4.94.1Heiko Schlittermann (HS12-RIPE)2021-04-281-0/+2
| |
* | rewrite: revert to unchecked result of parse_extract_address()Heiko Schlittermann (HS12-RIPE)2021-04-281-1/+17
| | | | | | | | | | Now it breaks 471, and overlong addresses won't make it into the rewrite process, as they are handled as empty.
* | Honour the outcome of parse_extract_address(), testsuite 471Heiko Schlittermann (HS12-RIPE)2021-04-286-16/+111
| |
* | CVE-2020-28023: Out-of-bounds read in smtp_setup_msg()Qualys Security Advisory2021-04-283-3/+5
| | | | | | | | Extracted from Jeremy Harris's commit afaf5a50.
* | Remove merge artifactHeiko Schlittermann (HS12-RIPE)2021-04-281-1/+0
| |
* | Update upgrade notes and source about use of seteuid()Heiko Schlittermann (HS12-RIPE)2021-04-282-10/+14
| | | | | | | | (cherry picked from commit bc13bbca6e07267dfe0c4d275bb0a2e9aabf1dfb)
* | CVE-2020-28007: Link attack in Exim's log directoryQualys Security Advisory2021-04-285-182/+234
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We patch this vulnerability by opening (instead of just creating) the log file in an unprivileged (exim) child process, and by passing this file descriptor back to the privileged (root) parent process. The two functions log_send_fd() and log_recv_fd() are inspired by OpenSSH's functions mm_send_fd() and mm_receive_fd(); thanks! This patch also fixes: - a NULL-pointer dereference in usr1_handler() (this signal handler is installed before process_log_path is initialized); - a file-descriptor leak in dmarc_write_history_file() (two return paths did not close history_file_fd). Note: the use of log_open_as_exim() in dmarc_write_history_file() should be fine because the documentation explicitly states "Make sure the directory of this file is writable by the user exim runs as." (cherry picked from commit 2502cc41d1d92c1413eca6a4ba035c21162662bd)
* | CVE-2020-28016: Heap out-of-bounds write in parse_fix_phrase()Heiko Schlittermann (HS12-RIPE)2021-04-281-3/+3
| | | | | | | | | | | | | | Based on Phil Pennock's commit 76a1ce77. Modified by Qualys. (cherry picked from commit f218fef171cbe9e61d10f15399aab8fa6956535b)
* | SECURITY: Avoid modification of constant data in dkim handlingHeiko Schlittermann (HS12-RIPE)2021-04-281-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Based on Heiko Schlittermann's commits f880c7f3 and c118c7f4. This fixes: 6/ In src/pdkim/pdkim.c, pdkim_update_ctx_bodyhash() is sometimes called with a global orig_data and hence canon_data, and the following line can therefore modify data that should be constant: 773 canon_data->len = b->bodylength - b->signed_body_bytes; For example, the following proof of concept sets lineending.len to 0 (this should not be possible): (sleep 10; echo 'EHLO test'; sleep 3; echo 'MAIL FROM:<>'; sleep 3; echo 'RCPT TO:postmaster'; sleep 3; echo 'DATA'; date >&2; sleep 30; printf 'DKIM-Signature:a=rsa-sha1;c=simple/simple;l=0\r\n\r\n\r\nXXX\r\n.\r\n'; sleep 30) | nc -n -v 192.168.56.102 25 (gdb) print lineending $1 = {data = 0x55e18035b2ad "\r\n", len = 2} (gdb) print &lineending.len $3 = (size_t *) 0x55e180385948 <lineending+8> (gdb) watch *(size_t *) 0x55e180385948 Hardware watchpoint 1: *(size_t *) 0x55e180385948 Old value = 2 New value = 0 (gdb) print lineending $5 = {data = 0x55e18035b2ad "\r\n", len = 0} (cherry picked from commit 92359a62a0e31734ad8069c66f64b37f9eaaccbe)
* | SECURITY: Leave a clean smtp_out input buffer even in case of read errorHeiko Schlittermann (HS12-RIPE)2021-04-281-1/+2
| | | | | | | | | | | | | | | | | | | | Based on Heiko Schlittermann's commit 54895bc3. This fixes: 7/ In src/smtp_out.c, read_response_line(), inblock->ptr is not updated when -1 is returned. This does not seem to have bad consequences, but is maybe not the intended behavior. (cherry picked from commit 30f5d98786fb4e6ccfdd112fe65c153f0ee34c5f)
* | SECURITY: Always exit when LOG_PANIC_DIE is setQualys Security Advisory2021-04-282-0/+5
| | | | | | | | (cherry picked from commit e20aa895b37f449d5c81c3e7b102fc534b5d23ba)
* | CVE-2020-28012: Missing close-on-exec flag for privileged pipeQualys Security Advisory2021-04-282-0/+8
| | | | | | | | (cherry picked from commit 72dad1e64bb3d1ff387938f59678098cab1f60a3)
* | CVE-2020-28024: Heap buffer underflow in smtp_ungetc()Qualys Security Advisory2021-04-282-0/+6
| | | | | | | | (cherry picked from commit 998e5a9db121c3eff15cac16859bdffd7adcbe57)
* | CVE-2020-28009: Integer overflow in get_stdinput()Qualys Security Advisory2021-04-281-1/+18
| | | | | | | | (cherry picked from commit bbf1bb10bee5a1d7cbcc97f178b348189219eb7d)
* | CVE-2020-28015+28021: New-line injection into spool header fileQualys Security Advisory2021-04-281-5/+18
| | | | | | | | (cherry picked from commit 31b1a42d0bd29cb05f85e56d3343b13bef20a2bd)
* | CVE-2020-28026: Line truncation and injection in spool_read_header()Heiko Schlittermann (HS12-RIPE)2021-04-281-16/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This also fixes: 2/ In src/spool_in.c: 462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1 463 && big_buffer[len-1] != '\n' 464 ) 465 { /* buffer not big enough for line; certs make this possible */ 466 uschar * buf; 467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR; 468 buf = store_get_perm(big_buffer_size *= 2, FALSE); 469 memcpy(buf, big_buffer, --len); The --len in memcpy() chops off a useful byte (we know for sure that big_buffer[len-1] is not a '\n' because we entered the while loop). Based on a patch done by Qualys. (cherry picked from commit f0c307458e1ee81abbe7ed2d4a8d16b5cbd8a799)
* | CVE-2020-28022: Heap out-of-bounds read and write in extract_option()Heiko Schlittermann (HS12-RIPE)2021-04-281-9/+14
| | | | | | | | | | | | Based on Phil Pennock's commit c5017adf. (cherry picked from commit 9e941e1807b624b255c9ec0f41a0b3a89e144de3)
* | CVE-2020-28017: Integer overflow in receive_add_recipient()Heiko Schlittermann (HS12-RIPE)2021-04-281-6/+6
| | | | | | | | | | | | Based on Phil Pennock's commit e3b441f7. (cherry picked from commit 18a19e18242edc5ab2082fa9c41cd6210d1b6087)
* | SECURITY: Refuse negative and large store allocationsHeiko Schlittermann (HS12-RIPE)2021-04-281-6/+12
| | | | | | | | | | | | Based on Phil Pennock's commits b34d3046 and e6c1606a. Done by Qualys. (cherry picked from commit 09d36bd64fc5bf71d8882af35c41ac4e8599acc1)
* | CVE-2020-28013: Heap buffer overflow in parse_fix_phrase()Heiko Schlittermann (HS12-RIPE)2021-04-281-6/+1
| | | | | | | | | | | | Based on Phil Pennock's 8a50c88a, done by Qualys (cherry picked from commit 8161c16ec7320ac6164954bade23179a0ed095eb)
* | CVE-2020-28011: Heap buffer overflow in queue_run()Qualys Security Advisory2021-04-281-4/+10
| | | | | | | | (cherry picked from commit 6e1fb878e95f8e6f838ffde5258c7a969c981865)
* | CVE-2020-28010: Heap out-of-bounds write in main()Heiko Schlittermann (HS12-RIPE)2021-04-281-6/+3
| | | | | | | | | | | | Based on Phil Pennock's 0f57feb4. Done by Qualys, modified by me. (cherry picked from commit b0982c2776048948ebae48574b70fa487684cb8c)
* | CVE-2020-28018: Use-after-free in tls-openssl.cQualys Security Advisory2021-04-281-4/+0
| | | | | | | | (cherry picked from commit 6290686dd59d8158d100c67e8f96df27158a6fc5)
* | CVE-2020-28025: Heap out-of-bounds read in pdkim_finish_bodyhash()Qualys Security Advisory2021-04-281-1/+1
| | | | | | | | (cherry picked from commit cad30cd3fb96196e908e0d66b1b45fdf377c850c)
* | CVE-2020-28014, CVE-2021-27216: PID file handlingHeiko Schlittermann (HS12-RIPE)2021-04-284-43/+149
| | | | | | | | | | | | | | Arbitrary PID file creation, clobbering, and deletion. Patch provided by Qualys. (cherry picked from commit 974f32939a922512b27d9f0a8a1cb5dec60e7d37)
* | Add priv.c: reworked version of priv dropping codeHeiko Schlittermann (HS12-RIPE)2021-04-2814-73/+81
| | | | | | | | (cherry picked from commit 82b545236e6dc82b7af34528c532811bfc74ea19)
* | CVE-2020-28008: Assorted attacks in Exim's spool directoryHeiko Schlittermann (HS12-RIPE)2021-04-2811-57/+77
| | | | | | | | | | | | | | | | | | | | | | | | We patch dbfn_open() by introducing two functions priv_drop_temp() and priv_restore() (inspired by OpenSSH's functions temporarily_use_uid() and restore_uid()), which temporarily drop and restore root privileges thanks to seteuid(). This goes against Exim's developers' wishes ("Exim (the project) doesn't trust seteuid to work reliably") but, to the best of our knowledge, seteuid() works everywhere and is the only way to securely fix dbfn_open(). (cherry picked from commit 18da59151dbafa89be61c63580bdb295db36e374)
* | CVE-2020-28019: Failure to reset function pointer after BDAT errorJeremy Harris2021-04-281-1/+14
| | | | | | | | | | | | | | Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy Harris's commits aa171254 and 9aceb5c2. (cherry picked from commit 0a3fbb7e3be375bc93b8e359c6aff333c7c2d76f)
* | SECURITY: smtp_out: Leave a clean input buffer, even in case of read errorHeiko Schlittermann (HS12-RIPE)2021-04-281-2/+3
| | | | | | | | | | | | | | | | | | | | Credits: Qualys 7/ In src/smtp_out.c, read_response_line(), inblock->ptr is not updated when -1 is returned. This does not seem to have bad consequences, but is maybe not the intended behavior. (cherry picked from commit f7ac5a7d1e817bf60f161e7a1d40b65d66da607f)
* | SECURITY: Avoid modification of constant dataHeiko Schlittermann (HS12-RIPE)2021-04-281-8/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 6/ In src/pdkim/pdkim.c, pdkim_update_ctx_bodyhash() is sometimes called with a global orig_data and hence canon_data, and the following line can therefore modify data that should be constant: 773 canon_data->len = b->bodylength - b->signed_body_bytes; For example, the following proof of concept sets lineending.len to 0 (this should not be possible): (sleep 10; echo 'EHLO test'; sleep 3; echo 'MAIL FROM:<>'; sleep 3; echo 'RCPT TO:postmaster'; sleep 3; echo 'DATA'; date >&2; sleep 30; printf 'DKIM-Signature:a=rsa-sha1;c=simple/simple;l=0\r\n\r\n\r\nXXX\r\n.\r\n'; sleep 30) | nc -n -v 192.168.56.102 25 (gdb) print lineending $1 = {data = 0x55e18035b2ad "\r\n", len = 2} (gdb) print &lineending.len $3 = (size_t *) 0x55e180385948 <lineending+8> (gdb) watch *(size_t *) 0x55e180385948 Hardware watchpoint 1: *(size_t *) 0x55e180385948 Old value = 2 New value = 0 (gdb) print lineending $5 = {data = 0x55e18035b2ad "\r\n", len = 0} (cherry picked from commit 9fce76f56459dde7489eb21ce1ff822e04e10f43)
* | SECURITY: Avoid memory corruption in dkim handlingHeiko Schlittermann (HS12-RIPE)2021-04-281-6/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 6/ In src/pdkim/pdkim.c, pdkim_update_ctx_bodyhash() is sometimes called with a global orig_data and hence canon_data, and the following line can therefore modify data that should be constant: 773 canon_data->len = b->bodylength - b->signed_body_bytes; For example, the following proof of concept sets lineending.len to 0 (this should not be possible): (sleep 10; echo 'EHLO test'; sleep 3; echo 'MAIL FROM:<>'; sleep 3; echo 'RCPT TO:postmaster'; sleep 3; echo 'DATA'; date >&2; sleep 30; printf 'DKIM-Signature:a=rsa-sha1;c=simple/simple;l=0\r\n\r\n\r\nXXX\r\n.\r\n'; sleep 30) | nc -n -v 192.168.56.102 25 (gdb) print lineending $1 = {data = 0x55e18035b2ad "\r\n", len = 2} (gdb) print &lineending.len $3 = (size_t *) 0x55e180385948 <lineending+8> (gdb) watch *(size_t *) 0x55e180385948 Hardware watchpoint 1: *(size_t *) 0x55e180385948 Old value = 2 New value = 0 (gdb) print lineending $5 = {data = 0x55e18035b2ad "\r\n", len = 0} (cherry picked from commit ea850e27714ccda2090d781ebe89b410bc38c2c6)
* | SECURITY: Avoid decrement of dkim_collect_input if already at 0Heiko Schlittermann (HS12-RIPE)2021-04-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 5/ receive_msg() calls dkim_exim_verify_finish(), which sets dkim_collect_input to 0 and calls pdkim_feed_finish(), which calls pdkim_header_complete(), which decreases dkim_collect_input to UINT_MAX, which reactivates the DKIM code. As a result, pdkim_feed() is called again (through receive_getc at the end of receive_msg()), but functions like pdkim_finish_bodyhash() and exim_sha_finish() have already been called (in pdkim_feed_finish()). This suggests a use-after-free. But it seems that a use-after-free would happen only with EVP_DigestFinal() (in exim_sha_finish()), which does not seem to be reachable via DKIM (no SHA3). But we checked OpenSSL only, not GnuTLS. Here is a proof of concept that triggers the bug (which came very close to a security vulnerability): (sleep 10; echo 'EHLO test'; sleep 3; echo 'MAIL FROM:<>'; sleep 3; echo 'RCPT TO:postmaster'; sleep 3; echo 'BDAT 42 LAST'; date >&2; sleep 30; printf 'not a valid header line\r\nDKIM-Signature:\r\nXXX'; sleep 30) | nc -n -v 192.168.56.102 25 (gdb) print &dkim_collect_input $2 = (unsigned int *) 0x55e180386d90 <dkim_collect_input> (gdb) watch *(unsigned int *) 0x55e180386d90 Hardware watchpoint 1: *(unsigned int *) 0x55e180386d90 Old value = 0 New value = 4294967295 #0 0x000055e18031f805 in pdkim_header_complete (ctx=ctx@entry=0x55e181b9e8e0) at pdkim.c:1006 #1 0x000055e18032106c in pdkim_feed_finish (ctx=0x55e181b9e8e0, return_signatures=0x55e180386d78 <dkim_signatures>, err=err@entry=0x7ffe443e1d00) at pdkim.c:1490 #2 0x000055e1802a3280 in dkim_exim_verify_finish () at dkim.c:328 #3 0x000055e1802c9d1d in receive_msg (extract_recip=extract_recip@entry=0) at receive.c:3409 (cherry picked from commit e3674091056ac05eb7ef1c504accce790c434bd7)
* | SECURITY: Check overrun rcpt_count integerHeiko Schlittermann (HS12-RIPE)2021-04-281-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 4/ In src/smtp_in.c: 4966 case RCPT_CMD: 4967 HAD(SCH_RCPT); 4968 rcpt_count++; .... 5123 if (rcpt_count > recipients_max && recipients_max > 0) In theory this recipients_max check can be bypassed, because the int rcpt_count can overflow (become negative). In practice this would either consume too much memory or generate too much network traffic, but maybe it should be fixed anyway. (cherry picked from commit 04139ca809fbe56d8fe9c55a77640ea9fa93b8f1)
* | SECURITY: Fix safeguard against upward traversal in msglog files.Heiko Schlittermann (HS12-RIPE)2021-04-282-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 3/ In src/deliver.c: 333 static int 334 open_msglog_file(uschar *filename, int mode, uschar **error) 335 { 336 if (Ustrstr(filename, US"/../")) 337 log_write(0, LOG_MAIN|LOG_PANIC, 338 "Attempt to open msglog file path with upward-traversal: '%s'\n", filename); Should this be LOG_PANIC_DIE instead of LOG_PANIC? Right now it will log the /../ attempt but will open the file anyway. (cherry picked from commit 742c27f02d83792937dcb1719b380d3dde6228bf)
* | SECURITY: Don't miss the very last byte when reading long lines from -HHeiko Schlittermann (HS12-RIPE)2021-04-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 2/ In src/spool_in.c: 462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1 463 && big_buffer[len-1] != '\n' 464 ) 465 { /* buffer not big enough for line; certs make this possible */ 466 uschar * buf; 467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR; 468 buf = store_get_perm(big_buffer_size *= 2, FALSE); 469 memcpy(buf, big_buffer, --len); The --len in memcpy() chops off a useful byte (we know for sure that big_buffer[len-1] is not a '\n' because we entered the while loop). (cherry picked from commit 58454ea01c2e817481770954edf09ad82f3cd417)
* | SECURITY: off-by-one in smtp transport (read response)Heiko Schlittermann (HS12-RIPE)2021-04-281-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Credits: Qualys 1/ In src/transports/smtp.c: 2281 int n = sizeof(sx->buffer); 2282 uschar * rsp = sx->buffer; 2283 2284 if (sx->esmtp_sent && (n = Ustrlen(sx->buffer)) < sizeof(sx->buffer)/2) 2285 { rsp = sx->buffer + n + 1; n = sizeof(sx->buffer) - n; } This should probably be either: rsp = sx->buffer + n + 1; n = sizeof(sx->buffer) - n - 1; or: rsp = sx->buffer + n; n = sizeof(sx->buffer) - n; (not sure which) to avoid an off-by-one. (cherry picked from commit d2c44ef5dd94f1f43ba1d1a02bc4594f4fba5e38)