dovecot-2.2: auth: Refuse to run checkpassword script insecurely...

dovecot at dovecot.org dovecot at dovecot.org
Sat Oct 26 19:11:48 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/a13098b642e9
changeset: 16887:a13098b642e9
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Oct 26 19:11:34 2013 +0300
description:
auth: Refuse to run checkpassword script insecurely by default

diffstat:

 src/auth/checkpassword-reply.c |  27 ++++++++++++++++++++++++++-
 src/auth/db-checkpassword.c    |   1 +
 2 files changed, 27 insertions(+), 1 deletions(-)

diffs (54 lines):

diff -r 26355654c314 -r a13098b642e9 src/auth/checkpassword-reply.c
--- a/src/auth/checkpassword-reply.c	Sat Oct 26 18:59:52 2013 +0300
+++ b/src/auth/checkpassword-reply.c	Sat Oct 26 19:11:34 2013 +0300
@@ -11,13 +11,38 @@
 int main(void)
 {
 	string_t *str;
-	const char *user, *home, *authorized;
+	const char *user, *home, *authorized, *orig_uid;
 	const char *extra_env, *key, *value, *const *tmp;
 	bool uid_found = FALSE, gid_found = FALSE;
 
 	lib_init();
 	str = t_str_new(1024);
 
+	orig_uid = getenv("ORIG_UID");
+	/* ORIG_UID should have the auth process's UID that forked us.
+	   if the checkpassword changed the UID, this could be a security hole
+	   because the UID's other processes can ptrace this process and write
+	   any kind of a reply to fd 4. so we can run only if:
+
+	   a) INSECURE_SETUID environment is set.
+	   b) process isn't ptraceable (this binary is setuid/setgid)
+	   c) checkpassword didn't actually change the UID (but used
+	      userdb_uid instead)
+	   */
+	if (getenv("INSECURE_SETUID") == NULL &&
+	    (orig_uid == NULL || strtoul(orig_uid, NULL, 10) != getuid()) &&
+	    getuid() == geteuid() && getgid() == getegid()) {
+		if (orig_uid == NULL) {
+			i_error("checkpassword: ORIG_UID environment was dropped by checkpassword. "
+				"Can't verify if we're safe to run. See "
+				"http://wiki2.dovecot.org/AuthDatabase/CheckPassword#Security");
+		} else {
+			i_error("checkpassword: The checkpassword couldn't be run securely. See "
+				"http://wiki2.dovecot.org/AuthDatabase/CheckPassword#Security");
+		}
+		return 111;
+	}
+
 	user = getenv("USER");
 	if (user != NULL) {
 		if (strchr(user, '\t') != NULL) {
diff -r 26355654c314 -r a13098b642e9 src/auth/db-checkpassword.c
--- a/src/auth/db-checkpassword.c	Sat Oct 26 18:59:52 2013 +0300
+++ b/src/auth/db-checkpassword.c	Sat Oct 26 19:11:34 2013 +0300
@@ -251,6 +251,7 @@
 	   pipe, also pass some other possibly interesting information
 	   via environment. Use UCSPI names for local/remote IPs. */
 	env_put("PROTO=TCP"); /* UCSPI */
+	env_put(t_strdup_printf("ORIG_UID=%s", dec2str(getuid())));
 	env_put(t_strconcat("SERVICE=", request->service, NULL));
 	if (request->local_ip.family != 0) {
 		env_put(t_strconcat("TCPLOCALIP=",


More information about the dovecot-cvs mailing list