CVE backports, first pass

This commit is contained in:
Mark Chappell 2011-05-18 21:58:25 +02:00
parent 22e399dd1c
commit ca973f1732
10 changed files with 826 additions and 1 deletions

View File

@ -0,0 +1,35 @@
From 519e7d3b8bef1e1de255c5926e49d03545c3f0bb Mon Sep 17 00:00:00 2001
From: Phil Pennock <pdp@exim.org>
Date: Tue, 12 Apr 2011 04:24:12 -0400
Subject: [PATCH 01/13] Catch divide-by-zero in ${eval:...}.
Fixes 1102
---
src/src/expand.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/src/src/expand.c b/src/src/expand.c
index 6e47125..a0d967d 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -3074,7 +3074,16 @@ if (*error == NULL)
int y = eval_op_unary(&s, decimal, error);
if (*error != NULL) break;
if (op == '*') x *= y;
- else if (op == '/') x /= y;
+ else if (op == '/')
+ {
+ if (y == 0)
+ {
+ *error = US"divide by zero";
+ x = 0;
+ break;
+ }
+ x /= y;
+ }
else x %= y;
}
}
--
1.7.1

View File

@ -0,0 +1,49 @@
From d84c166641a5c0a460a53cbbb117c7fe3f41e9c2 Mon Sep 17 00:00:00 2001
From: Phil Pennock <pdp@exim.org>
Date: Tue, 12 Apr 2011 16:26:44 -0400
Subject: [PATCH 02/13] Also ${eval:x % 0} fixed to not SIGFPE.
Pointed out by: Steven A. Reisman
---
src/src/expand.c | 23 +++++++++++++----------
1 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/src/src/expand.c b/src/src/expand.c
index a0d967d..a96da27 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -3073,18 +3073,21 @@ if (*error == NULL)
int op = *s++;
int y = eval_op_unary(&s, decimal, error);
if (*error != NULL) break;
- if (op == '*') x *= y;
- else if (op == '/')
+ if (op == '*')
+ x *= y;
+ else
+ {
+ if (y == 0)
{
- if (y == 0)
- {
- *error = US"divide by zero";
- x = 0;
- break;
- }
- x /= y;
+ *error = (op == '/') ? US"divide by zero" : US"modulo by zero";
+ x = 0;
+ break;
}
- else x %= y;
+ if (op == '/')
+ x /= y;
+ else
+ x %= y;
+ }
}
}
*sptr = s;
--
1.7.1

View File

