From: Timo Sirainen Date: Sat, 26 Oct 2013 16:11:34 +0000 (+0300) Subject: auth: Refuse to run checkpassword script insecurely by default X-Git-Tag: 2.2.7~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0e2c938d774fc5df086c102fea7210ed9e0557b;p=thirdparty%2Fdovecot%2Fcore.git auth: Refuse to run checkpassword script insecurely by default --- diff --git a/src/auth/checkpassword-reply.c b/src/auth/checkpassword-reply.c index f3d2e20b2e..31bf3473b1 100644 --- a/src/auth/checkpassword-reply.c +++ b/src/auth/checkpassword-reply.c @@ -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 --git a/src/auth/db-checkpassword.c b/src/auth/db-checkpassword.c index 3c8b8a1d2f..a5a1e7f7d1 100644 --- a/src/auth/db-checkpassword.c +++ b/src/auth/db-checkpassword.c @@ -251,6 +251,7 @@ static void checkpassword_setup_env(struct auth_request *request) 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=",