From cd25e41d2d044556e024f0292a17c5ec3cc7987b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 11 Dec 2010 23:39:54 +0000 Subject: [PATCH] Remove ALT_CONFIG_ROOT_ONLY build option, effectively making it always true. We *never* want the Exim user to be able to specify arbitrary configuration files. Don't let them build it that way. (Bug 1044, CVE-2010-4345) --- doc/doc-docbook/spec.xfpt | 80 +++++++++++++++++---------------------- doc/doc-txt/ChangeLog | 3 ++ src/src/EDITME | 32 +++++----------- src/src/config.h.defaults | 1 - src/src/exim.c | 39 ++++++------------- 5 files changed, 59 insertions(+), 96 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 049b2b6b0..578485ddd 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -3331,25 +3331,17 @@ name, but it can be a colon-separated list of names. In this case, the first file that exists is used. Failure to open an existing file stops Exim from proceeding any further along the list, and an error is generated. -When this option is used by a caller other than root or the Exim user, and the -list is different from the compiled-in list, Exim gives up its root privilege -immediately, and runs with the real and effective uid and gid set to those of -the caller. However, if ALT_CONFIG_ROOT_ONLY is defined in -&_Local/Makefile_&, root privilege is retained for &%-C%& only if the caller of -Exim is root. - -That is, the Exim user is no longer privileged in this regard. This build-time -option is not set by default in the Exim source distribution tarbundle. -However, if you are using a &"packaged"& version of Exim (source or binary), -the packagers might have enabled it. - -Setting ALT_CONFIG_ROOT_ONLY locks out the possibility of testing a -configuration using &%-C%& right through message reception and delivery, even -if the caller is root. The reception works, but by that time, Exim is running -as the Exim user, so when it re-executes to regain privilege for the delivery, -the use of &%-C%& causes privilege to be lost. However, root can test reception -and delivery using two separate commands (one to put a message on the queue, -using &%-odq%&, and another to do the delivery, using &%-M%&). +When this option is used by a caller other than root, and the list is different +from the compiled-in list, Exim gives up its root privilege immediately, and +runs with the real and effective uid and gid set to those of the caller. + +This behaviour precludes the possibility of testing a configuration using +&%-C%& right through message reception and delivery, even if the caller is +root. The reception works, but by that time, Exim is running as the Exim user, +so when it re-executes to regain privilege for the delivery, the use of &%-C%& +causes privilege to be lost. However, root can test reception and delivery +using two separate commands (one to put a message on the queue, using &%-odq%&, +and another to do the delivery, using &%-M%&). If ALT_CONFIG_PREFIX is defined &_in Local/Makefile_&, it specifies a prefix string with which any file named in a &%-C%& command line option @@ -4531,21 +4523,21 @@ configuration. .cindex "configuration file" "alternate" A one-off alternate configuration can be specified by the &%-C%& command line option, which may specify a single file or a list of files. However, when -&%-C%& is used, Exim gives up its root privilege, unless called by root or the -Exim user (or unless the argument for &%-C%& is identical to the built-in value -from CONFIGURE_FILE). &%-C%& is useful mainly for checking the syntax of +&%-C%& is used, Exim gives up its root privilege, unless called by root (or +unless the argument for &%-C%& is identical to the built-in value from +CONFIGURE_FILE). &%-C%& is useful mainly for checking the syntax of configuration files before installing them. No owner or group checks are done on a configuration file specified by &%-C%&. -The privileged use of &%-C%& by the Exim user can be locked out by setting -ALT_CONFIG_ROOT_ONLY in &_Local/Makefile_& when building Exim. However, -if you do this, you also lock out the possibility of testing a -configuration using &%-C%& right through message reception and delivery, even -if the caller is root. The reception works, but by that time, Exim is running -as the Exim user, so when it re-execs to regain privilege for the delivery, the -use of &%-C%& causes privilege to be lost. However, root can test reception and -delivery using two separate commands (one to put a message on the queue, using -&%-odq%&, and another to do the delivery, using &%-M%&). +The Exim user is not trusted to specify an arbitrary configuration file with +the &%-C%& option to be executed with root privileges. This locks out the +possibility of testing a configuration using &%-C%& right through message +reception and delivery, even if the caller is root. The reception works, but +by that time, Exim is running as the Exim user, so when it re-execs to regain +privilege for the delivery, the use of &%-C%& causes privilege to be lost. +However, root can test reception and delivery using two separate commands +(one to put a message on the queue, using &%-odq%&, and another to do the +delivery, using &%-M%&). If ALT_CONFIG_PREFIX is defined &_in Local/Makefile_&, it specifies a prefix string with which any file named in a &%-C%& command line option must @@ -33805,15 +33797,14 @@ which only root has access, this guards against someone who has broken into the Exim account from running a privileged Exim with an arbitrary configuration file, and using it to break into other accounts. .next -If ALT_CONFIG_ROOT_ONLY is defined, root privilege is retained for &%-C%& -and &%-D%& only if the caller of Exim is root. Without it, the Exim user may -also use &%-C%& and &%-D%& and retain privilege. Setting this option locks out -the possibility of testing a configuration using &%-C%& right through message -reception and delivery, even if the caller is root. The reception works, but by -that time, Exim is running as the Exim user, so when it re-execs to regain -privilege for the delivery, the use of &%-C%& causes privilege to be lost. -However, root can test reception and delivery using two separate commands. -ALT_CONFIG_ROOT_ONLY is not set by default. +If a non-default configuration file is specified with &%-C%&, or macros are +given with &%-D%&, then root privilege is retained only if the caller of Exim +is root. This locks out the possibility of testing a configuration using &%-C%& +right through message reception and delivery, even if the caller is root. The +reception works, but by that time, Exim is running as the Exim user, so when +it re-execs to regain privilege for the delivery, the use of &%-C%& causes +privilege to be lost. However, root can test reception and delivery using two +separate commands. .next If DISABLE_D_OPTION is defined, the use of the &%-D%& command line option is disabled. @@ -33869,11 +33860,10 @@ uid and gid in the following cases: .oindex "&%-D%&" If the &%-C%& option is used to specify an alternate configuration file, or if the &%-D%& option is used to define macro values for the configuration, and the -calling process is not running as root or the Exim user, the uid and gid are -changed to those of the calling process. -However, if ALT_CONFIG_ROOT_ONLY is defined in &_Local/Makefile_&, only -root callers may use &%-C%& and &%-D%& without losing privilege, and if -DISABLE_D_OPTION is set, the &%-D%& option may not be used at all. +calling process is not running as root, the uid and gid are changed to those of + the calling process. +However, if DISABLE_D_OPTION is defined in &_Local/Makefile_&, the &%-D%& +option may not be used at all. .next .oindex "&%-be%&" .oindex "&%-bf%&" diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 0063c6be0..afc854e44 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -83,6 +83,9 @@ DW/23 Bugzilla 1044: CVE-2010-4345 - part two: extend checks for writeability they are going to be used with root privileges, not just the default configuration file. +DW/24 Bugzilla 1044: CVE-2010-4345 - part three: remove ALT_CONFIG_ROOT_ONLY + option (effectively making it always true). + Exim version 4.72 ----------------- diff --git a/src/src/EDITME b/src/src/EDITME index 285e5b656..f8ba7cfe3 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -458,34 +458,20 @@ FIXED_NEVER_USERS=root #------------------------------------------------------------------------------ # The -C option allows Exim to be run with an alternate runtime configuration -# file. When this is used by root or the Exim user, root privilege is retained -# by the binary (for any other caller, it is dropped). You can restrict the -# location of alternate configurations by defining a prefix below. Any file -# used with -C must then start with this prefix (except that /dev/null is also -# permitted if the caller is root, because that is used in the install script). -# If the prefix specifies a directory that is owned by root, a compromise of -# the Exim account does not permit arbitrary alternate configurations to be -# used. The prefix can be more restrictive than just a directory (the second -# example). +# file. When this is used by root, root privilege is retained by the binary +# (for any other caller including the Exim user, it is dropped). You can +# restrict the location of alternate configurations by defining a prefix below. +# Any file used with -C must then start with this prefix (except that /dev/null +# is also permitted if the caller is root, because that is used in the install +# script). If the prefix specifies a directory that is owned by root, a +# compromise of the Exim account does not permit arbitrary alternate +# configurations to be used. The prefix can be more restrictive than just a +# directory (the second example). # ALT_CONFIG_PREFIX=/some/directory/ # ALT_CONFIG_PREFIX=/some/directory/exim.conf- -#------------------------------------------------------------------------------ -# If you uncomment the following line, only root may use the -C or -D options -# without losing root privilege. The -C option specifies an alternate runtime -# configuration file, and the -D option changes macro values in the runtime -# configuration. Uncommenting this line restricts what can be done with these -# options. A call to receive a message (either one-off or via a daemon) cannot -# successfully continue to deliver it, because the re-exec of Exim to regain -# root privilege will fail, owing to the use of -C or -D by the Exim user. -# However, you can still use -C for testing (as root) if you do separate Exim -# calls for receiving a message and subsequently delivering it. - -# ALT_CONFIG_ROOT_ONLY=yes - - #------------------------------------------------------------------------------ # Uncommenting this option disables the use of the -D command line option, # which changes the values of macros in the runtime configuration file. diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 9f0eba0fe..9e4556e8c 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -13,7 +13,6 @@ in config.h unless some value is defined in Local/Makefile. If there is data, it's a default value. */ #define ALT_CONFIG_PREFIX -#define ALT_CONFIG_ROOT_ONLY #define APPENDFILE_MODE 0600 #define APPENDFILE_DIRECTORY_MODE 0700 diff --git a/src/src/exim.c b/src/src/exim.c index 0d8f24492..0d9378d46 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -3031,11 +3031,11 @@ if (setgroups(0, NULL) != 0) /* If the configuration file name has been altered by an argument on the command line (either a new file name or a macro definition) and the caller is -not root or the exim user, or if this is a filter testing run, remove any -setuid privilege the program has, and run as the underlying user. +not root, or if this is a filter testing run, remove any setuid privilege the +program has and run as the underlying user. -If ALT_CONFIG_ROOT_ONLY is defined, the exim user is locked out of this, which -severely restricts the use of -C for some purposes. +The exim user is locked out of this, which severely restricts the use of -C +for some purposes. Otherwise, set the real ids to the effective values (should be root unless run from inetd, which it can either be root or the exim uid, if one is configured). @@ -3049,9 +3049,6 @@ configuration file changes and macro definitions haven't happened. */ if (( /* EITHER */ (!trusted_config || macros != NULL) && /* Config changed, and */ real_uid != root_uid && /* Not root, and */ - #ifndef ALT_CONFIG_ROOT_ONLY /* (when not locked out) */ - real_uid != exim_uid && /* Not exim, and */ - #endif !running_in_test_harness /* Not fudged */ ) || /* OR */ expansion_test /* expansion testing */ @@ -3239,15 +3236,12 @@ else } /* Handle the case when we have removed the setuid privilege because of -C or --D. This means that the caller of Exim was not root, and, provided that -ALT_CONFIG_ROOT_ONLY is not defined, was not the Exim user that is built into -the binary. +-D. This means that the caller of Exim was not root. -If ALT_CONFIG_ROOT_ONLY is not defined, there is a problem if it turns out we -were running as the exim user defined in the configuration file (different to -the one in the binary). The sysadmin may expect this case to retain privilege -because "the binary was called by the Exim user", but it hasn't, because of the -order in which it handles this stuff. There are two possibilities: +There is a problem if we were running as the Exim user. The sysadmin may +expect this case to retain privilege because "the binary was called by the +Exim user", but it hasn't, because either the -D option set macros, or the +-C option set a non-default configuration file. There are two possibilities: (1) If deliver_drop_privilege is set, Exim is not going to re-exec in order to do message deliveries. Thus, the fact that it is running as a @@ -3259,27 +3253,18 @@ order in which it handles this stuff. There are two possibilities: (2) If deliver_drop_privilege is not set, the configuration won't work as apparently intended, and so we log a panic message. In order to retain - root for -C or -D, the caller must either be root or the Exim user - defined in the binary (when deliver_drop_ privilege is false). - -If ALT_CONFIG_ROOT_ONLY is defined, we don't know whether we were called by the -built-in exim user or one defined in the configuration. In either event, -re-enable log processing, assuming the sysadmin knows what they are doing. */ + root for -C or -D, the caller must be root (when deliver_drop_privilege + is false). */ if (removed_privilege && (!trusted_config || macros != NULL) && real_uid == exim_uid) { - #ifdef ALT_CONFIG_ROOT_ONLY - really_exim = TRUE; /* let logging work normally */ - #else - if (deliver_drop_privilege) really_exim = TRUE; /* let logging work normally */ else log_write(0, LOG_MAIN|LOG_PANIC, - "exim user (uid=%d) is defined only at runtime; privilege lost for %s", + "exim user lost privilege for using %s option", (int)exim_uid, trusted_config? "-D" : "-C"); - #endif } /* Start up Perl interpreter if Perl support is configured and there is a -- 2.30.2