@ -0,0 +1,34 @@
From cca8361d074b4d1f1a24143ee79a3bf045781062 Mon Sep 17 00:00:00 2001
From: Tom Kistner <tom@tahini.csx.cam.ac.uk>
Date: Sat, 30 Apr 2011 13:20:17 +0100
Subject: [PATCH 03/13] Bugzilla #1106: Don't pass DKIM compound log line as format string
---
src/src/dkim.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/src/dkim.c b/src/src/dkim.c
index ca46805..94fbaa5 100644
--- a/src/src/dkim.c
+++ b/src/src/dkim.c
@@ -108,7 +108,7 @@ void dkim_exim_verify_finish(void) {
/* Log a line for each signature */
uschar *logmsg = string_append(NULL, &size, &ptr, 5,
- string_sprintf( "DKIM: d=%s s=%s c=%s/%s a=%s ",
+ string_sprintf( "d=%s s=%s c=%s/%s a=%s ",
sig->domain,
sig->selector,
(sig->canon_headers == PDKIM_CANON_SIMPLE)?"simple":"relaxed",
@@ -176,7 +176,7 @@ void dkim_exim_verify_finish(void) {
}
logmsg[ptr] = '\0';
- log_write(0, LOG_MAIN, (char *)logmsg);
+ log_write(0, LOG_MAIN, "DKIM: %s", logmsg);
/* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */
dkim_signers = string_append(dkim_signers,
--
1.7.1

View File

@ -0,0 +1,119 @@
From c69806dd901049cd7828baff79cc0a5d96490e6d Mon Sep 17 00:00:00 2001
From: Phil Pennock <pdp@exim.org>
Date: Fri, 21 Jan 2011 03:56:02 -0500
Subject: [PATCH 04/13] Check return values of setgid/setuid.
CVE-2011-0017
One assertion of the unimportance of checking the return value was wrong,
in the event of a compromised exim run-time user.
---
src/src/exim.c | 41 +++++++++++++++++++++++++++++++++++++----
src/src/log.c | 19 ++++++++++++++-----
2 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/src/exim.c b/src/src/exim.c
index 12916e8..bb39438 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1309,7 +1309,7 @@ int arg_error_handling = error_handling;
int filter_sfd = -1;
int filter_ufd = -1;
int group_count;
-int i;
+int i, rv;
int list_queue_option = 0;
int msg_action = 0;
int msg_action_arg = -1;
@@ -1628,8 +1628,20 @@ real_gid = getgid();
if (real_uid == root_uid)
{
- setgid(real_gid);
- setuid(real_uid);
+ rv = setgid(real_gid);
+ if (rv)
+ {
+ fprintf(stderr, "exim: setgid(%ld) failed: %s\n",
+ (long int)real_gid, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ rv = setuid(real_uid);
+ if (rv)
+ {
+ fprintf(stderr, "exim: setuid(%ld) failed: %s\n",
+ (long int)real_uid, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
}
/* If neither the original real uid nor the original euid was root, Exim is
@@ -3746,7 +3758,28 @@ if (!unprivileged && /* originally had root AND */
/* When we are retaining a privileged uid, we still change to the exim gid. */
-else setgid(exim_gid);
+else
+ {
+ int rv;
+ rv = setgid(exim_gid);
+ /* Impact of failure is that some stuff might end up with an incorrect group.
+ We track this for failures from root, since any attempt to change privilege
+ by root should succeed and failures should be examined. For non-root,
+ there's no security risk. For me, it's { exim -bV } on a just-built binary,
+ no need to complain then. */
+ if (rv == -1)
+ {
+ if (!unprivileged)
+ {
+ fprintf(stderr,
+ "exim: changing group failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ else
+ debug_printf("changing group to %ld failed: %s\n",
+ (long int)exim_gid, strerror(errno));
+ }
+ }
/* Handle a request to list the delivery queue */
diff --git a/src/src/log.c b/src/src/log.c
index a5cd100..ff8f9dd 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -343,17 +343,26 @@ are neither exim nor root, creation is not attempted. */
else if (euid == root_uid)
{
- int status;
+ int status, rv;
pid_t pid = fork();
/* In the subprocess, change uid/gid and do the creation. Return 0 from the
- subprocess on success. There doesn't seem much point in testing for setgid
- and setuid errors. */
+ subprocess on success. If we don't check for setuid failures, then the file
+ can be created as root, so vulnerabilities which cause setuid to fail mean
+ that the Exim user can use symlinks to cause a file to be opened/created as
+ root. We always open for append, so can't nuke existing content but it would
+ still be Rather Bad. */
if (pid == 0)
{
- (void)setgid(exim_gid);
- (void)setuid(exim_uid);
+ rv = setgid(exim_gid);
+ if (rv)
+ die(US"exim: setgid for log-file creation failed, aborting",
+ US"Unexpected log failure, please try later");
+ rv = setuid(exim_uid);
+ if (rv)
+ die(US"exim: setuid for log-file creation failed, aborting",
+ US"Unexpected log failure, please try later");
_exit((create_log(buffer) < 0)? 1 : 0);
}
--
1.7.1

View File

@ -0,0 +1,94 @@
From c0d4b16d16983569141de9052b8c3567f5839a1e Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Sat, 11 Dec 2010 13:44:55 +0000
Subject: [PATCH 05/13] Don't allow a configure file which is writeable by the Exim user or group
(Bug 1044, CVE-2010-4345)
---
src/src/EDITME | 7 +++----
src/src/config.h.defaults | 1 +
src/src/globals.c | 1 +
src/src/globals.h | 1 +
src/src/readconf.c | 5 ++---
6 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/src/src/EDITME b/src/src/EDITME
index 3ee1663..368290c 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -412,14 +412,13 @@ FIXED_NEVER_USERS=root
#------------------------------------------------------------------------------
-# By default, Exim insists that its configuration file be owned either by root
-# or by the Exim user. You can specify one additional permitted owner here.
+# By default, Exim insists that its configuration file be owned by root. You
+# can specify one additional permitted owner here.
# CONFIGURE_OWNER=
# If the configuration file is group-writeable, Exim insists by default that it
-# is owned by root or the Exim user. You can specify one additional permitted
-# group owner here.
+# is owned by root. You can specify one additional permitted group owner here.
# CONFIGURE_GROUP=
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 8bae17b..20ecf0b 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -159,5 +159,6 @@ just in case. */
#define DNS_MAXNAME 1024
#define EXPAND_MAXN 20
#define ROOT_UID 0
+#define ROOT_GID 0
/* End of config.h.defaults */
diff --git a/src/src/globals.c b/src/src/globals.c
index 3e1e76c..7a09b08 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -945,6 +945,7 @@ int rewrite_existflags = 0;
uschar *rfc1413_hosts = US"*";
int rfc1413_query_timeout = 5;
/* BOOL rfc821_domains = FALSE; <<< on the way out */
+uid_t root_gid = ROOT_GID;
uid_t root_uid = ROOT_UID;
router_instance *routers = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index cc5d601..70635c0 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -609,6 +609,7 @@ extern int rewrite_existflags; /* Indicate which headers have rewrites *
extern uschar *rfc1413_hosts; /* RFC hosts */
extern int rfc1413_query_timeout; /* Timeout on RFC 1413 calls */
/* extern BOOL rfc821_domains; */ /* If set, syntax is 821, not 822 => being abolished */
+extern uid_t root_gid; /* The gid for root */
extern uid_t root_uid; /* The uid for root */
extern router_info routers_available[];/* Vector of available routers */
extern router_instance *routers; /* Chain of instantiated routers */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 41fb9f7..a5f32bf 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -2838,13 +2838,12 @@ if (!config_changed)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
big_buffer);
- if ((statbuf.st_uid != root_uid && /* owner not root */
- statbuf.st_uid != exim_uid /* owner not exim */
+ if ((statbuf.st_uid != root_uid /* owner not root */
#ifdef CONFIGURE_OWNER
&& statbuf.st_uid != config_uid /* owner not the special one */
#endif
) || /* or */
- (statbuf.st_gid != exim_gid /* group not exim & */
+ (statbuf.st_gid != root_gid /* group not root & */
#ifdef CONFIGURE_GROUP
&& statbuf.st_gid != config_gid /* group not the special one */
#endif
--
1.7.1

View File

@ -0,0 +1,97 @@
From 8145e5489cd02197b156efd8fefeae986747e05a Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Sat, 11 Dec 2010 14:09:17 +0000
Subject: [PATCH 06/13] Check configure file permissions even for non-default files if still privileged
(Bug 1044, CVE-2010-4345)
---
src/src/exim.c | 7 ++++---
src/src/globals.c | 1 +
src/src/globals.h | 1 +
src/src/readconf.c | 6 +++---
4 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/src/exim.c b/src/src/exim.c
index bb39438..a3af9db 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1989,6 +1989,7 @@ for (i = 1; i < argc; i++)
config_main_filelist = argrest;
config_changed = TRUE;
+ trusted_config = FALSE;
}
break;
@@ -3187,7 +3188,7 @@ values (such as the path name). If running in the test harness, pretend that
configuration file changes and macro definitions haven't happened. */
if (( /* EITHER */
- (config_changed || macros != NULL) && /* Config changed, and */
+ (!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 */
@@ -3406,7 +3407,7 @@ 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. */
-if (removed_privilege && (config_changed || macros != NULL) &&
+if (removed_privilege && (!trusted_config || macros != NULL) &&
real_uid == exim_uid)
{
#ifdef ALT_CONFIG_ROOT_ONLY
@@ -3418,7 +3419,7 @@ if (removed_privilege && (config_changed || macros != NULL) &&
else
log_write(0, LOG_MAIN|LOG_PANIC,
"exim user (uid=%d) is defined only at runtime; privilege lost for %s",
- (int)exim_uid, config_changed? "-C" : "-D");
+ (int)exim_uid, trusted_config? "-D" : "-C");
#endif
}
diff --git a/src/src/globals.c b/src/src/globals.c
index 7a09b08..211b1cd 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1264,6 +1264,7 @@ tree_node *tree_nonrecipients = NULL;
tree_node *tree_unusable = NULL;
BOOL trusted_caller = FALSE;
+BOOL trusted_config = TRUE;
gid_t *trusted_groups = NULL;
uid_t *trusted_users = NULL;
uschar *timezone_string = US TIMEZONE_DEFAULT;
diff --git a/src/src/globals.h b/src/src/globals.h
index 70635c0..fe5b7c3 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -779,6 +779,7 @@ extern tree_node *tree_nonrecipients; /* Tree of nonrecipient addresses */
extern tree_node *tree_unusable; /* Tree of unusable addresses */
extern BOOL trusted_caller; /* Caller is trusted */
+extern BOOL trusted_config; /* Configuration file is trusted */
extern gid_t *trusted_groups; /* List of trusted groups */
extern uid_t *trusted_users; /* List of trusted users */
extern uschar *timezone_string; /* Required timezone setting */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index a5f32bf..d6416c8 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -2829,10 +2829,10 @@ else
"configuration file %s", filename));
}
-/* Check the status of the file we have opened, unless it was specified on
-the command line, in which case privilege was given away at the start. */
+/* Check the status of the file we have opened, if we have retained root
+privileges. */
-if (!config_changed)
+if (trusted_config)
{
if (fstat(fileno(config_file), &statbuf) != 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
--
1.7.1

View File

@ -0,0 +1,160 @@
From 18a77559b0921016e18e80670171d10e3b04e9da Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Sat, 11 Dec 2010 23:39:54 +0000
Subject: [PATCH 07/13] 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)
---
src/src/config.h.defaults | 1 -
src/src/exim.c | 39 +++++++---------------
4 files changed, 56 insertions(+), 96 deletions(-)
diff --git a/src/src/EDITME b/src/src/EDITME
index 368290c..4175b97 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -440,35 +440,21 @@ 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.
# This is another protection against somebody breaking into the Exim account.
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 20ecf0b..f72c292 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 a3af9db..93f27b7 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -3172,11 +3172,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).
@@ -3190,9 +3190,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 */
@@ -3380,15 +3377,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
@@ -3400,27 +3394,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
--
1.7.1

View File

@ -0,0 +1,180 @@
From a47c55346c719d8f1f71f0849b1b4f87a55e3541 Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Sun, 12 Dec 2010 02:41:37 +0000
Subject: [PATCH 08/13] Add TRUSTED_CONFIG_PREFIX_FILE option
(Bug 1044, CVE-2010-4345)
--
src/src/EDITME | 13 +++
src/src/config.h.defaults | 1 +
src/src/exim.c | 101 ++++++++++++++++++++++-
6 files changed, 299 insertions(+), 102 deletions(-)
diff --git a/src/src/EDITME b/src/src/EDITME
index 4175b97..6bfdb7c 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -455,6 +455,19 @@ FIXED_NEVER_USERS=root
#------------------------------------------------------------------------------
+# When a user other than root uses the -C option to override the configuration
+# file (including the Exim user when re-executing Exim to regain root
+# privileges for local message delivery), this will normally cause Exim to
+# drop root privileges. The TRUSTED_CONFIG_PREFIX_LIST option, specifies
+# a file which contains a list of trusted configuration prefixes (like the
+# ALT_CONFIG_PREFIX above), one per line. If the -C option is used to specify
+# a configuration file which matches a trusted prefix, root privileges are not
+# dropped by Exim.
+
+# TRUSTED_CONFIG_PREFIX_LIST=/usr/exim/trusted_configs
+
+
+#------------------------------------------------------------------------------
# Uncommenting this option disables the use of the -D command line option,
# which changes the values of macros in the runtime configuration file.
# This is another protection against somebody breaking into the Exim account.
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index f72c292..a160fef 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -13,6 +13,7 @@ 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 TRUSTED_CONFIG_PREFIX_LIST
#define APPENDFILE_MODE 0600
#define APPENDFILE_DIRECTORY_MODE 0700
diff --git a/src/src/exim.c b/src/src/exim.c
index 93f27b7..1f43898 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1986,10 +1986,103 @@ for (i = 1; i < argc; i++)
}
}
#endif
+ if (real_uid != root_uid)
+ {
+ #ifdef TRUSTED_CONFIG_PREFIX_LIST
+
+ if (Ustrstr(argrest, "/../"))
+ trusted_config = FALSE;
+ else
+ {
+ FILE *trust_list = Ufopen(TRUSTED_CONFIG_PREFIX_LIST, "rb");
+ if (trust_list)
+ {
+ struct stat statbuf;
+
+ if (fstat(fileno(trust_list), &statbuf) != 0 ||
+ (statbuf.st_uid != root_uid /* owner not root */
+ #ifdef CONFIGURE_OWNER
+ && statbuf.st_uid != config_uid /* owner not the special one */
+ #endif
+ ) || /* or */
+ (statbuf.st_gid != root_gid /* group not root */
+ #ifdef CONFIGURE_GROUP
+ && statbuf.st_gid != config_gid /* group not the special one */
+ #endif
+ && (statbuf.st_mode & 020) != 0 /* group writeable */
+ ) || /* or */
+ (statbuf.st_mode & 2) != 0) /* world writeable */
+ {
+ trusted_config = FALSE;
+ fclose(trust_list);
+ }
+ else
+ {
+ /* Well, the trust list at least is up to scratch... */
+ void *reset_point = store_get(0);
+ uschar *trusted_prefixes[32];
+ int nr_prefixes = 0;
+ int i = 0;
+
+ while (Ufgets(big_buffer, big_buffer_size, trust_list))
+ {
+ uschar *start = big_buffer, *nl;
+ while (*start && isspace(*start))
+ start++;
+ if (*start == '#')
+ continue;
+ nl = Ustrchr(start, '\n');
+ if (nl)
+ *nl = 0;
+ trusted_prefixes[nr_prefixes++] = string_copy(start);
+ if (nr_prefixes == 32)
+ break;
+ }
+ fclose(trust_list);
+
+ if (nr_prefixes)
+ {
+ int sep = 0;
+ uschar *list = argrest;
+ uschar *filename;
+ while (trusted_config && (filename = string_nextinlist(&list,
+ &sep, big_buffer, big_buffer_size)) != NULL)
+ {
+ for (i=0; i < nr_prefixes; i++)
+ {
+ int len = Ustrlen(trusted_prefixes[i]);
+ if (Ustrlen(filename) >= len &&
+ Ustrncmp(filename, trusted_prefixes[i], len) == 0)
+ break;
+ }
+ if (i == nr_prefixes)
+ {
+ trusted_config = FALSE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* No valid prefixes found in trust_list file. */
+ trusted_config = FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* Could not open trust_list file. */
+ trusted_config = FALSE;
+ }
+ }
+ #else
+ /* Not root; don't trust config */
+ trusted_config = FALSE;
+ #endif
+ }
config_main_filelist = argrest;
config_changed = TRUE;
- trusted_config = FALSE;
}
break;
@@ -3382,7 +3475,7 @@ else
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:
+-C option set a non-trusted 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
@@ -3394,8 +3487,8 @@ Exim user", but it hasn't, because either the -D option set macros, or the
(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 be root (when deliver_drop_privilege
- is false). */
+ root for -C or -D, the caller must either be root or be invoking a
+ trusted configuration file (when deliver_drop_privilege is false). */
if (removed_privilege && (!trusted_config || macros != NULL) &&
real_uid == exim_uid)
--
1.7.1

View File

@ -0,0 +1,33 @@
From 44badec262804bd3d309de902f1724ef40a79847 Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Sun, 12 Dec 2010 10:18:48 +0000
Subject: [PATCH 09/13] Allow only absolute paths in TRUSTED_CONFIG_PREFIX_LIST, fix store leak
---
src/src/exim.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/src/exim.c b/src/src/exim.c
index 1f43898..cfb85b0 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -2029,7 +2029,7 @@ for (i = 1; i < argc; i++)
uschar *start = big_buffer, *nl;
while (*start && isspace(*start))
start++;
- if (*start == '#')
+ if (*start != '/')
continue;
nl = Ustrchr(start, '\n');
if (nl)
@@ -2061,6 +2061,7 @@ for (i = 1; i < argc; i++)
break;
}
}
+ store_reset(reset_point);
}
else
{
--
1.7.1

View File

@ -12,7 +12,7 @@
Summary: The exim mail transfer agent
Name: exim
Version: 4.72
Release: 1%{?dist}
Release: 2%{?dist}
License: GPLv2+
Url: http://www.exim.org/
Group: System Environment/Daemons
@ -52,6 +52,16 @@ Patch23: exim-4.67-smarthost-config.patch
Patch24: exim-4.71-dynlookup.patch
Patch25: exim-4.69-dynlookup-config.patch
Patch26: exim-4.69-strictaliasing.patch
Patch31: exim-4.72-0001-div-by-zero.patch
Patch32: exim-4.72-0002-eval-sigfpe.patch
Patch33: exim-4.72-0003-CVE-2011-1407.patch
Patch34: exim-4.72-0004-CVE-2011-0017.patch
Patch35: exim-4.72-0005-CVE-2010-4345.patch
Patch36: exim-4.72-0006-CVE-2010-4345.patch
Patch37: exim-4.72-0007-CVE-2010-4345.patch
Patch38: exim-4.72-0008-CVE-2010-4345.patch
Patch39: exim-4.72-0009-CVE-2010-4345.patch
Requires: /etc/pki/tls/certs /etc/pki/tls/private
Requires: /etc/aliases
@ -183,6 +193,16 @@ greylisting unconditional.
%patch25 -p1 -b .dynconfig
%patch26 -p1 -b .strictaliasing
%patch31 -p2 -b .0001
%patch32 -p2 -b .0002
%patch33 -p2 -b .0003
%patch34 -p2 -b .0004
%patch35 -p2 -b .0005
%patch36 -p2 -b .0006
%patch37 -p2 -b .0007
%patch38 -p2 -b .0008
%patch39 -p2 -b .0009
cp src/EDITME Local/Makefile
sed -i 's@^# LOOKUP_MODULE_DIR=.*@LOOKUP_MODULE_DIR=%{_libdir}/exim/%{version}-%{release}/lookups@' Local/Makefile
sed -i 's@^# AUTH_LIBS=-lsasl2@AUTH_LIBS=-lsasl2@' Local/Makefile
@ -501,6 +521,10 @@ test "$1" = 0 || %{_initrddir}/clamd.exim condrestart >/dev/null || :
%{_sysconfdir}/cron.daily/greylist-tidy.sh
%changelog
* Wed May 18 2011 Mark Chappell <tremble@tremble.org.uk> 4.72-2
- Backport various security fixes
- (CVE-2011-1407 CVE-2011-0017 CVE-2010-4345)
* Thu Jun 03 2010 David Woodhouse <David.Woodhouse@intel.com> - 4.72-1
- Update to 4.72 (fixes CVE-2010-2023, CVS-2010-2024)