* Prototypes
*/
static void runas_setup __P((void));
+static void runas_setgroups __P((const char *, gid_t));
+static void restore_groups __P((void));
+
+static int current_perm = -1;
#ifdef HAVE_SETRESUID
/*
set_perms(perm)
int perm;
{
+ if (perm == current_perm)
+ return;
+
switch (perm) {
case PERM_ROOT:
if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
errorx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid");
(void) setresgid(-1, user_gid, -1);
+ if (current_perm == PERM_RUNAS)
+ restore_groups();
break;
case PERM_USER:
break;
case PERM_RUNAS:
+ runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
(void) setresgid(-1, runas_gr ?
runas_gr->gr_gid : runas_pw->pw_gid, -1);
if (setresuid(-1,
error(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
break;
}
+
+ current_perm = perm;
}
#else
set_perms(perm)
int perm;
{
+ if (perm == current_perm)
+ return;
+
switch (perm) {
case PERM_ROOT:
if (setreuid(-1, ROOT_UID))
if (setuid(ROOT_UID))
error(1, "setuid(ROOT_UID)");
(void) setregid(-1, user_gid);
+ if (current_perm == PERM_RUNAS)
+ restore_groups();
break;
case PERM_USER:
break;
case PERM_RUNAS:
+ runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
(void) setregid(-1, runas_gr ?
runas_gr->gr_gid : runas_pw->pw_gid);
if (setreuid(-1,
error(1, "setreuid(ROOT_UID, timestamp_uid)");
break;
}
+
+ current_perm = perm;
}
# else /* !HAVE_SETRESUID && !HAVE_SETREUID */
set_perms(perm)
int perm;
{
+ if (perm == current_perm)
+ return;
+
/*
* Since we only have setuid() and seteuid() and semantics
* for these calls differ on various systems, we set
case PERM_ROOT:
/* uid set above */
(void) setegid(user_gid);
+ if (current_perm == PERM_RUNAS)
+ restore_groups();
break;
case PERM_USER:
break;
case PERM_RUNAS:
+ runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
(void) setegid(runas_gr ?
runas_gr->gr_gid : runas_pw->pw_gid);
if (seteuid(runas_pw ? runas_pw->pw_uid : user_uid))
error(1, "seteuid(timestamp_uid)");
break;
}
+
+ current_perm = perm;
}
# else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
set_perms(perm)
int perm;
{
+ if (perm == current_perm)
+ return;
switch (perm) {
case PERM_ROOT:
if (setuid(ROOT_UID))
error(1, "setuid(ROOT_UID)");
+ if (current_perm == PERM_RUNAS)
+ restore_groups();
break;
case PERM_FULL_USER:
/* Unsupported since we can't set euid. */
break;
}
+
+ current_perm = perm;
}
# endif /* HAVE_SETEUID */
# endif /* HAVE_SETREUID */
#endif /* HAVE_SETRESUID */
+#ifdef HAVE_INITGROUPS
+static void
+runas_setgroups(name, basegid)
+ const char *name;
+ gid_t basegid;
+{
+ static int ngroups = -1;
+ static gid_t *groups;
+
+ if (def_preserve_groups)
+ return;
+
+ /*
+ * Use stashed copy of runas groups if available, else initgroups and stash.
+ */
+ if (ngroups == -1) {
+ if (initgroups(name, basegid) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
+ if ((ngroups = getgroups(0, NULL)) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, "can't get runas ngroups");
+ groups = emalloc2(ngroups, MAX(sizeof(gid_t), sizeof(int)));
+ if (getgroups(ngroups, groups) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
+ } else {
+ if (setgroups(ngroups, groups) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
+ }
+}
+
+static void
+restore_groups()
+{
+ if (setgroups(user_ngroups, user_groups) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
+}
+
+#else
+
+static void
+runas_setgroups(name, basegid)
+ const char *name;
+ gid_t basegid;
+{
+ /* STUB */
+}
+
+static void
+restore_groups()
+{
+ /* STUB */
+}
+
+#endif /* HAVE_INITGROUPS */
+
static void
runas_setup()
{
#ifdef HAVE_LOGIN_CAP_H
if (def_use_loginclass) {
/*
- * We don't have setusercontext() set the user since we
- * may only want to set the effective uid. Depending on
- * sudoers and/or command line arguments we may not want
- * setusercontext() to call initgroups().
+ * We only use setusercontext() set the nice value and rlimits.
*/
flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
if (!def_preserve_groups)
else
warning("unable to set user context");
}
- } else
-#endif /* HAVE_LOGIN_CAP_H */
- {
- if (setgid(gid))
- warning("cannot set gid to runas gid");
-#ifdef HAVE_INITGROUPS
- /*
- * Initialize group vector unless asked not to.
- */
- if (!def_preserve_groups &&
- initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0)
- warning("cannot set group vector");
-#endif /* HAVE_INITGROUPS */
}
+#endif /* HAVE_LOGIN_CAP_H */
+ if (setgid(gid))
+ warning("cannot set gid to runas gid");
+ /*
+ * Initialize group vector
+ */
+ runas_setgroups(runas_pw->pw_name, runas_pw->pw_gid);
}
}