]> andersk Git - openssh.git/blobdiff - uidswap.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / uidswap.c
index e652161af938e2c2a0e22ad73f7646b6cd27a60e..8376483967a9f609f089a1879423ee6b3ea4d4d0 100644 (file)
--- a/uidswap.c
+++ b/uidswap.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: uidswap.c,v 1.35 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: uidswap.c,v 1.24 2003/05/29 16:58:45 deraadt Exp $");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <grp.h>
 
 #include "log.h"
 #include "uidswap.h"
@@ -56,10 +65,12 @@ temporarily_use_uid(struct passwd *pw)
        debug("temporarily_use_uid: %u/%u (e=%u/%u)",
            (u_int)pw->pw_uid, (u_int)pw->pw_gid,
            (u_int)saved_euid, (u_int)saved_egid);
+#ifndef HAVE_CYGWIN
        if (saved_euid != 0) {
                privileged = 0;
                return;
        }
+#endif
 #else
        if (geteuid() != 0) {
                privileged = 0;
@@ -75,11 +86,11 @@ temporarily_use_uid(struct passwd *pw)
                fatal("getgroups: %.100s", strerror(errno));
        if (saved_egroupslen > 0) {
                saved_egroups = xrealloc(saved_egroups,
-                   saved_egroupslen * sizeof(gid_t));
+                   saved_egroupslen, sizeof(gid_t));
                if (getgroups(saved_egroupslen, saved_egroups) < 0)
                        fatal("getgroups: %.100s", strerror(errno));
        } else { /* saved_egroupslen == 0 */
-               if (saved_egroups)
+               if (saved_egroups != NULL)
                        xfree(saved_egroups);
        }
 
@@ -94,7 +105,7 @@ temporarily_use_uid(struct passwd *pw)
                        fatal("getgroups: %.100s", strerror(errno));
                if (user_groupslen > 0) {
                        user_groups = xrealloc(user_groups,
-                           user_groupslen * sizeof(gid_t));
+                           user_groupslen, sizeof(gid_t));
                        if (getgroups(user_groupslen, user_groups) < 0)
                                fatal("getgroups: %.100s", strerror(errno));
                } else { /* user_groupslen == 0 */
@@ -121,6 +132,41 @@ temporarily_use_uid(struct passwd *pw)
                    strerror(errno));
 }
 
+void
+permanently_drop_suid(uid_t uid)
+{
+       uid_t old_uid = getuid();
+
+       debug("permanently_drop_suid: %u", (u_int)uid);
+#if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
+       if (setresuid(uid, uid, uid) < 0)
+               fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno));
+#elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
+       if (setreuid(uid, uid) < 0)
+               fatal("setreuid %u: %.100s", (u_int)uid, strerror(errno));
+#else
+# ifndef SETEUID_BREAKS_SETUID
+       if (seteuid(uid) < 0)
+               fatal("seteuid %u: %.100s", (u_int)uid, strerror(errno));
+# endif
+       if (setuid(uid) < 0)
+               fatal("setuid %u: %.100s", (u_int)uid, strerror(errno));
+#endif
+
+#ifndef HAVE_CYGWIN
+       /* Try restoration of UID if changed (test clearing of saved uid) */
+       if (old_uid != uid &&
+           (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
+               fatal("%s: was able to restore old [e]uid", __func__);
+#endif
+
+       /* Verify UID drop was successful */
+       if (getuid() != uid || geteuid() != uid) {
+               fatal("%s: euid incorrect uid:%u euid:%u (should be %u)",
+                   __func__, (u_int)getuid(), (u_int)geteuid(), (u_int)uid);
+       }
+}
+
 /*
  * Restores to the original (privileged) uid.
  */
@@ -167,6 +213,8 @@ permanently_set_uid(struct passwd *pw)
        uid_t old_uid = getuid();
        gid_t old_gid = getgid();
 
+       if (pw == NULL)
+               fatal("permanently_set_uid: no user given");
        if (temporarily_use_uid_effective)
                fatal("permanently_set_uid: temporarily_use_uid effective");
        debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid,
@@ -185,6 +233,16 @@ permanently_set_uid(struct passwd *pw)
                fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
 #endif
 
+#ifdef __APPLE__
+       /*
+        * OS X requires initgroups after setgid to opt back into
+        * memberd support for >16 supplemental groups.
+        */
+       if (initgroups(pw->pw_name, pw->pw_gid) < 0)
+               fatal("initgroups %.100s %u: %.100s",
+                   pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
+#endif
+
 #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
        if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0)
                fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
@@ -200,10 +258,12 @@ permanently_set_uid(struct passwd *pw)
                fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
 #endif
 
+#ifndef HAVE_CYGWIN
        /* Try restoration of GID if changed (test clearing of saved gid) */
-       if (old_gid != pw->pw_gid &&
+       if (old_gid != pw->pw_gid && pw->pw_uid != 0 &&
            (setgid(old_gid) != -1 || setegid(old_gid) != -1))
                fatal("%s: was able to restore old [e]gid", __func__);
+#endif
 
        /* Verify GID drop was successful */
        if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) {
This page took 0.201122 seconds and 4 git commands to generate.