diff options
author | Damien Miller <djm@mindrot.org> | 2003-06-05 09:53:31 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2003-06-05 09:53:31 +1000 |
commit | 5fe46a45c834bf2e336d979e2ae755b94e01d707 (patch) | |
tree | e65443bf5183b99f97a28f7209011f60c2a620e0 | |
parent | 0f68486a7673885ba2834af80fd14f1e3be16e8f (diff) | |
download | openssh-git-5fe46a45c834bf2e336d979e2ae755b94e01d707.tar.gz |
- (djm) Implement paranoid priv dropping checks, based on:
"SetUID demystified" - Hao Chen, David Wagner and Drew Dean
Proceedings of USENIX Security Symposium 2002
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | acconfig.h | 5 | ||||
-rw-r--r-- | configure.ac | 15 | ||||
-rw-r--r-- | includes.h | 1 | ||||
-rw-r--r-- | uidswap.c | 47 |
5 files changed, 64 insertions, 9 deletions
@@ -1,6 +1,9 @@ 20030605 - (djm) Support AI_NUMERICHOST in fake-getaddrinfo.c. Needed for recent canohost.c changes. + - (djm) Implement paranoid priv dropping checks, based on: + "SetUID demystified" - Hao Chen, David Wagner and Drew Dean + Proceedings of USENIX Security Symposium 2002 20030604 - (djm) Bug #573 - Remove unneeded Krb headers and compat goop. Patch from @@ -462,4 +465,4 @@ - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. Report from murple@murple.net, diagnosis from dtucker@zip.com.au -$Id: ChangeLog,v 1.2782 2003/06/04 23:48:32 djm Exp $ +$Id: ChangeLog,v 1.2783 2003/06/04 23:53:42 djm Exp $ @@ -1,4 +1,4 @@ -/* $Id: acconfig.h,v 1.155 2003/06/03 00:14:28 djm Exp $ */ +/* $Id: acconfig.h,v 1.156 2003/06/04 23:53:31 djm Exp $ */ #ifndef _CONFIG_H #define _CONFIG_H @@ -8,6 +8,9 @@ @TOP@ +/* Define if your platform breaks doing a seteuid before a setuid */ +#undef SETEUID_BREAKS_SETUID + /* Define to a Set Process Title type if your system is */ /* supported by bsd-setproctitle.c */ #undef SPT_TYPE diff --git a/configure.ac b/configure.ac index 21d764f2..92f182ac 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.125 2003/06/03 00:14:28 djm Exp $ +# $Id: configure.ac,v 1.126 2003/06/04 23:53:31 djm Exp $ AC_INIT AC_CONFIG_SRCDIR([ssh.c]) @@ -439,7 +439,7 @@ AC_ARG_WITH(libs, ) # Checks for header files. -AC_CHECK_HEADERS(bstring.h crypt.h endian.h floatingpoint.h \ +AC_CHECK_HEADERS(bstring.h crypt.h endian.h features.h floatingpoint.h \ getopt.h glob.h ia.h lastlog.h libgen.h limits.h login.h \ login_cap.h maillock.h netdb.h netgroup.h \ netinet/in_systm.h paths.h pty.h readpassphrase.h \ @@ -659,17 +659,18 @@ AC_ARG_WITH(tcp-wrappers, dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS(\ - arc4random __b64_ntop b64_ntop __b64_pton b64_pton basename bcopy \ - bindresvport_sa clock fchmod fchown freeaddrinfo futimes \ + arc4random __b64_ntop b64_ntop __b64_pton b64_pton basename \ + bcopy bindresvport_sa clock fchmod fchown freeaddrinfo futimes \ gai_strerror getaddrinfo getcwd getgrouplist getnameinfo getopt \ getpeereid _getpty getrlimit getrusage getttyent glob inet_aton \ inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \ mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \ pstat readpassphrase realpath recvmsg rresvport_af sendmsg \ setdtablesize setegid setenv seteuid setgroups setlogin setpcred \ - setproctitle setresgid setreuid setrlimit setsid setvbuf sigaction \ - sigvec snprintf socketpair strerror strlcat strlcpy strmode strnvis \ - sysconf tcgetpgrp truncate utimes vhangup vsnprintf waitpid \ + setproctitle setregid setresgid setresuid setreuid setrlimit \ + setsid setvbuf sigaction sigvec snprintf socketpair strerror \ + strlcat strlcpy strmode strnvis sysconf tcgetpgrp truncate utimes \ + vhangup vsnprintf waitpid \ ) AC_SEARCH_LIBS(nanosleep, rt posix4, AC_DEFINE(HAVE_NANOSLEEP)) @@ -68,6 +68,7 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #ifdef HAVE_NEXT # include <libc.h> #endif +#define __USE_GNU /* before unistd.h, activate extra prototypes for glibc */ #include <unistd.h> /* For STDIN_FILENO, etc */ #include <termios.h> /* Struct winsize */ @@ -143,16 +143,63 @@ restore_uid(void) void permanently_set_uid(struct passwd *pw) { + uid_t old_uid = getuid(); + gid_t old_gid = getgid(); + if (temporarily_use_uid_effective) fatal("permanently_set_uid: temporarily_use_uid effective"); debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, (u_int)pw->pw_gid); + +#if defined(HAVE_SETRESGID) + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) + fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); +#elif defined(HAVE_SETREGID) + if (setregid(pw->pw_gid, pw->pw_gid) < 0) + fatal("setregid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); +#else if (setegid(pw->pw_gid) < 0) fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); if (setgid(pw->pw_gid) < 0) fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); +#endif + +#if defined(HAVE_SETRESUID) + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) + fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); +#elif defined(HAVE_SETRESUID) + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) + fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); +#else +# ifndef SETEUID_BREAKS_SETUID if (seteuid(pw->pw_uid) < 0) fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); +# endif if (setuid(pw->pw_uid) < 0) fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); +#endif + + /* Try restoration of GID if changed (test clearing of saved gid) */ + if (old_gid != pw->pw_gid && + (setgid(old_gid) != -1 || setegid(old_gid) != -1)) + fatal("%s: was able to restore old [e]gid"); + + /* Verify GID drop was successful */ + if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { + fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", + __func__, (u_int)getgid(), (u_int)getegid(), + (u_int)pw->pw_gid); + } + + /* Try restoration of UID if changed (test clearing of saved uid) */ + if (old_uid != pw->pw_uid && + (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) + fatal("%s: was able to restore old [e]uid"); + + /* Verify UID drop was successful */ + if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { + fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", + __func__, (u_int)getuid(), (u_int)geteuid(), + (u_int)pw->pw_uid); + } } |