summaryrefslogtreecommitdiff
path: root/uidswap.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-06-05 09:53:31 +1000
committerDamien Miller <djm@mindrot.org>2003-06-05 09:53:31 +1000
commit5fe46a45c834bf2e336d979e2ae755b94e01d707 (patch)
treee65443bf5183b99f97a28f7209011f60c2a620e0 /uidswap.c
parent0f68486a7673885ba2834af80fd14f1e3be16e8f (diff)
downloadopenssh-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
Diffstat (limited to 'uidswap.c')
-rw-r--r--uidswap.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/uidswap.c b/uidswap.c
index db625325..04c269b0 100644
--- a/uidswap.c
+++ b/uidswap.c
@@ -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);
+ }
}