}
#endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */
-#ifdef HAVE_SETREUID
+#ifdef HAVE_SETRESUID
+/*
+ * Set real and effective and saved uids and gids based on perm.
+ * We always retain a saved uid of 0 unless we are headed for an exec().
+ * We only flip the effective gid since it only changes for PERM_SUDOERS.
+ * This version of set_perms() works fine with the "stay_setuid" option.
+ */
+void
+set_perms_suid(perm)
+ int perm;
+{
+ int error;
+
+ switch (perm) {
+ case PERM_FULL_ROOT:
+ case PERM_ROOT:
+ if (setresuid(0, 0, 0))
+ fatal("setresuid(0, 0, 0) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid", 0);
+ break;
+
+ case PERM_USER:
+ (void) setresgid(user_gid, -1, -1);
+ if (setresuid(user_uid, user_uid, 0))
+ fatal("setresuid(user_uid, user_uid, 0)", 1);
+ break;
+
+ case PERM_FULL_USER:
+ /* headed for exec() */
+ (void) setgid(user_gid);
+ if (setresuid(user_uid, user_uid, user_uid))
+ fatal("setresuid(user_uid, user_uid, user_uid)", 1);
+ break;
+
+ case PERM_RUNAS:
+ /* headed for exec(), assume euid == 0 */
+ runas_setup();
+ error = setresuid(def_flag(I_STAY_SETUID) ?
+ user_uid : runas_pw->pw_uid,
+ runas_pw->pw_uid, runas_pw->pw_uid);
+ if (error)
+ fatal("unable to change to runas uid", 1);
+ break;
+
+ case PERM_SUDOERS:
+ /* assume euid == 0, ruid == user */
+ if (setresgid(SUDOERS_GID, -1, -1))
+ fatal("unable to change to sudoers gid", 1);
+
+ /*
+ * If SUDOERS_UID == 0 and SUDOERS_MODE
+ * is group readable we use a non-zero
+ * uid in order to avoid NFS lossage.
+ * Using uid 1 is a bit bogus but should
+ * work on all OS's.
+ */
+ if (SUDOERS_UID == 0) {
+ if ((SUDOERS_MODE & 040) && setresuid(0, 1, 0))
+ fatal("setresuid(0, 1, 0)", 1);
+ } else {
+ if (setresuid(0, SUDOERS_UID, 0))
+ fatal("setresuid(0, SUDOERS_UID, 0)", 1);
+ }
+ break;
+ case PERM_TIMESTAMP:
+ if (setresuid(0, timestamp_uid, 0))
+ fatal("setresuid(0, timestamp_uid, 0)", 1);
+ break;
+ }
+}
+
+#else
+# ifdef HAVE_SETREUID
+
/*
* Set real and effective uids and gids based on perm.
* We always retain a real or effective uid of 0 unless
* we are headed for an exec().
+ * This version of set_perms() works fine with the "stay_setuid" option.
*/
void
-set_perms_fallback(perm)
+set_perms_suid(perm)
int perm;
{
int error;
switch (perm) {
case PERM_FULL_ROOT:
case PERM_ROOT:
- if (setuid(0))
- fatal("setuid(0) failed, your operating system may have broken POSIX saved ID support\nTry running configure with --disable-setreuid", 0);
+ if (setreuid(0, 0))
+ fatal("setreuid(0, 0) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid", 0);
break;
case PERM_USER:
- (void) setegid(user_gid);
+ (void) setregid(user_gid, -1);
if (setreuid(0, user_uid))
fatal("setreuid(0, user_uid)", 1);
break;
case PERM_FULL_USER:
/* headed for exec() */
(void) setgid(user_gid);
- if (setuid(user_uid))
- fatal("setuid(user_uid)", 1);
+ if (setreuid(user_uid, user_uid))
+ fatal("setreuid(user_uid, user_uid)", 1);
break;
case PERM_RUNAS:
/* headed for exec(), assume euid == 0 */
runas_setup();
- if (def_flag(I_STAY_SETUID))
- error = setreuid(user_uid, runas_pw->pw_uid);
- else
- error = setuid(runas_pw->pw_uid);
+ error = setreuid(def_flag(I_STAY_SETUID) ?
+ user_uid : runas_pw->pw_uid,
+ runas_pw->pw_uid);
if (error)
fatal("unable to change to runas uid", 1);
break;
case PERM_SUDOERS:
/* assume euid == 0, ruid == user */
- if (setegid(SUDOERS_GID))
+ if (setregid(SUDOERS_GID, -1))
fatal("unable to change to sudoers gid", 1);
/*
}
}
-#else
+# else
/*
* Set real and effective uids and gids based on perm.
* NOTE: does not support the "stay_setuid" option.
*/
void
-set_perms_fallback(perm)
+set_perms_nosuid(perm)
int perm;
{
/*
* Since we only have setuid() and seteuid() we have to set
- * real and effective uidss to 0 initially.
+ * real and effective uids to 0 initially.
*/
if (setuid(0))
fatal("setuid(0)", 1);
break;
}
}
-#endif /* HAVE_SETREUID */
+# endif /* HAVE_SETREUID */
+#endif /* HAVE_SETRESUID */
static void
runas_setup()
validated = sudoers_lookup(pwflag);
/*
- * If we have POSIX saved uids and the stay_setuid flag was not set,
- * set the real, effective and saved uids to 0 and use set_perms_fallback()
+ * If we are using set_perms_posix() and the stay_setuid flag was not set,
+ * set the real, effective and saved uids to 0 and use set_perms_nosuid()
* instead of set_perms_posix().
*/
-#if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
+#if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \
+ !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
if (!def_flag(I_STAY_SETUID) && set_perms == set_perms_posix) {
if (setuid(0)) {
perror("setuid(0)");
exit(1);
}
- set_perms = set_perms_fallback;
+ set_perms = set_perms_nosuid;
}
#endif
for (fd = maxfd; fd > STDERR_FILENO; fd--)
(void) close(fd);
- /* Set set_perms pointer to the correct function */
-#if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
+ /*
+ * Make set_perms point to the correct function.
+ * If we are using setresuid() or setreuid() we only need to set this
+ * once. If we are using POSIX saved uids we will switch to
+ * set_perms_nosuid after sudoers has been parsed if the "stay_suid"
+ * option is not set.
+ */
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID)
+ set_perms = set_perms_suid;
+#else
+# if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
set_perms = set_perms_posix;
else
-#endif
- set_perms = set_perms_fallback;
+# endif
+ set_perms = set_perms_nosuid;
+#endif /* HAVE_SETRESUID || HAVE_SETREUID */
}
#ifdef HAVE_LOGIN_CAP_H