From cdee66a2abd6e3f2da6efc36f8efd4b5dd46ce4c Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Thu, 18 Mar 2021 07:59:21 +0100 Subject: Enforce pid_file_path start at "/" (cherry picked from commit 60f2a8e797d9ebaea1e3eac4ad28ff64e11bab40) (cherry picked from commit 6b3d553c733475a1033c8b7a241e6506d7ed73b1) --- doc/doc-txt/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index df6efeea3..d66dc64d1 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -252,6 +252,8 @@ JH/53 Bug 2743: fix immediate-delivery via named queue. Previously this would fail with a taint-check on the spoolfile name, and leave the message queued. +HS/01 Enforce absolute PID file path name. + Exim version 4.94 ----------------- -- cgit v1.2.3 From 25cd313cfb1f29f179319daf81de63e989d442a7 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Thu, 18 Mar 2021 07:56:59 +0100 Subject: Handle SIGINT as we do with SIGTERM (cherry picked from commit cdc5c672e1c309294626cd5ed90acdccb05baaa1) (cherry picked from commit f9c8211fb0ad0dd362f471978a5e0abc5dfa71b4) --- doc/doc-txt/ChangeLog | 2 ++ src/src/daemon.c | 6 +++++- test/stderr/0433 | 6 ++++++ test/stderr/0438 | 6 +++--- test/stderr/0609 | 2 +- test/stderr/1007 | 16 ++++++++-------- test/stderr/2201 | 2 +- 7 files changed, 26 insertions(+), 14 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index d66dc64d1..c219275fc 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -254,6 +254,8 @@ JH/53 Bug 2743: fix immediate-delivery via named queue. Previously this would HS/01 Enforce absolute PID file path name. +HS/02 Handle SIGINT as we handle SIGTERM: terminate the Exim process. + Exim version 4.94 ----------------- diff --git a/src/src/daemon.c b/src/src/daemon.c index 0b39fd555..ed7d30a16 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -471,6 +471,7 @@ if (pid == 0) signal(SIGCHLD, SIG_IGN); #endif signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); /* Attempt to get an id from the sending machine via the RFC 1413 protocol. We do this in the sub-process in order not to hold up the @@ -697,6 +698,7 @@ if (pid == 0) signal(SIGHUP, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); if (geteuid() != root_uid && !deliver_drop_privilege) { @@ -985,7 +987,7 @@ daemon_die(void) { int pid; -DEBUG(D_any) debug_printf("SIGTERM seen\n"); +DEBUG(D_any) debug_printf("SIGTERM/SIGINT seen\n"); #if !defined(DISABLE_TLS) && (defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)) tls_watch_invalidate(); #endif @@ -1891,6 +1893,7 @@ os_non_restarting_signal(SIGCHLD, main_sigchld_handler); sigterm_seen = FALSE; os_non_restarting_signal(SIGTERM, main_sigterm_handler); +os_non_restarting_signal(SIGINT, main_sigterm_handler); /* If we are to run the queue periodically, pretend the alarm has just gone off. This will cause the first queue-runner to get kicked off straight away. */ @@ -2178,6 +2181,7 @@ for (;;) signal(SIGHUP, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); /* Re-exec if privilege has been given up, unless deliver_drop_ privilege is set. Reset SIGALRM before exec(). */ diff --git a/test/stderr/0433 b/test/stderr/0433 index c178519ab..b36788373 100644 --- a/test/stderr/0433 +++ b/test/stderr/0433 @@ -20,6 +20,7 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -43,6 +44,7 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -67,6 +69,7 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -91,6 +94,7 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 0.0.0.0; 127.0.0.1.1228 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -116,6 +120,7 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -141,5 +146,6 @@ daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... SIGTERM seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX +SIGTERM/SIGINT seen search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> diff --git a/test/stderr/0438 b/test/stderr/0438 index b50e6e30a..040f4f959 100644 --- a/test/stderr/0438 +++ b/test/stderr/0438 @@ -20,7 +20,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -44,7 +44,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.anotherpid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -68,7 +68,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/mypidfile -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> diff --git a/test/stderr/0609 b/test/stderr/0609 index 2ae8a95bd..5d6f97fd8 100644 --- a/test/stderr/0609 +++ b/test/stderr/0609 @@ -50,5 +50,5 @@ ppppp LOG: lost_incoming_connection MAIN ppppp unexpected disconnection while reading SMTP command from [127.0.0.1] D=qqs ppppp >>>>>>>>>>>>>>>> Exim pid=pppp (daemon-accept) terminating with rc=1 >>>>>>>>>>>>>>>> ppppp 1 SMTP accept process running -ppppp SIGTERM seen +ppppp SIGTERM/SIGINT seen ppppp >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> diff --git a/test/stderr/1007 b/test/stderr/1007 index acadf2270..9ec794af5 100644 --- a/test/stderr/1007 +++ b/test/stderr/1007 @@ -19,7 +19,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 (IPv6 and IPv4) daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -44,7 +44,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 (IPv6 and IPv4) port 1226 (IPv6 and IPv4) daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -70,7 +70,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 (IPv6 and IPv4) port 1226 (IPv6 and IPv4) [127.0.0.1]:1228 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; ::0 ; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -96,7 +96,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 (IPv6 and IPv4) port 1226 (IPv6 and IPv4) [127.0.0.1]:1228 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 0.0.0.0; 127.0.0.1.1228 ; ::0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -119,7 +119,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on [ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6]:{1225,1226} daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -145,7 +145,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1227 (IPv6 and IPv4) [127.0.0.1]:1228 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; ::0 ; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -172,7 +172,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on [127.0.0.1]:{1227,1225} daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; ::0 ; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -198,7 +198,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 (IPv6 and IPv4) port 1226 (IPv4) daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen +SIGTERM/SIGINT seen pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> diff --git a/test/stderr/2201 b/test/stderr/2201 index 80ebe911e..229de2ce0 100644 --- a/test/stderr/2201 +++ b/test/stderr/2201 @@ -235,5 +235,5 @@ ppppp child ppppp ended: status=0x0 ppppp normal exit, 0 ppppp 0 SMTP accept processes now running ppppp Listening... -ppppp SIGTERM seen +ppppp SIGTERM/SIGINT seen ppppp >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> -- cgit v1.2.3 From 7411ebe05198d5365557b6c982b76ceb9e843894 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 22:14:45 -0400 Subject: Default config: reject on too many bad RCPT An example exploit failed against my system, because I had this sanity guard in place; it's not a real security fix since a careful attacker could find enough valid recipients to hit that problem, but it highlights that this is a useful enough pattern that we should encourage its wider use. (cherry picked from commit 2a636a39fff29b7c3da1798767a510dfed982a62) (cherry picked from commit 346f96bad326893f9c1fa772a5b8ac35b1f8f7bd) --- doc/doc-txt/ChangeLog | 2 ++ src/src/configure.default | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index c219275fc..d741e3532 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -256,6 +256,8 @@ HS/01 Enforce absolute PID file path name. HS/02 Handle SIGINT as we handle SIGTERM: terminate the Exim process. +PP/01 Add a too-many-bad-recipients guard to the default config's RCPT ACL. + Exim version 4.94 ----------------- diff --git a/src/src/configure.default b/src/src/configure.default index 6127a9bf0..87f255aa9 100644 --- a/src/src/configure.default +++ b/src/src/configure.default @@ -458,6 +458,20 @@ acl_check_rcpt: require verify = sender + # Reject all RCPT commands after too many bad recipients + # This is partly a defense against spam abuse and partly attacker abuse. + # Real senders should manage, by the time they get to 10 RCPT directives, + # to have had at least half of them be real addresses. + # + # This is a lightweight check and can protect you against repeated + # invocations of more heavy-weight checks which would come after it. + + deny condition = ${if and {\ + {>{$rcpt_count}{10}}\ + {<{$recipients_count}{${eval:$rcpt_count/2}}} }} + message = Rejected for too many bad recipients + logwrite = REJECT [$sender_host_address]: bad recipient count high [${eval:$rcpt_count-$recipients_count}] + # Accept if the message comes from one of the hosts for which we are an # outgoing relay. It is assumed that such hosts are most likely to be MUAs, # so we set control=submission to make Exim treat the message as a -- cgit v1.2.3 From 66c014bb0d4972b7d5915795dec376535089740c Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Fri, 18 Sep 2020 10:25:42 -0400 Subject: Re-ran the conversion of all DH parameters I get different results now to those I got before. Now, using gen_pkcs3 linked against OpenSSL 1.1.1f-1ubuntu2 on Focal Fossa, I get the results below. The ffdhe2048 value now matches that at . I ran the same code yesterday for just the ffdhe2048 item and got code which seemed to me then to match what was already in the C file. Something hinky is going on, perhaps with my sanity. (the commit IDs changee because of heavy rebasing (heiko)) (cherry picked from commit 76ed8115182e2daaadb437ec9655df8000796ec5) (cherry picked from commit 0aafa26a5d3d528e79476c91537c28936154fe04) --- doc/doc-txt/ChangeLog | 5 +++++ src/src/std-crypto.c | 42 ++++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index d741e3532..58ba70f02 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -258,6 +258,11 @@ HS/02 Handle SIGINT as we handle SIGTERM: terminate the Exim process. PP/01 Add a too-many-bad-recipients guard to the default config's RCPT ACL. +PP/02 Bug 2643: Correct TLS DH constants. + A missing NUL termination in our code-generation tool had led to some + incorrect Diffie-Hellman constants in the Exim source. + Reported by kylon94, code-gen tool fix by Simon Arlott. + Exim version 4.94 ----------------- diff --git a/src/src/std-crypto.c b/src/src/std-crypto.c index e4df56006..b462908ea 100644 --- a/src/src/std-crypto.c +++ b/src/src/std-crypto.c @@ -350,12 +350,12 @@ static const char dh_ike_18_pem[] = */ static const char dh_ike_22_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIIBCAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y\n" +"MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y\n" "mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4\n" "+qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV\n" "w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0\n" "sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR\n" -"jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5Q==\n" +"jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=\n" "-----END DH PARAMETERS-----\n"; /* RFC 5114 IKE_id=23 @@ -396,7 +396,7 @@ static const char dh_ike_22_pem[] = */ static const char dh_ike_23_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIICCgKCAQEArRB+HpEjqdDWYPqnlVnFH6INZOVoO5/RtUsVl7YdCnXm+hQd+VpW\n" +"MIICDgKCAQEArRB+HpEjqdDWYPqnlVnFH6INZOVoO5/RtUsVl7YdCnXm+hQd+VpW\n" "26+aPEB7od8V6z1oijCcGA4d5rhaEnSgpm0/gVKtasISkDfJ7e/aTfjZHo/vVbc5\n" "S3rVt9C2wSIHyfmNEe002/bGugssi7wnvmoA4KC5xJcIs7+KMXCRiDaBKGEwvImF\n" "2xYC5xRBXZMwJ4Jzx94x79xzEPcSH9WgdBWYfZrcCkhtzfk6zEQyg4cxXXXhmMZB\n" @@ -406,7 +406,8 @@ static const char dh_ike_23_pem[] = "kAGo1mrXwXZpEBmZAkr00CcnWsE0i7inYtBSG8mK4kcVBCLqHtQJk51U2nRgzbX2\n" "xrJQcXy+8YDrNBGOmNEZUppF1vg0Vm4wJeMWozDvu3eobwwasVsFGuPUKMj4rLcK\n" "gTcVC47rEOGD7dGZY93Z4mPkdwWJ72qiHn9fL/OBtTnM40CdE81Wavu0jWwBkYHh\n" -"vP6UswJp7f5y/ptqpL17Wg8ccc//TBnEGOH27AF5gbwIfypwZbOEuJDTGR8r+g==\n" +"vP6UswJp7f5y/ptqpL17Wg8ccc//TBnEGOH27AF5gbwIfypwZbOEuJDTGR8r+gIC\n" +"AOA=\n" "-----END DH PARAMETERS-----\n"; /* RFC 5114 IKE_id=24 @@ -447,7 +448,7 @@ static const char dh_ike_23_pem[] = */ static const char dh_ike_24_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIICCQKCAQEAh6jmHbS2Zjz/u9GcZRlZmYzu9ghmDdDyXSzu1ENeOwDgDfjx1hlX\n" +"MIICDQKCAQEAh6jmHbS2Zjz/u9GcZRlZmYzu9ghmDdDyXSzu1ENeOwDgDfjx1hlX\n" "1Pr330VhsqowFsPZETQJb6o79Cltgw6afCCeDGSXUXq9WoqdMGvPZ+2R+eZyW0dY\n" "wCLgse9Cdb97bFv8EdRfkIi5QfVOseWbuLw5oL8SMH9cT9twxYGyP3a2Osrhyqa3\n" "kC1SUmc1SIoO8TxtmlG/pKs62DR3llJNjvahZ7WkGCXZZ+FE5RQFZCUcysuD5rSG\n" @@ -457,7 +458,8 @@ static const char dh_ike_24_pem[] = "+MKMuxilWuMTQQAKZQGW+THHelfy3fRj5ensFEt3feYqqrioYorDdtKC1u04ZOZ5\n" "gkKOvIMdFDSPby+Rk7UEWvJ2cWTh38lnwfs/LlWkvRv/6DucgNBSuYXRguoK2yo7\n" "cxPT/hTISEseBSWIubfSu9LfAWGZ7NBuFVfNCRWzNTu7ZODsN3/QKDcN+StSx4kU\n" -"KM3GfrYYS1I9HbJGwy9jB4SQ8A741kfRSNR5VFFeIyfP75jFgmZLTA9sxBZZ\n" +"KM3GfrYYS1I9HbJGwy9jB4SQ8A741kfRSNR5VFFeIyfP75jFgmZLTA9sxBZZAgIB\n" +"AA==\n" "-----END DH PARAMETERS-----\n"; /* ------------------------------------------------------------------------- */ @@ -509,12 +511,12 @@ A.1. ffdhe2048 */ static const char dh_ffdhe2048_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIH+AoH4DfhUWKK7Spqv3FYgJz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v\n" -"42NjDHXY9oGyAq7EYXrT3x7V1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhP\n" -"DHDg5ot34qaJ2vPv6HId8VihNq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq\n" -"2rdg1/RoHU9Co945TfSuVu3nY3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy\n" -"/pzphYP/jk8SMu7ygYPD/jsbTG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohr\n" -"QjhhKFyX//////////8CAQI=\n" +"MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" +"+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" +"87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" +"YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" +"7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n" +"ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICB/8=\n" "-----END DH PARAMETERS-----\n"; /* @@ -574,7 +576,7 @@ A.2. ffdhe3072 */ static const char dh_ffdhe3072_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" +"MIIBjAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" @@ -582,7 +584,7 @@ static const char dh_ffdhe3072_pem[] = "ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n" "7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n" "nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu\n" -"N///////////AgEC\n" +"N///////////AgECAgIL/w==\n" "-----END DH PARAMETERS-----\n"; /* @@ -654,7 +656,7 @@ A.3. ffdhe4096 */ static const char dh_ffdhe4096_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" +"MIICDAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" @@ -664,7 +666,7 @@ static const char dh_ffdhe4096_pem[] = "nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n" "8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n" "iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n" -"zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=\n" +"zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQICAg//\n" "-----END DH PARAMETERS-----\n"; /* @@ -756,7 +758,7 @@ A.4. ffdhe6144 */ static const char dh_ffdhe6144_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIIDCAKCAwEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" +"MIIDDAKCAwEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" @@ -772,7 +774,7 @@ static const char dh_ffdhe6144_pem[] = "w1h+ONoAd9m0dj5OS5Syu8GUxmUed8r5ku6qwCMqKBv2s6c5wSJhFoIK6NtYR6Z8\n" "vvnJCRtGLVOM1ysDdGrnf15iKSwxFWKoRlBdyC24VDOK5J9SNclbkReMzy3Vys70\n" "A+ydGBDGJysEWztx+dxrgNY/3UqOmtseaWKmlSbUMWHBpB1XDXk42tSkDjKc0OQO\n" -"Zf//////////AgEC\n" +"Zf//////////AgECAgIX/w==\n" "-----END DH PARAMETERS-----\n"; /* @@ -886,7 +888,7 @@ A.5. ffdhe8192 */ static const char dh_ffdhe8192_pem[] = "-----BEGIN DH PARAMETERS-----\n" -"MIIECAKCBAEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" +"MIIEDAKCBAEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" @@ -907,7 +909,7 @@ static const char dh_ffdhe8192_pem[] = "UVQfxoychrAiu3CZh2pGDnRRqKkxCXA/7hwhfmw4JuUsUappHg5CPPyZ6eMWUMEh\n" "e2JIFs2tmpX51bgBlIjZwKCh/jB1pXfiMYP4HUo/L6RXHvyM4LqKT+i2hV3+crCm\n" "bt7S+6v75Yow+vq+HF1xqH4vdB74wf6G/qa7/eUwZ38Nl9EdSfeoRD0IIuUGqfRh\n" -"TgEeKpSDj/iM1oyLt8XGQkz//////////wIBAg==\n" +"TgEeKpSDj/iM1oyLt8XGQkz//////////wIBAgICH/8=\n" "-----END DH PARAMETERS-----\n"; /* ========================================================================= */ -- cgit v1.2.3 From c1fb74d63ecf0cd1501e53352419bfdfd154b7ea Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 18:11:35 -0400 Subject: SECURITY: length limits on many cmdline options We'll also now abort upon, rather than silently truncate, a driver name (router, transport, ACL, etc) encountered in the config which is longer than the 64-char limit. (cherry picked from commit ff8bef9ae2370db4a7873fe2ce573a607fe6999f) (cherry picked from commit a8bd24b96c2027fd839f95a9e6b3282453ae288e) --- doc/doc-docbook/spec.xfpt | 19 ++++++++++ doc/doc-txt/ChangeLog | 6 +++ src/src/acl.c | 4 +- src/src/exim.c | 93 +++++++++++++++++++++++++++++++---------------- src/src/exim.h | 45 +++++++++++++++++++++++ src/src/macro_predef.c | 2 +- src/src/macros.h | 6 --- src/src/malware.c | 2 +- src/src/parse.c | 8 ++-- src/src/readconf.c | 30 ++++++++++----- src/src/transport.c | 9 +++-- 11 files changed, 165 insertions(+), 59 deletions(-) (limited to 'doc') diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 9b8c92bbd..61abb70c0 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -51,6 +51,8 @@ .set ACL "access control lists (ACLs)" .set I "    " +.set drivernamemax "64" + .macro copyyear 2020 .endmacro @@ -18802,6 +18804,11 @@ which the preconditions are tested. The order of expansion of the options that provide data for a transport is: &%errors_to%&, &%headers_add%&, &%headers_remove%&, &%transport%&. +.new +The name of a router is limited to be &drivernamemax; ASCII characters long; +prior to Exim 4.95 names would be silently truncated at this length, but now +it is enforced. +.wen .option address_data routers string&!! unset @@ -22345,6 +22352,12 @@ and &$original_domain$& is never set. .scindex IIDgenoptra1 "generic options" "transport" .scindex IIDgenoptra2 "options" "generic; for transports" .scindex IIDgenoptra3 "transport" "generic options for" +.new +The name of a transport is limited to be &drivernamemax; ASCII characters long; +prior to Exim 4.95 names would be silently truncated at this length, but now +it is enforced. +.wen + The following generic options apply to all transports: @@ -27181,6 +27194,12 @@ permitted to use it as a relay. SMTP authentication is not of relevance to the transfer of mail between servers that have no managerial connection with each other. +.new +The name of an authenticator is limited to be &drivernamemax; ASCII characters long; +prior to Exim 4.95 names would be silently truncated at this length, but now +it is enforced. +.wen + .cindex "AUTH" "description of" .cindex "ESMTP extensions" AUTH Very briefly, the way SMTP authentication works is as follows: diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 58ba70f02..4c6eb810e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -263,6 +263,12 @@ PP/02 Bug 2643: Correct TLS DH constants. incorrect Diffie-Hellman constants in the Exim source. Reported by kylon94, code-gen tool fix by Simon Arlott. +PP/03 Fix Linux security issue CVE-2020-SLCWD and guard against PATH_MAX + better. Reported by Qualys. + +PP/04 Impose security length checks on various command-line options. + Fixes CVE-2020-SPRSS reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/acl.c b/src/src/acl.c index a6c3d4cbe..f358516a1 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -486,7 +486,7 @@ static control_def controls_list[] = { { US"no_delay_flush", FALSE, ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START }, - + [CONTROL_NO_ENFORCE_SYNC] = { US"no_enforce_sync", FALSE, ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START @@ -744,7 +744,7 @@ while ((s = (*func)())) int v, c; BOOL negated = FALSE; uschar *saveline = s; - uschar name[64]; + uschar name[EXIM_DRIVERNAME_MAX]; /* Conditions (but not verbs) are allowed to be negated by an initial exclamation mark. */ diff --git a/src/src/exim.c b/src/src/exim.c index fd1d87362..112fa4f3d 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -760,6 +760,25 @@ vfprintf(stderr, fmt, ap); exit(EXIT_FAILURE); } +/* fail if a length is too long */ +static void +exim_len_fail_toolong(int itemlen, int maxlen, const char *description) +{ +if (itemlen <= maxlen) + return; +fprintf(stderr, "exim: length limit exceeded (%d > %d) for: %s\n", + len, maxlen, description) +exit(EXIT_FAILURE); +} + +/* only pass through the string item back to the caller if it's short enough */ +static const uschar * +exim_str_fail_toolong(const uschar *item, int maxlen, const char *description) +{ +exim_len_fail_toolong(Ustrlen(item), maxlen, description); +return item; +} + /* exim_chown_failure() called from exim_chown()/exim_fchown() on failure of chown()/fchown(). See src/functions.h for more explanation */ int @@ -2140,10 +2159,10 @@ on the second character (the one after '-'), to save some effort. */ { if (++i >= argc) exim_fail("exim: string expected after %s\n", arg); - if (Ustrcmp(argrest, "d") == 0) ftest_domain = argv[i]; - else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = argv[i]; - else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = argv[i]; - else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = argv[i]; + if (Ustrcmp(argrest, "d") == 0) ftest_domain = exim_str_fail_toolong(argv[i], EXIM_DOMAINNAME_MAX, "-bfd"); + else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfl"); + else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfp"); + else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfs"); else badarg = TRUE; } break; @@ -2153,7 +2172,7 @@ on the second character (the one after '-'), to save some effort. */ if (!*argrest || Ustrcmp(argrest, "c") == 0) { if (++i >= argc) { badarg = TRUE; break; } - sender_host_address = string_copy_taint(argv[i], TRUE); + sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-bh"), TRUE); host_checking = checking = f.log_testing_mode = TRUE; f.host_checking_callout = *argrest == 'c'; message_logs = FALSE; @@ -2611,7 +2630,7 @@ on the second character (the one after '-'), to save some effort. */ case 'F': if (!*argrest) if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; } - originator_name = string_copy_taint(argrest, TRUE); + originator_name = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_HUMANNAME_MAX, "-F"), TRUE); f.sender_name_forced = TRUE; break; @@ -2637,6 +2656,7 @@ on the second character (the one after '-'), to save some effort. */ uschar *errmess; if (!*argrest) if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; } + (void) exim_str_fail_toolong(argrest, EXIM_DISPLAYMAIL_MAX, "-f"); if (!*argrest) *(sender_address = store_get(1, FALSE)) = '\0'; /* Ensure writeable memory */ else @@ -2733,9 +2753,9 @@ on the second character (the one after '-'), to save some effort. */ if (msg_action_arg >= 0) exim_fail("exim: incompatible arguments\n"); - continue_transport = string_copy_taint(argv[++i], TRUE); - continue_hostname = string_copy_taint(argv[++i], TRUE); - continue_host_address = string_copy_taint(argv[++i], TRUE); + continue_transport = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-C internal transport"), TRUE); + continue_hostname = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-C internal hostname"), TRUE); + continue_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-C internal hostaddr"), TRUE); continue_sequence = Uatoi(argv[++i]); msg_action = MSG_DELIVER; msg_action_arg = ++i; @@ -2780,7 +2800,7 @@ on the second character (the one after '-'), to save some effort. */ /* -MCd: for debug, set a process-purpose string */ case 'd': if (++i < argc) - process_purpose = string_copy_taint(argv[i], TRUE); + process_purpose = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCd"), TRUE); else badarg = TRUE; break; @@ -2788,7 +2808,7 @@ on the second character (the one after '-'), to save some effort. */ from the commandline should be tainted - but we will need an untainted value for the spoolfile when doing a -odi delivery process. */ - case 'G': if (++i < argc) queue_name = string_copy_taint(argv[i], FALSE); + case 'G': if (++i < argc) queue_name = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCG"), FALSE); else badarg = TRUE; break; @@ -2861,7 +2881,7 @@ on the second character (the one after '-'), to save some effort. */ case 'r': case 's': if (++i < argc) { - continue_proxy_sni = string_copy_taint(argv[i], TRUE); + continue_proxy_sni = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_HOSTNAME_MAX, "-MCr/-MCs"), TRUE); if (argrest[1] == 'r') continue_proxy_dane = TRUE; } else badarg = TRUE; @@ -2873,13 +2893,13 @@ on the second character (the one after '-'), to save some effort. */ and the TLS cipher. */ case 't': if (++i < argc) - sending_ip_address = string_copy_taint(argv[i], TRUE); + sending_ip_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-MCt IP"), TRUE); else badarg = TRUE; if (++i < argc) sending_port = (int)(Uatol(argv[i])); else badarg = TRUE; if (++i < argc) - continue_proxy_cipher = string_copy_taint(argv[i], TRUE); + continue_proxy_cipher = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_CIPHERNAME_MAX, "-MCt cipher"), TRUE); else badarg = TRUE; /*FALLTHROUGH*/ @@ -2906,6 +2926,7 @@ on the second character (the one after '-'), to save some effort. */ following options which are followed by a single message id, and which act on that message. Some of them use the "recipient" addresses as well. -Mar add recipient(s) + -MG move to a different queue -Mmad mark all recipients delivered -Mmd mark recipients(s) delivered -Mes edit sender @@ -2941,7 +2962,7 @@ on the second character (the one after '-'), to save some effort. */ else if (Ustrcmp(argrest, "G") == 0) { msg_action = MSG_SETQUEUE; - queue_name_dest = string_copy_taint(argv[++i], TRUE); + queue_name_dest = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-MG"), TRUE); } else if (Ustrcmp(argrest, "mad") == 0) { @@ -3154,27 +3175,27 @@ on the second character (the one after '-'), to save some effort. */ /* -oMa: Set sender host address */ if (Ustrcmp(argrest, "a") == 0) - sender_host_address = string_copy_taint(argv[++i], TRUE); + sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMa"), TRUE); /* -oMaa: Set authenticator name */ else if (Ustrcmp(argrest, "aa") == 0) - sender_host_authenticated = string_copy_taint(argv[++i], TRUE); + sender_host_authenticated = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMaa"), TRUE); /* -oMas: setting authenticated sender */ else if (Ustrcmp(argrest, "as") == 0) - authenticated_sender = string_copy_taint(argv[++i], TRUE); + authenticated_sender = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE); /* -oMai: setting authenticated id */ else if (Ustrcmp(argrest, "ai") == 0) - authenticated_id = string_copy_taint(argv[++i], TRUE); + authenticated_id = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE); /* -oMi: Set incoming interface address */ else if (Ustrcmp(argrest, "i") == 0) - interface_address = string_copy_taint(argv[++i], TRUE); + interface_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMi"), TRUE); /* -oMm: Message reference */ @@ -3194,19 +3215,19 @@ on the second character (the one after '-'), to save some effort. */ if (received_protocol) exim_fail("received_protocol is set already\n"); else - received_protocol = string_copy_taint(argv[++i], TRUE); + received_protocol = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMr"), TRUE); /* -oMs: Set sender host name */ else if (Ustrcmp(argrest, "s") == 0) - sender_host_name = string_copy_taint(argv[++i], TRUE); + sender_host_name = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-oMs"), TRUE); /* -oMt: Set sender ident */ else if (Ustrcmp(argrest, "t") == 0) { sender_ident_set = TRUE; - sender_ident = string_copy_taint(argv[++i], TRUE); + sender_ident = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IDENTUSER_MAX, "-oMt"), TRUE); } /* Else a bad argument */ @@ -3256,10 +3277,11 @@ on the second character (the one after '-'), to save some effort. */ break; /* -oX : Override local_interfaces and/or default daemon ports */ + /* Limits: Is there a real limit we want here? 1024 is very arbitrary. */ case 'X': if (*argrest) badarg = TRUE; - else override_local_interfaces = string_copy_taint(argv[++i], TRUE); + else override_local_interfaces = string_copy_taint(exim_str_fail_toolong(argv[++i], 1024, "-oX", TRUE); break; /* -oY: Override creation of daemon notifier socket */ @@ -3307,9 +3329,10 @@ on the second character (the one after '-'), to save some effort. */ exim_fail("received_protocol is set already\n"); if (!hn) - received_protocol = string_copy_taint(argrest, TRUE); + received_protocol = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_DRIVERNAME_MAX, "-p"), TRUE); else { + (void) exim_str_fail_toolong(argrest, (EXIM_DRIVERNAME_MAX+1+EXIM_HOSTNAME_MAX), "-p:"); received_protocol = string_copyn_taint(argrest, hn - argrest, TRUE); sender_host_name = string_copy_taint(hn + 1, TRUE); } @@ -3365,6 +3388,7 @@ on the second character (the one after '-'), to save some effort. */ { int i; for (argrest++, i = 0; argrest[i] && argrest[i] != '/'; ) i++; + exim_len_fail_toolong(i, EXIM_DRIVERNAME_MAX, "-q*G"); queue_name = string_copyn(argrest, i); argrest += i; if (*argrest == '/') argrest++; @@ -3418,15 +3442,18 @@ on the second character (the one after '-'), to save some effort. */ /* -R: Set string to match in addresses for forced queue run to pick out particular messages. */ + /* Avoid attacks from people providing very long strings, and do so before + we make copies. */ + const char *tainted_selectstr; if (*argrest) - deliver_selectstring = string_copy_taint(argrest, TRUE); + tainted_selectstr = argrest; else if (i+1 < argc) - deliver_selectstring = string_copy_taint(argv[++i], TRUE); + tainted_selectstr = argv[++i]; else exim_fail("exim: string expected after -R\n"); + deliver_selectstring = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-R"), TRUE); break; - /* -r: an obsolete synonym for -f (see above) */ @@ -3457,12 +3484,14 @@ on the second character (the one after '-'), to save some effort. */ /* -S: Set string to match in addresses for forced queue run to pick out particular messages. */ + const char *tainted_selectstr; if (*argrest) - deliver_selectstring_sender = string_copy_taint(argrest, TRUE); + tainted_selectstr = argrest; else if (i+1 < argc) - deliver_selectstring_sender = string_copy_taint(argv[++i], TRUE); + tainted_selectstr = argv[++i]; else exim_fail("exim: string expected after -S\n"); + deliver_selectstring_sender = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-S"), TRUE); break; /* -Tqt is an option that is exclusively for use by the testing suite. @@ -3544,10 +3573,12 @@ on the second character (the one after '-'), to save some effort. */ exim_fail("exim: string expected after -X\n"); break; + /* -z: a line of text to log */ + case 'z': if (!*argrest) if (++i < argc) - log_oneline = string_copy_taint(argv[i], TRUE); + log_oneline = string_copy_taint(exim_str_fail_toolong(argv[i], 2048, "-z logtext"), TRUE); else exim_fail("exim: file name expected after %s\n", argv[i-1]); break; diff --git a/src/src/exim.h b/src/src/exim.h index bb8e4f6e2..8bbeecb4d 100644 --- a/src/src/exim.h +++ b/src/src/exim.h @@ -135,6 +135,51 @@ making unique names. */ # endif #endif +/* RFC 5321 specifies that the maximum length of a local-part is 64 octets +and the maximum length of a domain is 255 octets, but then also defines +the maximum length of a forward/reverse path as 256 not 64+1+255. +For an IP address, the maximum is 45 without a scope and we don't work +with scoped addresses, so go with that. (IPv6 with mapped IPv4). + +A hostname maximum length is in practice the same as the domainname, for +the same core reasons (maximum length of a DNS name), but the semantics +are different and seeing "DOMAIN" in source is confusing when talking about +hostnames; so we define a second macro. We'll use RFC 2181 as the reference +for this one. + +There is no known (to me) specification on the maximum length of a human name +in email addresses and we should be careful about imposing such a limit on +received email, but in terms of limiting what untrusted callers specify, or +local generation, having a limit makes sense. Err on the side of generosity. + +For a display mail address, we have a human name, an email in brackets, +possibly some (Comments), so it needs to be at least 512+3 and some more to +avoid extraneous errors. +Since the sane SMTP line length limit is 998, constraining such parameters to +be 1024 seems generous and unlikely to spuriously reject legitimate +invocations. + +The driver name is a name of a router/transport/authenticator etc in the +configuration file. We also use this for some other short strings, such +as queue names. +Also TLS ciphersuite name (no real known limit since the protocols use +integers, but max seen in reality is 45 octets). + +RFC 1413 gives us the 512 limit on IDENT protocol userids. +*/ + +#define EXIM_EMAILADDR_MAX 256 +#define EXIM_LOCALPART_MAX 64 +#define EXIM_DOMAINNAME_MAX 255 +#define EXIM_IPADDR_MAX 45 +#define EXIM_HOSTNAME_MAX 255 +#define EXIM_HUMANNAME_MAX 256 +#define EXIM_DISPLAYMAIL_MAX 1024 +#define EXIM_DRIVERNAME_MAX 64 +#define EXIM_CIPHERNAME_MAX 64 +#define EXIM_IDENTUSER_MAX 512 + + #include #include #include diff --git a/src/src/macro_predef.c b/src/src/macro_predef.c index b0f57be19..5340c5af8 100644 --- a/src/src/macro_predef.c +++ b/src/src/macro_predef.c @@ -72,7 +72,7 @@ options_from_list(optionlist * opts, unsigned nopt, const uschar * section, uschar * group) { const uschar * s; -uschar buf[64]; +uschar buf[EXIM_DRIVERNAME_MAX]; /* The 'previously-defined-substring' rule for macros in config file lines is done thus for these builtin macros: we know that the table diff --git a/src/src/macros.h b/src/src/macros.h index 43217807f..72856a53b 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -180,12 +180,6 @@ written on the spool, it gets read into big_buffer. */ #define LOCAL_SCAN_MAX_RETURN (BIG_BUFFER_SIZE - 24) -/* A limit to the length of an address. RFC 2821 limits the local part to 64 -and the domain to 255, so this should be adequate, taking into account quotings -etc. */ - -#define ADDRESS_MAXLENGTH 512 - /* The length of the base names of spool files, which consist of an internal message id with a trailing "-H" or "-D" added. */ diff --git a/src/src/malware.c b/src/src/malware.c index 831e9af1f..a6e354bc4 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -109,7 +109,7 @@ features_malware(void) { const uschar * s; uschar * t; -uschar buf[64]; +uschar buf[EXIM_DRIVERNAME_MAX]; spf(buf, sizeof(buf), US"_HAVE_MALWARE_"); diff --git a/src/src/parse.c b/src/src/parse.c index 885a01c0d..18a6df198 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -808,11 +808,11 @@ while (isspace(endptr[-1])) endptr--; *end = endptr - US mailbox; /* Although this code has no limitation on the length of address extracted, -other parts of Exim may have limits, and in any case, RFC 2821 limits local -parts to 64 and domains to 255, so we do a check here, giving an error if the -address is ridiculously long. */ +other parts of Exim may have limits, and in any case, RFC 5321 limits email +addresses to 256, so we do a check here, giving an error if the address is +ridiculously long. */ -if (*end - *start > ADDRESS_MAXLENGTH) +if (*end - *start > EXIM_EMAILADDR_MAX) { *errorptr = string_sprintf("address is ridiculously long: %.64s...", yield); return NULL; diff --git a/src/src/readconf.c b/src/src/readconf.c index e8e310beb..8a7b710a2 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -422,7 +422,7 @@ options_from_list(optionlist_config, nelem(optionlist_config), US"MAIN", NULL); void options_auths(void) { -uschar buf[64]; +uschar buf[EXIM_DRIVERNAME_MAX]; options_from_list(optionlist_auths, optionlist_auths_size, US"AUTHENTICATORS", NULL); @@ -439,7 +439,7 @@ for (struct auth_info * ai = auths_available; ai->driver_name[0]; ai++) void options_logging(void) { -uschar buf[64]; +uschar buf[EXIM_DRIVERNAME_MAX]; for (bit_table * bp = log_options; bp < log_options + log_options_count; bp++) { @@ -684,7 +684,7 @@ Returns: FALSE iff fatal error BOOL macro_read_assignment(uschar *s) { -uschar name[64]; +uschar name[EXIM_DRIVERNAME_MAX]; int namelen = 0; BOOL redef = FALSE; macro_item *m; @@ -1178,15 +1178,25 @@ uschar * readconf_readname(uschar *name, int len, uschar *s) { int p = 0; +BOOL broken = FALSE; if (isalpha(Uskip_whitespace(&s))) while (isalnum(*s) || *s == '_') { if (p < len-1) name[p++] = *s; + else { + broken = TRUE; + break; + } s++; } name[p] = 0; +if (broken) { + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, + "exim item name too long (>%d), unable to use \"%s\" (truncated)", + len, name); +} Uskip_whitespace(&s); return s; } @@ -1353,7 +1363,7 @@ static BOOL * get_set_flag(uschar *name, optionlist *oltop, int last, void *data_block) { optionlist *ol; -uschar name2[64]; +uschar name2[EXIM_DRIVERNAME_MAX]; sprintf(CS name2, "*set_%.50s", name); if (!(ol = find_option(name2, oltop, last))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, @@ -1626,8 +1636,8 @@ uschar *inttype = US""; uschar *sptr; uschar *s = buffer; uschar **str_target; -uschar name[64]; -uschar name2[64]; +uschar name[EXIM_DRIVERNAME_MAX]; +uschar name2[EXIM_DRIVERNAME_MAX]; /* There may be leading spaces; thereafter, we expect an option name starting with a letter. */ @@ -2089,7 +2099,7 @@ switch (type) case opt_bool_set: if (*s != 0) { - s = readconf_readname(name2, 64, s); + s = readconf_readname(name2, EXIM_DRIVERNAME_MAX, s); if (strcmpic(name2, US"true") == 0 || strcmpic(name2, US"yes") == 0) boolvalue = TRUE; else if (strcmpic(name2, US"false") == 0 || strcmpic(name2, US"no") == 0) @@ -2436,7 +2446,7 @@ void *value; uid_t *uidlist; gid_t *gidlist; uschar *s; -uschar name2[64]; +uschar name2[EXIM_DRIVERNAME_MAX]; if (!ol) { @@ -3706,7 +3716,7 @@ uschar *buffer; while ((buffer = get_config_line())) { - uschar name[64]; + uschar name[EXIM_DRIVERNAME_MAX]; uschar *s; /* Read the first name on the line and test for the start of a new driver. A @@ -4234,7 +4244,7 @@ acl_line = get_config_line(); while(acl_line) { - uschar name[64]; + uschar name[EXIM_DRIVERNAME_MAX]; tree_node *node; uschar *error; diff --git a/src/src/transport.c b/src/src/transport.c index d8fd85855..89252ec7a 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -959,9 +959,10 @@ if (!(tctx->options & topt_no_headers)) if (tctx->options & topt_add_return_path) { - uschar buffer[ADDRESS_MAXLENGTH + 20]; - int n = sprintf(CS buffer, "Return-path: <%.*s>\n", ADDRESS_MAXLENGTH, - return_path); + uschar buffer[EXIM_EMAILADDR_MAX + 20]; + int n = string_format(CS buffer, sizeof(buffer), + "Return-path: <%.*s>\n", + EXIM_EMAILADDR_MAX, return_path); if (!write_chunk(tctx, buffer, n)) goto bad; } @@ -1729,7 +1730,7 @@ while (1) { msgq[i].bKeep = TRUE; - Ustrncpy_nt(msgq[i].message_id, host_record->text + (i * MESSAGE_ID_LENGTH), + Ustrncpy_nt(msgq[i].message_id, host_record->text + (i * MESSAGE_ID_LENGTH), MESSAGE_ID_LENGTH); msgq[i].message_id[MESSAGE_ID_LENGTH] = 0; } -- cgit v1.2.3 From 5dc522966ae58ac845dc280495af651c9858f152 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 11:47:58 -0400 Subject: SECURITY: fix Qualys CVE-2020-SLCWD (cherry picked from commit bf5f9d56fadf9be8d947f141d31f7e0e8fa63762) (cherry picked from commit 6d2cfb575c95c1b81597d6b9eb2904cd695d7e4a) --- doc/doc-txt/ChangeLog | 8 ++++---- src/src/exim.c | 6 ++++++ src/src/macros.h | 14 +++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 4c6eb810e..ba9cc1c12 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -263,12 +263,12 @@ PP/02 Bug 2643: Correct TLS DH constants. incorrect Diffie-Hellman constants in the Exim source. Reported by kylon94, code-gen tool fix by Simon Arlott. -PP/03 Fix Linux security issue CVE-2020-SLCWD and guard against PATH_MAX - better. Reported by Qualys. - -PP/04 Impose security length checks on various command-line options. +PP/03 Impose security length checks on various command-line options. Fixes CVE-2020-SPRSS reported by Qualys. +PP/04 Fix Linux security issue CVE-2020-SLCWD and guard against PATH_MAX + better. Reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/exim.c b/src/src/exim.c index 49f7e5f36..1b7529c73 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -3870,7 +3870,13 @@ during readconf_main() some expansion takes place already. */ /* Store the initial cwd before we change directories. Can be NULL if the dir has already been unlinked. */ +errno = 0; initial_cwd = os_getcwd(NULL, 0); +if (!initial_cwd && errno) + exim_fail("exim: getting initial cwd failed: %s\n", strerror(errno)); + +if (initial_cwd && (strlen(CCS initial_cwd) >= BIG_BUFFER_SIZE)) + exim_fail("exim: initial cwd is far too long (%d)\n", Ustrlen(CCS initial_cwd)); /* checking: -be[m] expansion test - diff --git a/src/src/macros.h b/src/src/macros.h index 72856a53b..f8987d604 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -154,7 +154,9 @@ enough to hold all the headers from a normal kind of message. */ /* The initial size of a big buffer for use in various places. It gets put into big_buffer_size and in some circumstances increased. It should be at least -as long as the maximum path length. */ +as long as the maximum path length PLUS room for string additions. +Let's go with "at least twice as large as maximum path length". +*/ #ifdef AUTH_HEIMDAL_GSSAPI /* RFC 4121 section 5.2, SHOULD support 64K input buffers */ @@ -163,10 +165,12 @@ as long as the maximum path length. */ # define __BIG_BUFFER_SIZE 16384 #endif -#if defined PATH_MAX && PATH_MAX > __BIG_BUFFER_SIZE -# define BIG_BUFFER_SIZE PATH_MAX -#elif defined MAXPATHLEN && MAXPATHLEN > __BIG_BUFFER_SIZE -# define BIG_BUFFER_SIZE MAXPATHLEN +#ifndef PATH_MAX +/* exim.h will have ensured this exists before including us. */ +# error headers confusion, PATH_MAX missing in macros.h +#endif +#if (PATH_MAX*2) > __BIG_BUFFER_SIZE +# define BIG_BUFFER_SIZE (PATH_MAX*2) #else # define BIG_BUFFER_SIZE __BIG_BUFFER_SIZE #endif -- cgit v1.2.3 From cb08e2f59f2166660abc998a0554e64c61d4a0f5 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 19:00:51 -0400 Subject: SECURITY: fix Qualys CVE-2020-PFPSN (cherry picked from commit 93b6044e1636404f3463f3e1113098742e295542) (cherry picked from commit 4e59a5d5c448e1fcdcbead268ffe6561adf0224d) --- doc/doc-txt/ChangeLog | 4 ++++ src/src/parse.c | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index ba9cc1c12..07fba9c23 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -269,6 +269,10 @@ PP/03 Impose security length checks on various command-line options. PP/04 Fix Linux security issue CVE-2020-SLCWD and guard against PATH_MAX better. Reported by Qualys. +PP/05 Fix security issue CVE-2020-PFPSN and guard against cmdline invoker + providing a particularly obnoxious sender full name. + Reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/parse.c b/src/src/parse.c index 18a6df198..7dfb9a7eb 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -1129,9 +1129,17 @@ while (s < end) { if (ss >= end) ss--; *t++ = '('; - Ustrncpy(t, s, ss-s); - t += ss-s; - s = ss; + if (ss < s) + { + /* Someone has ended the string with "(". */ + ss = s; + } + else + { + Ustrncpy(t, s, ss-s); + t += ss-s; + s = ss; + } } } -- cgit v1.2.3 From bafc62583bc4ded96e3a66d2fb98c9d7afaa8768 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 20:42:40 -0400 Subject: SECURITY: fix Qualys CVE-2020-PFPZA (cherry picked from commit 29d7a8c25f182c91d5d30f124f9e296dce5c018e) (cherry picked from commit 0a6a7a3fd8464bae9ce0cf889e8eeb0bf0bab756) --- doc/doc-txt/ChangeLog | 3 +++ src/src/parse.c | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 07fba9c23..95b95e794 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -273,6 +273,9 @@ PP/05 Fix security issue CVE-2020-PFPSN and guard against cmdline invoker providing a particularly obnoxious sender full name. Reported by Qualys. +pp/06 Fix CVE-2020-28016 (PFPZA): Heap out-of-bounds write in parse_fix_phrase() + + Exim version 4.94 ----------------- diff --git a/src/src/parse.c b/src/src/parse.c index 7dfb9a7eb..8d689e88a 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -984,6 +984,11 @@ if (i < len) /* No non-printers; use the RFC 822 quoting rules */ +if (!len) + { + return string_copy_taint_function("", is_tainted(phrase)); + } + buffer = store_get(len*4, is_tainted(phrase)); s = phrase; -- cgit v1.2.3 From 15282ddb92382fb203e61d7a66f37aa2fbdebb82 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 20:49:49 -0400 Subject: SECURITY: refuse too small store allocations Negative sizes are definitely bad. Optimistically, I'm saying that zero is bad too. But perhaps we have something doing that, expecting to be able to grow. In which case we'll have to amend this. (cherry picked from commit 1c9afcec0043e2fb72607b2addb0613763705549) (cherry picked from commit 6f5d7e5af8eff688c36f81334e4f063689561963) --- doc/doc-txt/ChangeLog | 4 +++- src/src/store.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 95b95e794..5a9c8f214 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -273,8 +273,10 @@ PP/05 Fix security issue CVE-2020-PFPSN and guard against cmdline invoker providing a particularly obnoxious sender full name. Reported by Qualys. -pp/06 Fix CVE-2020-28016 (PFPZA): Heap out-of-bounds write in parse_fix_phrase() +PP/06 Fix CVE-2020-28016 (PFPZA): Heap out-of-bounds write in parse_fix_phrase() +PP/07 Refuse to allocate too little memory, block negative/zero allocations. + Security guard. Exim version 4.94 diff --git a/src/src/store.c b/src/src/store.c index 22615ea08..b5115fa13 100644 --- a/src/src/store.c +++ b/src/src/store.c @@ -268,6 +268,17 @@ store_get_3(int size, BOOL tainted, const char *func, int linenumber) { int pool = tainted ? store_pool + POOL_TAINT_BASE : store_pool; +/* Ensure we've been asked to allocate memory. +A negative size is a sign of a security problem. +A zero size is also suspect (but we might have to allow it if we find our API +expects it in some places). */ +if (size < 1) + { + log_write(0, LOG_MAIN|LOG_PANIC_DIE, + "bad memory allocation requested (%d bytes) at %s %d", + size, func, linenumber); + } + /* Round up the size to a multiple of the alignment. Although this looks a messy statement, because "alignment" is a constant expression, the compiler can do a reasonable job of optimizing, especially if the value of "alignment" is a -- cgit v1.2.3 From f07847e436d1130628717ef92e46b56b293d5fa1 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 21:38:25 -0400 Subject: SECURITY: default recipients_max to 50,000 A default of "unlimited" can have unfortunate consequences when people start putting many millions of recipients on a message. (cherry picked from commit 1d7780722a66cea8da5fa4ae0775e85d185fbf7e) (cherry picked from commit a6e1f69d82adcfd3caab8f228d96750dfddc8f07) --- doc/doc-docbook/spec.xfpt | 2 +- doc/doc-txt/ChangeLog | 2 ++ doc/doc-txt/OptionLists.txt | 2 +- src/src/globals.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 61abb70c0..68d9c056f 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -17394,7 +17394,7 @@ or if the message was submitted locally (not using TCP/IP), and the &%-bnq%& option was not set. -.option recipients_max main integer 0 +.option recipients_max main integer 50000 .cindex "limit" "number of recipients" .cindex "recipient" "maximum number" If this option is set greater than zero, it specifies the maximum number of diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 5a9c8f214..89a60e757 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -278,6 +278,8 @@ PP/06 Fix CVE-2020-28016 (PFPZA): Heap out-of-bounds write in parse_fix_phrase() PP/07 Refuse to allocate too little memory, block negative/zero allocations. Security guard. +PP/08 Change default for recipients_max from unlimited to 50,000. + Exim version 4.94 ----------------- diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index 183f6b722..59be0a06b 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -466,7 +466,7 @@ receive_timeout time 0s main received_header_text string* + main received_headers_max integer 30 main recipient_unqualified_hosts host list unset main 4.00 replacing receiver_unqualified_hosts -recipients_max integer 0 main 1.60 +recipients_max integer 50000 main 1.60 default changed in 4.95 (was 0) recipients_max_reject boolean false main 1.70 redirect_router string unset routers 4.00 remote_max_parallel integer 1 main diff --git a/src/src/globals.c b/src/src/globals.c index c45e8a930..bd874a789 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1295,7 +1295,7 @@ uschar *recipient_verify_failure = NULL; int recipients_count = 0; recipient_item *recipients_list = NULL; int recipients_list_max = 0; -int recipients_max = 0; +int recipients_max = 50000; const pcre *regex_AUTH = NULL; const pcre *regex_check_dns_names = NULL; const pcre *regex_From = NULL; -- cgit v1.2.3 From 0695aae1eb75b439862d0f7fbf099b5d08f55af0 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 21:48:05 -0400 Subject: SECURITY: Avoid integer overflow on too many recipients (cherry picked from commit 323ff55e67b44e95f9d3cfaba155e385aa33c4bd) (cherry picked from commit 3a54fcd1e303bf1cc49beca7ceac35d7448860a9) --- doc/doc-txt/ChangeLog | 5 +++++ src/src/receive.c | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 89a60e757..3d0e638d2 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -280,6 +280,11 @@ PP/07 Refuse to allocate too little memory, block negative/zero allocations. PP/08 Change default for recipients_max from unlimited to 50,000. +PP/09 Fix security issue with too many recipients on a message (to remove a + known security problem if someone does set recipients_max to unlimited, + or if local additions add to the recipient list). + Fixes CVE-2020-RCPTL reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/receive.c b/src/src/receive.c index b0dacbd68..67971c3e4 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -486,11 +486,18 @@ Returns: nothing void receive_add_recipient(uschar *recipient, int pno) { +/* XXX This is a math limit; we should consider a performance/sanity limit too. */ +const int safe_recipients_limit = INT_MAX / sizeof(recipient_item) - 1; + if (recipients_count >= recipients_list_max) { recipient_item *oldlist = recipients_list; int oldmax = recipients_list_max; recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50; + if ((recipients_list_max >= safe_recipients_limit) || (recipients_list_max < 0)) + { + log_write(0, LOG_MAIN|LOG_PANIC, "Too many recipients needed: %d not satisfiable", recipients_list_max); + } recipients_list = store_get(recipients_list_max * sizeof(recipient_item), FALSE); if (oldlist) memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item)); -- cgit v1.2.3 From 518f0a0dd6df6f0d0ea51bfa126982d134e7a7ff Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 22:40:59 -0400 Subject: SECURITY: fix SMTP verb option parsing A boundary case in looking for an opening quote before the closing quote could walk off the front of the buffer. (cherry picked from commit 515d8d43a18481d23d7cf410b8dc71b4e254ebb8) (cherry picked from commit 467948de0c407bd2bbc2e84abbbf09f35b035538) --- doc/doc-txt/ChangeLog | 3 +++ src/src/smtp_in.c | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 3d0e638d2..9837d6c0f 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -285,6 +285,9 @@ PP/09 Fix security issue with too many recipients on a message (to remove a or if local additions add to the recipient list). Fixes CVE-2020-RCPTL reported by Qualys. +PP/10 Fix security issue in SMTP verb option parsing + Fixes CVE-2020-EXOPT reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index d60e7d5c5..4f16fd4b8 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1969,12 +1969,13 @@ extract_option(uschar **name, uschar **value) uschar *n; uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1; while (isspace(*v)) v--; -v[1] = 0; +v[1] = '\0'; while (v > smtp_cmd_data && *v != '=' && !isspace(*v)) { /* Take care to not stop at a space embedded in a quoted local-part */ - if (*v == '"') do v--; while (*v != '"' && v > smtp_cmd_data+1); + if ((*v == '"') && (v > smtp_cmd_data + 1)) + do v--; while (*v != '"' && v > smtp_cmd_data+1); v--; } -- cgit v1.2.3 From 36771878fa93a04ecf5bdd71ad3c3c380a16aa03 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Thu, 29 Oct 2020 23:21:36 -0400 Subject: SECURITY: rework BDAT receive function handling (cherry picked from commit dd1b9b753bb7c42df2b8f48d726b82928b67940b) (cherry picked from commit 96fb195ebc2eb6790e6ad6dde46d478aee62198d) --- doc/doc-txt/ChangeLog | 6 +++++ src/src/globals.c | 1 + src/src/smtp_in.c | 67 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 19 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 9837d6c0f..0e008c985 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -288,6 +288,12 @@ PP/09 Fix security issue with too many recipients on a message (to remove a PP/10 Fix security issue in SMTP verb option parsing Fixes CVE-2020-EXOPT reported by Qualys. +PP/11 Fix security issue in BDAT state confusion. + Ensure we reset known-good where we know we need to not be reading BDAT + data, as a general case fix, and move the places where we switch to BDAT + mode until after various protocol state checks. + Fixes CVE-2020-BDATA reported by Qualys. + Exim version 4.94 ----------------- diff --git a/src/src/globals.c b/src/src/globals.c index bd874a789..e1837b67d 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -227,6 +227,7 @@ struct global_flags f = .authentication_local = FALSE, .background_daemon = TRUE, + .bdat_readers_wanted = FALSE, .chunking_offered = FALSE, .config_changed = FALSE, diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 4f16fd4b8..eb032bb52 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -624,9 +624,7 @@ for(;;) if (chunking_data_left > 0) return lwr_receive_getc(chunking_data_left--); - receive_getc = lwr_receive_getc; - receive_getbuf = lwr_receive_getbuf; - receive_ungetc = lwr_receive_ungetc; + bdat_pop_receive_functions(); #ifndef DISABLE_DKIM dkim_save = dkim_collect_input; dkim_collect_input = 0; @@ -730,9 +728,7 @@ next_cmd: goto repeat_until_rset; } - receive_getc = bdat_getc; - receive_getbuf = bdat_getbuf; /* r~getbuf is never actually used */ - receive_ungetc = bdat_ungetc; + bdat_push_receive_functions(); #ifndef DISABLE_DKIM dkim_collect_input = dkim_save; #endif @@ -765,9 +761,7 @@ while (chunking_data_left) if (!bdat_getbuf(&n)) break; } -receive_getc = lwr_receive_getc; -receive_getbuf = lwr_receive_getbuf; -receive_ungetc = lwr_receive_ungetc; +bdat_pop_receive_functions(); if (chunking_state != CHUNKING_LAST) { @@ -777,7 +771,35 @@ if (chunking_state != CHUNKING_LAST) } +void +bdat_push_receive_functions(void) +{ +/* push the current receive_* function on the "stack", and +replace them by bdat_getc(), which in turn will use the lwr_receive_* +functions to do the dirty work. */ +if (lwr_receive_getc == NULL) + { + lwr_receive_getc = receive_getc; + lwr_receive_getbuf = receive_getbuf; + lwr_receive_ungetc = receive_ungetc; + } +else + { + DEBUG(D_receive) debug_printf("chunking double-push receive functions\n"); + } +receive_getc = bdat_getc; +receive_ungetc = bdat_ungetc; +} + +void +bdat_pop_receive_functions(void) +{ +receive_getc = lwr_receive_getc; +receive_getbuf = lwr_receive_getbuf; +receive_ungetc = lwr_receive_ungetc; +lwr_receive_getc = lwr_receive_getbuf = lwr_receive_ungetc = NULL; +} /************************************************* * SMTP version of ungetc() * @@ -2528,6 +2550,7 @@ receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; receive_smtp_buffered = smtp_buffered; +lwr_receive_getc = lwr_receive_getbuf = lwr_receive_ungetc = NULL; smtp_inptr = smtp_inend = smtp_inbuffer; smtp_had_eof = smtp_had_error = 0; @@ -3954,6 +3977,14 @@ cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE; cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = TRUE; #endif +if (lwr_receive_getc != NULL) + { + /* This should have already happened, but if we've gotten confused, + force a reset here. */ + DEBUG(D_receive) debug_printf("WARNING: smtp_setup_msg had to restore receive functions to lowers\n"); + bdat_pop_receive_functions(); + } + /* Set the local signal handler for SIGTERM - it tries to end off tidily */ had_command_sigterm = 0; @@ -5288,16 +5319,7 @@ while (done <= 0) DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n", (int)chunking_state, chunking_data_left); - /* push the current receive_* function on the "stack", and - replace them by bdat_getc(), which in turn will use the lwr_receive_* - functions to do the dirty work. */ - lwr_receive_getc = receive_getc; - lwr_receive_getbuf = receive_getbuf; - lwr_receive_ungetc = receive_ungetc; - - receive_getc = bdat_getc; - receive_ungetc = bdat_ungetc; - + f.bdat_readers_wanted = TRUE; f.dot_ends = FALSE; goto DATA_BDAT; @@ -5306,6 +5328,7 @@ while (done <= 0) case DATA_CMD: HAD(SCH_DATA); f.dot_ends = TRUE; + f.bdat_readers_wanted = FALSE DATA_BDAT: /* Common code for DATA and BDAT */ #ifndef DISABLE_PIPE_CONNECT @@ -5334,7 +5357,10 @@ while (done <= 0) : US"valid RCPT command must precede BDAT"); if (chunking_state > CHUNKING_OFFERED) + { + bdat_push_receive_functions(); bdat_flush_data(); + } break; } @@ -5373,6 +5399,9 @@ while (done <= 0) } } + if (f.bdat_readers_wanted) + bdat_push_receive_functions(); + if (user_msg) smtp_user_msg(US"354", user_msg); else -- cgit v1.2.3 From 40b8be2e25abb7569a05c839f5d0ab6176307a75 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Sat, 21 Nov 2020 22:41:28 +0100 Subject: SECURITY: Fix safeguard against upward traversal in msglog files. 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) (cherry picked from commit 1e9a340c05d7233969637095a8a6378b14de2976) --- doc/doc-txt/ChangeLog | 2 ++ src/src/deliver.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 0e008c985..313dcbf7e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -294,6 +294,8 @@ PP/11 Fix security issue in BDAT state confusion. mode until after various protocol state checks. Fixes CVE-2020-BDATA reported by Qualys. +HS/03 Die on "/../" in msglog file names + Exim version 4.94 ----------------- diff --git a/src/src/deliver.c b/src/src/deliver.c index ba2948dfd..cf8ab09eb 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -334,7 +334,7 @@ static int open_msglog_file(uschar *filename, int mode, uschar **error) { if (Ustrstr(filename, US"/../")) - log_write(0, LOG_MAIN|LOG_PANIC, + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Attempt to open msglog file path with upward-traversal: '%s'\n", filename); for (int i = 2; i > 0; i--) -- cgit v1.2.3 From 186e99bafcf8dbc53f9a25ea26998cab9b091a62 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Sun, 14 Mar 2021 12:16:57 +0100 Subject: CVE-2020-28008: Assorted attacks in Exim's spool directory 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) (cherry picked from commit b05dc3573f4cd476482374b0ac0393153d344338) --- doc/doc-txt/ChangeLog | 3 ++ src/src/dbfn.c | 116 ++++++++++++++++++++++++++++---------------------- 2 files changed, 68 insertions(+), 51 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 313dcbf7e..4debef807 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -296,6 +296,9 @@ PP/11 Fix security issue in BDAT state confusion. HS/03 Die on "/../" in msglog file names +QS/01 Creation of (database) files in $spool_dir: only uid=0 or the euid of + the Exim runtime user are allowed to create files. + Exim version 4.94 ----------------- diff --git a/src/src/dbfn.c b/src/src/dbfn.c index 0f56ad5a6..b66d4603f 100644 --- a/src/src/dbfn.c +++ b/src/src/dbfn.c @@ -65,6 +65,66 @@ log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg); +static enum { + PRIV_DROPPING, PRIV_DROPPED, + PRIV_RESTORING, PRIV_RESTORED +} priv_state = PRIV_RESTORED; + +static uid_t priv_euid; +static gid_t priv_egid; +static gid_t priv_groups[EXIM_GROUPLIST_SIZE + 1]; +static int priv_ngroups; + +/* Inspired by OpenSSH's temporarily_use_uid(). Thanks! */ + +static void +priv_drop_temp(const uid_t temp_uid, const gid_t temp_gid) +{ +if (priv_state != PRIV_RESTORED) _exit(EXIT_FAILURE); +priv_state = PRIV_DROPPING; + +priv_euid = geteuid(); +if (priv_euid == root_uid) + { + priv_egid = getegid(); + priv_ngroups = getgroups(nelem(priv_groups), priv_groups); + if (priv_ngroups < 0) _exit(EXIT_FAILURE); + + if (priv_ngroups > 0 && setgroups(1, &temp_gid) != 0) _exit(EXIT_FAILURE); + if (setegid(temp_gid) != 0) _exit(EXIT_FAILURE); + if (seteuid(temp_uid) != 0) _exit(EXIT_FAILURE); + + if (geteuid() != temp_uid) _exit(EXIT_FAILURE); + if (getegid() != temp_gid) _exit(EXIT_FAILURE); + } + +priv_state = PRIV_DROPPED; +} + +/* Inspired by OpenSSH's restore_uid(). Thanks! */ + +static void +priv_restore(void) +{ +if (priv_state != PRIV_DROPPED) _exit(EXIT_FAILURE); +priv_state = PRIV_RESTORING; + +if (priv_euid == root_uid) + { + if (seteuid(priv_euid) != 0) _exit(EXIT_FAILURE); + if (setegid(priv_egid) != 0) _exit(EXIT_FAILURE); + if (priv_ngroups > 0 && setgroups(priv_ngroups, priv_groups) != 0) _exit(EXIT_FAILURE); + + if (geteuid() != priv_euid) _exit(EXIT_FAILURE); + if (getegid() != priv_egid) _exit(EXIT_FAILURE); + } + +priv_state = PRIV_RESTORED; +} + + + + /************************************************* * Open and lock a database file * *************************************************/ @@ -96,7 +156,6 @@ dbfn_open(uschar *name, int flags, open_db *dbblock, BOOL lof, BOOL panic) { int rc, save_errno; BOOL read_only = flags == O_RDONLY; -BOOL created = FALSE; flock_t lock_data; uschar dirname[PATHLEN], filename[PATHLEN]; @@ -118,12 +177,13 @@ exists, there is no error. */ snprintf(CS dirname, sizeof(dirname), "%s/db", spool_directory); snprintf(CS filename, sizeof(filename), "%s/%s.lockfile", dirname, name); +priv_drop_temp(exim_uid, exim_gid); if ((dbblock->lockfd = Uopen(filename, O_RDWR, EXIMDB_LOCKFILE_MODE)) < 0) { - created = TRUE; (void)directory_make(spool_directory, US"db", EXIMDB_DIRECTORY_MODE, panic); dbblock->lockfd = Uopen(filename, O_RDWR|O_CREAT, EXIMDB_LOCKFILE_MODE); } +priv_restore(); if (dbblock->lockfd < 0) { @@ -172,63 +232,17 @@ it easy to pin this down, there are now debug statements on either side of the open call. */ snprintf(CS filename, sizeof(filename), "%s/%s", dirname, name); -EXIM_DBOPEN(filename, dirname, flags, EXIMDB_MODE, &(dbblock->dbptr)); +priv_drop_temp(exim_uid, exim_gid); +EXIM_DBOPEN(filename, dirname, flags, EXIMDB_MODE, &(dbblock->dbptr)); if (!dbblock->dbptr && errno == ENOENT && flags == O_RDWR) { DEBUG(D_hints_lookup) debug_printf_indent("%s appears not to exist: trying to create\n", filename); - created = TRUE; EXIM_DBOPEN(filename, dirname, flags|O_CREAT, EXIMDB_MODE, &(dbblock->dbptr)); } - save_errno = errno; - -/* If we are running as root and this is the first access to the database, its -files will be owned by root. We want them to be owned by exim. We detect this -situation by noting above when we had to create the lock file or the database -itself. Because the different dbm libraries use different extensions for their -files, I don't know of any easier way of arranging this than scanning the -directory for files with the appropriate base name. At least this deals with -the lock file at the same time. Also, the directory will typically have only -half a dozen files, so the scan will be quick. - -This code is placed here, before the test for successful opening, because there -was a case when a file was created, but the DBM library still returned NULL -because of some problem. It also sorts out the lock file if that was created -but creation of the database file failed. */ - -if (created && geteuid() == root_uid) - { - DIR * dd; - uschar path[PATHLEN]; - uschar *lastname; - int namelen = Ustrlen(name); - - Ustrcpy(path, filename); - lastname = Ustrrchr(path, '/') + 1; - *lastname = 0; - - if ((dd = exim_opendir(path))) - for (struct dirent *ent; ent = readdir(dd); ) - if (Ustrncmp(ent->d_name, name, namelen) == 0) - { - struct stat statbuf; - /* Filenames from readdir() are trusted, - so use a taint-nonchecking copy */ - strcpy(CS lastname, CCS ent->d_name); - if (Ustat(path, &statbuf) >= 0 && statbuf.st_uid != exim_uid) - { - DEBUG(D_hints_lookup) - debug_printf_indent("ensuring %s is owned by exim\n", path); - if (exim_chown(path, exim_uid, exim_gid)) - DEBUG(D_hints_lookup) - debug_printf_indent("failed setting %s to owned by exim\n", path); - } - } - - closedir(dd); - } +priv_restore(); /* If the open has failed, return NULL, leaving errno set. If lof is TRUE, log the event - also for debugging - but debug only if the file just doesn't -- cgit v1.2.3 From c7f4ea442a264b5cb3a9ef0eed641f4778dfb5b7 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Thu, 25 Mar 2021 22:48:09 +0100 Subject: CVE-2020-28014, CVE-2021-27216: PID file handling Arbitrary PID file creation, clobbering, and deletion. Patch provided by Qualys. (cherry picked from commit 974f32939a922512b27d9f0a8a1cb5dec60e7d37) (cherry picked from commit 43c6f0b83200b7082353c50187ef75de3704580a) --- doc/doc-txt/ChangeLog | 5 +- src/src/daemon.c | 169 ++++++++++++++++++++++++++++++++++++++++---------- src/src/exim.c | 4 ++ test/stderr/0433 | 18 ++---- 4 files changed, 149 insertions(+), 47 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 4debef807..adf43bc4b 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -296,9 +296,12 @@ PP/11 Fix security issue in BDAT state confusion. HS/03 Die on "/../" in msglog file names -QS/01 Creation of (database) files in $spool_dir: only uid=0 or the euid of +QS/01 Creation of (database) files in $spool_dir: only uid=0 or the uid of the Exim runtime user are allowed to create files. +QS/02 PID file creation/deletion: only possible if uid=0 or uid is the Exim + runtime user. + Exim version 4.94 ----------------- diff --git a/src/src/daemon.c b/src/src/daemon.c index ed7d30a16..f40a58c75 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -932,7 +932,6 @@ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) } - static void set_pid_file_path(void) { @@ -947,34 +946,144 @@ if (pid_file_path[0] != '/') } -/* Remove the daemon's pidfile. Note: runs with root privilege, -as a direct child of the daemon. Does not return. */ +enum pid_op { PID_WRITE, PID_CHECK, PID_DELETE }; -void -delete_pid_file(void) +/* Do various pid file operations as safe as possible. Ideally we'd just +drop the privileges for creation of the pid file and not care at all about removal of +the file. FIXME. +Returns: true on success, false + errno==EACCES otherwise +*/ +static BOOL +operate_on_pid_file(const enum pid_op operation, const pid_t pid) { -uschar * daemon_pid = string_sprintf("%d\n", (int)getppid()); -FILE * f; +char pid_line[sizeof(int) * 3 + 2]; +const int pid_len = snprintf(pid_line, sizeof(pid_line), "%d\n", (int)pid); +BOOL lines_match = FALSE; + +char * path = NULL; +char * base = NULL; +char * dir = NULL; + +const int dir_flags = O_RDONLY | O_NONBLOCK; +const int base_flags = O_NOFOLLOW | O_NONBLOCK; +const mode_t base_mode = 0644; +struct stat sb; + +int cwd_fd = -1; +int dir_fd = -1; +int base_fd = -1; + +BOOL success = FALSE; +errno = EACCES; set_pid_file_path(); -if ((f = Ufopen(pid_file_path, "rb"))) +if (!f.running_in_test_harness && real_uid != root_uid && real_uid != exim_uid) goto cleanup; +if (pid_len < 2 || pid_len >= (int)sizeof(pid_line)) goto cleanup; + +path = CS string_copy(pid_file_path); +if ((base = Ustrrchr(path, '/')) == NULL) /* should not happen, but who knows */ + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "pid file path \"%s\" does not contain a '/'", pid_file_path); + +dir = (base != path) ? path : "/"; +*base++ = '\0'; + +if (!dir || !*dir || *dir != '/') goto cleanup; +if (!base || !*base || strchr(base, '/') != NULL) goto cleanup; + +cwd_fd = open(".", dir_flags); +if (cwd_fd < 0 || fstat(cwd_fd, &sb) != 0 || !S_ISDIR(sb.st_mode)) goto cleanup; +dir_fd = open(dir, dir_flags); +if (dir_fd < 0 || fstat(dir_fd, &sb) != 0 || !S_ISDIR(sb.st_mode)) goto cleanup; + +/* emulate openat */ +if (fchdir(dir_fd) != 0) goto cleanup; +base_fd = open(base, O_RDONLY | base_flags); +if (fchdir(cwd_fd) != 0) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "can't return to previous working dir: %s", strerror(errno)); + +if (base_fd >= 0) { - if ( fgets(CS big_buffer, big_buffer_size, f) - && Ustrcmp(daemon_pid, big_buffer) == 0 - ) - if (Uunlink(pid_file_path) == 0) + char line[sizeof(pid_line)]; + ssize_t len = -1; + + if (fstat(base_fd, &sb) != 0 || !S_ISREG(sb.st_mode)) goto cleanup; + if ((sb.st_mode & 07777) != base_mode || sb.st_nlink != 1) goto cleanup; + if (sb.st_size < 2 || sb.st_size >= (off_t)sizeof(line)) goto cleanup; + + len = read(base_fd, line, sizeof(line)); + if (len != (ssize_t)sb.st_size) goto cleanup; + line[len] = '\0'; + + if (strspn(line, "0123456789") != (size_t)len-1) goto cleanup; + if (line[len-1] != '\n') goto cleanup; + lines_match = (len == pid_len && strcmp(line, pid_line) == 0); + } + +if (operation == PID_WRITE) + { + if (!lines_match) + { + if (base_fd >= 0) { - DEBUG(D_any) - debug_printf("%s unlink: %s\n", pid_file_path, strerror(errno)); - } - else - DEBUG(D_any) - debug_printf("unlinked %s\n", pid_file_path); - fclose(f); + int error = -1; + /* emulate unlinkat */ + if (fchdir(dir_fd) != 0) goto cleanup; + error = unlink(base); + if (fchdir(cwd_fd) != 0) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "can't return to previous working dir: %s", strerror(errno)); + if (error) goto cleanup; + (void)close(base_fd); + base_fd = -1; + } + /* emulate openat */ + if (fchdir(dir_fd) != 0) goto cleanup; + base_fd = open(base, O_WRONLY | O_CREAT | O_EXCL | base_flags, base_mode); + if (fchdir(cwd_fd) != 0) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "can't return to previous working dir: %s", strerror(errno)); + if (base_fd < 0) goto cleanup; + if (fchmod(base_fd, base_mode) != 0) goto cleanup; + if (write(base_fd, pid_line, pid_len) != pid_len) goto cleanup; + DEBUG(D_any) debug_printf("pid written to %s\n", pid_file_path); + } } else - DEBUG(D_any) - debug_printf("%s\n", string_open_failed("pid file %s", pid_file_path)); + { + if (!lines_match) goto cleanup; + if (operation == PID_DELETE) + { + int error = -1; + /* emulate unlinkat */ + if (fchdir(dir_fd) != 0) goto cleanup; + error = unlink(base); + if (fchdir(cwd_fd) != 0) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "can't return to previous working dir: %s", strerror(errno)); + if (error) goto cleanup; + } + } + +success = TRUE; +errno = 0; + +cleanup: +if (cwd_fd >= 0) (void)close(cwd_fd); +if (dir_fd >= 0) (void)close(dir_fd); +if (base_fd >= 0) (void)close(base_fd); +return success; +} + + +/* Remove the daemon's pidfile. Note: runs with root privilege, +as a direct child of the daemon. Does not return. */ + +void +delete_pid_file(void) +{ +const BOOL success = operate_on_pid_file(PID_DELETE, getppid()); + +DEBUG(D_any) + debug_printf("delete pid file %s %s: %s\n", pid_file_path, + success ? "success" : "failure", strerror(errno)); + exim_exit(EXIT_SUCCESS); } @@ -1841,22 +1950,14 @@ The variable daemon_write_pid is used to control this. */ if (f.running_in_test_harness || write_pid) { - FILE *f; - - set_pid_file_path(); - if ((f = modefopen(pid_file_path, "wb", 0644))) - { - (void)fprintf(f, "%d\n", (int)getpid()); - (void)fclose(f); - DEBUG(D_any) debug_printf("pid written to %s\n", pid_file_path); - } - else - DEBUG(D_any) - debug_printf("%s\n", string_open_failed("pid file %s", pid_file_path)); + const enum pid_op operation = (f.running_in_test_harness + || real_uid == root_uid + || (real_uid == exim_uid && !override_pid_file_path)) ? PID_WRITE : PID_CHECK; + if (!operate_on_pid_file(operation, getpid())) + DEBUG(D_any) debug_printf("%s pid file %s: %s\n", (operation == PID_WRITE) ? "write" : "check", pid_file_path, strerror(errno)); } /* Set up the handler for SIGHUP, which causes a restart of the daemon. */ - sighup_seen = FALSE; signal(SIGHUP, sighup_handler); diff --git a/src/src/exim.c b/src/src/exim.c index abb3ba7c0..49ba9e728 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -3256,6 +3256,10 @@ on the second character (the one after '-'), to save some effort. */ -oPX: delete pid file of daemon */ case 'P': + if (!f.running_in_test_harness && real_uid != root_uid && real_uid != exim_uid) + exim_fail("exim: only uid=%d or uid=%d can use -oP and -oPX " + "(uid=%d euid=%d | %d)\n", + root_uid, exim_uid, getuid(), geteuid(), real_uid); if (!*argrest) override_pid_file_path = argv[++i]; else if (Ustrcmp(argrest, "X") == 0) delete_pid_file(); else badarg = TRUE; diff --git a/test/stderr/0433 b/test/stderr/0433 index b36788373..3d0e9e9f8 100644 --- a/test/stderr/0433 +++ b/test/stderr/0433 @@ -18,9 +18,8 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -42,9 +41,8 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 port 1226 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -67,9 +65,8 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on [127.0.0.1]:1228 port 1225 (IPv4) port 1226 (IPv4) daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -92,9 +89,8 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 port 1226 [127.0.0.1]:1228 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 0.0.0.0; 127.0.0.1.1228 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 0.0.0.0; 127.0.0.1.1228 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -118,9 +114,8 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on [127.0.0.1]:1228 port 1227 (IPv4) daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -DPORT=daemon_smtp_port=1225:1226 -DIFACE=local_interfaces = <; 127.0.0.1.1228 ; 0.0.0.0 -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... @@ -144,8 +139,7 @@ LOG: MAIN set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225 port 1226 daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID Listening... -SIGTERM seen -pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX SIGTERM/SIGINT seen +pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -MCd daemon-del-pidfile -oP TESTSUITE/spool/exim-daemon.pid -oPX search_tidyup called >>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>> -- cgit v1.2.3 From e4e3d18dad8b9b8560889f552e1060d0f83c7159 Mon Sep 17 00:00:00 2001 From: Qualys Security Advisory Date: Sun, 21 Feb 2021 21:53:55 -0800 Subject: CVE-2020-28012: Missing close-on-exec flag for privileged pipe (cherry picked from commit 72dad1e64bb3d1ff387938f59678098cab1f60a3) (cherry picked from commit 645a31d16195bb6b73f0a0d0c04b2251e5b28421) --- doc/doc-txt/ChangeLog | 3 +++ src/src/rda.c | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index adf43bc4b..bcace272d 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -302,6 +302,9 @@ QS/01 Creation of (database) files in $spool_dir: only uid=0 or the uid of QS/02 PID file creation/deletion: only possible if uid=0 or uid is the Exim runtime user. +QS/03 When reading the output from interpreted forward files we do not + pass the pipe between the parent and the interpreting process to + executed child processes (if any). Exim version 4.94 ----------------- diff --git a/src/src/rda.c b/src/src/rda.c index 5615b64d5..fb3714ea2 100644 --- a/src/src/rda.c +++ b/src/src/rda.c @@ -618,9 +618,14 @@ search_tidyup(); if ((pid = exim_fork(US"router-interpret")) == 0) { header_line *waslast = header_last; /* Save last header */ + int fd_flags = -1; fd = pfd[pipe_write]; (void)close(pfd[pipe_read]); + + if ((fd_flags = fcntl(fd, F_GETFD)) == -1) goto bad; + if (fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC) == -1) goto bad; + exim_setugid(ugid->uid, ugid->gid, FALSE, rname); /* Addresses can get rewritten in filters; if we are not root or the exim -- cgit v1.2.3 From 6f97d821f13060b234c3d272d7672558bb2365ae Mon Sep 17 00:00:00 2001 From: Qualys Security Advisory Date: Sun, 21 Feb 2021 22:09:06 -0800 Subject: SECURITY: Always exit when LOG_PANIC_DIE is set (cherry picked from commit e20aa895b37f449d5c81c3e7b102fc534b5d23ba) (cherry picked from commit 3b8c0ceb7339329188e19efb907da950dbe691d1) --- doc/doc-txt/ChangeLog | 4 ++++ src/src/log.c | 1 + 2 files changed, 5 insertions(+) (limited to 'doc') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index bcace272d..a5bce7e81 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -306,6 +306,10 @@ QS/03 When reading the output from interpreted forward files we do not pass the pipe between the parent and the interpreting process to executed child processes (if any). +QS/04 Always die if requested from internal logging, even is logging is + disabled. + + Exim version 4.94 ----------------- diff --git a/src/src/log.c b/src/src/log.c index 2cf578069..6e35ff9a7 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -903,6 +903,7 @@ if (!(flags & (LOG_MAIN|LOG_PANIC|LOG_REJECT))) if (f.disable_logging) { DEBUG(D_any) debug_printf("log writing disabled\n"); + if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE); return; } -- cgit v1.2.3 From 9370c62082c6596c3eaf5dcf6c0b29cf002bd321 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Wed, 21 Apr 2021 07:52:39 +0200 Subject: Update upgrade notes and source about use of seteuid() (cherry picked from commit bc13bbca6e07267dfe0c4d275bb0a2e9aabf1dfb) (cherry picked from commit fee1a06ec05e58e0cda8cf04f28240688736f945) --- doc/doc-txt/Exim4.upgrade | 18 +++++++++++------- src/src/deliver.c | 6 +++--- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'doc') diff --git a/doc/doc-txt/Exim4.upgrade b/doc/doc-txt/Exim4.upgrade index 528d94d9c..86d4a4dda 100644 --- a/doc/doc-txt/Exim4.upgrade +++ b/doc/doc-txt/Exim4.upgrade @@ -468,11 +468,12 @@ Generic Router Options . The way that require_files works has been changed. Each item in the list is now separately expanded as the test proceeds. The use of leading ! and + characters is unchanged. However, user and group checking is done differently. - Previously, seteuid() was used, but seteuid() is no longer used in Exim (see - "Security" below). Instead, Exim now scans along the components of the file - path and checks the access for the given uid and gid. It expects "x" access - on directories and "r" on the final file. This means that file access control - lists (on those operating systems that have them) are ignored. + Previously, seteuid() was used, but seteuid() is no longer used (see + "Security" below) for checking the files required by this option. Instead, + Exim now scans along the components of the file path and checks the access + for the given uid and gid. It expects "x" access on directories and "r" on + the final file. This means that file access control lists (on those + operating systems that have them) are ignored. Other Consequences of the Director/Router Merge @@ -1380,8 +1381,11 @@ Security -------- Exim 3 could be run in a variety of ways as far as security was concerned. This -has all been simplified in Exim 4. The security-conscious might like to know -that it no longer makes any use of the seteuid() function. +has all been simplified in Exim 4. Exim dropped the use of seteuid() in +most places. But recent (2020-10/2021-04) vulnerabilities forced us to +re-introduce seteuid() for opening the database files (hint files) as secure as +possible. For future (>= 4.95) versions we work on a solution that +does not need the seteuid call. . A UID and GID are required to be specified when Exim is compiled. They can be now specified by name as well as by number, so the relevant options are now diff --git a/src/src/deliver.c b/src/src/deliver.c index cf8ab09eb..4e472ebe6 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -2097,9 +2097,9 @@ return FALSE; /* Each local delivery is performed in a separate process which sets its uid and gid as specified. This is a safer way than simply changing and -restoring using seteuid(); there is a body of opinion that seteuid() cannot be -used safely. From release 4, Exim no longer makes any use of it. Besides, not -all systems have seteuid(). +restoring using seteuid(); there is a body of opinion that seteuid() +cannot be used safely. From release 4, Exim no longer makes any use of +it for delivery. Besides, not all systems have seteuid(). If the uid/gid are specified in the transport_instance, they are used; the transport initialization must ensure that either both or neither are set. -- cgit v1.2.3 From b2e302203ed3d40b70185bbf283c053f58934174 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Mon, 26 Apr 2021 18:54:28 +0200 Subject: Cleanup docs on cve-2020-qualys, point to the Exim website (cherry picked from commit 6429b0fc79595f120703c022ae99aa10d698f909) --- doc/doc-txt/cve-2020-qualys | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 doc/doc-txt/cve-2020-qualys (limited to 'doc') diff --git a/doc/doc-txt/cve-2020-qualys b/doc/doc-txt/cve-2020-qualys new file mode 100644 index 000000000..d5716444d --- /dev/null +++ b/doc/doc-txt/cve-2020-qualys @@ -0,0 +1,2 @@ +For the vulnerabilites reported by Qualys in October 2020 please see the +Exim Website: https://exim.org/static/doc/security/CVE-2020-qualys/ -- cgit v1.2.3