/*
* Prototypes
*/
-static void runas_setgroups(void);
+static struct group_list *runas_setgroups(void);
/*
* We keep track of the current permisstions and use a stack to restore
#ifdef HAVE_SETRESUID
gid_t sgid;
#endif
- GETGROUPS_T *groups;
- int ngroups;
+ struct group_list *grlist;
};
#define PERM_STACK_MAX 16
static struct perm_state perm_stack[PERM_STACK_MAX];
static int perm_stack_depth = 0;
-/* XXX - make a runas_user struct? */
-int runas_ngroups = -1;
-#ifdef HAVE_GETGROUPS
-GETGROUPS_T *runas_groups;
-#endif
-
#undef ID
#define ID(x) (state->x == ostate->x ? -1 : state->x)
#undef OID
{
while (perm_stack_depth > 1)
restore_perms();
+ grlist_delref(perm_stack[0].grlist);
}
#ifdef HAVE_SETRESUID
int
set_perms(int perm)
{
- struct perm_state *state, *ostate = NULL;
+ struct perm_state *state, *ostate;
const char *errstr;
int noexit;
CLR(perm, PERM_MASK);
if (perm_stack_depth == PERM_STACK_MAX) {
- errstr = "perm stack overflow";
+ errstr = _("perm stack overflow");
errno = EINVAL;
goto bad;
}
state = &perm_stack[perm_stack_depth];
- if (perm_stack_depth)
+ if (perm != PERM_INITIAL) {
+ if (perm_stack_depth == 0) {
+ errstr = _("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
ostate = &perm_stack[perm_stack_depth - 1];
-
- if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0)
- goto done;
+ if (memcmp(state, ostate, sizeof(*state)) == 0)
+ goto done;
+ }
switch (perm) {
case PERM_INITIAL:
state->egid = getegid();
state->sgid = state->egid; /* in case we are setgid */
#endif
- state->groups = user_groups;
- state->ngroups = user_ngroups;
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
break;
case PERM_ROOT:
state->rgid = -1;
state->egid = -1;
state->sgid = -1;
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
break;
case PERM_USER:
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
state->rgid = -1;
state->egid = user_gid;
state->sgid = -1;
errstr = "setresgid(-1, user_gid, -1)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
state->ruid = user_uid;
state->euid = user_uid;
state->suid = ROOT_UID;
case PERM_FULL_USER:
/* headed for exec() */
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
state->rgid = user_gid;
state->egid = user_gid;
state->sgid = user_gid;
errstr = "setresgid(user_gid, user_gid, user_gid)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
state->ruid = user_uid;
state->euid = user_uid;
state->suid = user_uid;
break;
case PERM_RUNAS:
- runas_setgroups();
- state->groups = runas_groups;
- state->ngroups = runas_ngroups;
-
state->rgid = -1;
state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
state->sgid = -1;
if (setresgid(-1, ID(egid), -1)) {
- errstr = "unable to change to runas gid";
+ errstr = _("unable to change to runas gid");
goto bad;
}
+ state->grlist = runas_setgroups();
state->ruid = -1;
state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
state->suid = -1;
if (setresuid(-1, ID(euid), -1)) {
- errstr = "unable to change to runas uid";
+ errstr = _("unable to change to runas uid");
goto bad;
}
break;
case PERM_SUDOERS:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
/* assumes euid == ROOT_UID, ruid == user */
state->rgid = -1;
state->egid = sudoers_gid;
state->sgid = -1;
if (setresgid(-1, ID(egid), -1))
- error(1, "unable to change to sudoers gid");
+ error(1, _("unable to change to sudoers gid"));
state->ruid = ROOT_UID;
/*
break;
case PERM_TIMESTAMP:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
state->rgid = -1;
state->egid = -1;
state->sgid = -1;
bad:
/* XXX - better warnings inline */
warningx("%s: %s", errstr,
- errno == EAGAIN ? "too many processes" : strerror(errno));
+ errno == EAGAIN ? _("too many processes") : strerror(errno));
if (noexit)
return 0;
exit(1);
state->egid, state->sgid, OID(rgid), OID(egid), OID(sgid));
goto bad;
}
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(ostate->ngroups, ostate->groups)) {
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
warning("setgroups()");
goto bad;
}
}
+ grlist_delref(state->grlist);
return;
bad:
int
set_perms(int perm)
{
- struct perm_state *state, *ostate = NULL;
+ struct perm_state *state, *ostate;
const char *errstr;
int noexit;
CLR(perm, PERM_MASK);
if (perm_stack_depth == PERM_STACK_MAX) {
- errstr = "perm stack overflow";
+ errstr = _("perm stack overflow");
errno = EINVAL;
goto bad;
}
state = &perm_stack[perm_stack_depth];
- if (perm_stack_depth)
+ if (perm != PERM_INITIAL) {
+ if (perm_stack_depth == 0) {
+ errstr = _("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
ostate = &perm_stack[perm_stack_depth - 1];
-
- if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0)
- goto done;
+ if (memcmp(state, ostate, sizeof(*state)) == 0)
+ goto done;
+ }
switch (perm) {
case PERM_INITIAL:
state->euid = geteuid();
state->rgid = getgid();
state->egid = getegid();
- state->groups = user_groups;
- state->ngroups = user_ngroups;
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
break;
case PERM_ROOT:
state->euid = ROOT_UID;
state->rgid = -1;
state->egid = -1;
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
break;
case PERM_USER:
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
state->rgid = -1;
state->egid = user_gid;
if (setregid(-1, ID(egid))) {
errstr = "setregid(-1, user_gid)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
state->ruid = ROOT_UID;
state->euid = user_uid;
if (setreuid(ID(ruid), ID(euid))) {
case PERM_FULL_USER:
/* headed for exec() */
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
state->rgid = user_gid;
state->egid = user_gid;
if (setregid(ID(rgid), ID(egid))) {
errstr = "setregid(user_gid, user_gid)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
state->ruid = user_uid;
state->euid = user_uid;
if (setreuid(ID(ruid), ID(euid))) {
break;
case PERM_RUNAS:
- runas_setgroups();
- state->groups = runas_groups;
- state->ngroups = runas_ngroups;
-
state->rgid = -1;
state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
if (setregid(ID(rgid), ID(egid))) {
- errstr = "unable to change to runas gid";
+ errstr = _("unable to change to runas gid");
goto bad;
}
+ state->grlist = runas_setgroups();
state->ruid = ROOT_UID;
state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
if (setreuid(ID(ruid), ID(euid))) {
- errstr = "unable to change to runas uid";
+ errstr = _("unable to change to runas uid");
goto bad;
}
break;
case PERM_SUDOERS:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
/* assume euid == ROOT_UID, ruid == user */
state->rgid = -1;
state->egid = sudoers_gid;
if (setregid(-1, ID(egid)))
- error(1, "unable to change to sudoers gid");
+ error(1, _("unable to change to sudoers gid"));
state->ruid = ROOT_UID;
/*
break;
case PERM_TIMESTAMP:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
state->rgid = -1;
state->egid = -1;
state->ruid = ROOT_UID;
bad:
/* XXX - better warnings inline */
warningx("%s: %s", errstr,
- errno == EAGAIN ? "too many processes" : strerror(errno));
+ errno == EAGAIN ? _("too many processes") : strerror(errno));
if (noexit)
return 0;
exit(1);
state->egid, OID(rgid), OID(egid));
goto bad;
}
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(ostate->ngroups, ostate->groups)) {
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
warning("setgroups()");
goto bad;
}
}
+ grlist_delref(state->grlist);
return;
bad:
int
set_perms(int perm)
{
- struct perm_state *state, *ostate = NULL;
+ struct perm_state *state, *ostate;
const char *errstr;
int noexit;
CLR(perm, PERM_MASK);
if (perm_stack_depth == PERM_STACK_MAX) {
- errstr = "perm stack overflow";
+ errstr = _("perm stack overflow");
errno = EINVAL;
goto bad;
}
state = &perm_stack[perm_stack_depth];
- if (perm_stack_depth)
+ if (perm != PERM_INITIAL) {
+ if (perm_stack_depth == 0) {
+ errstr = _("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
ostate = &perm_stack[perm_stack_depth - 1];
-
- if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0)
- goto done;
+ if (memcmp(state, ostate, sizeof(*state)) == 0)
+ goto done;
+ }
/*
* Since we only have setuid() and seteuid() and semantics
state->euid = geteuid();
state->rgid = getgid();
state->egid = getegid();
- state->groups = user_groups;
- state->ngroups = user_ngroups;
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
break;
case PERM_ROOT:
state->euid = ROOT_UID;
state->rgid = -1;
state->egid = -1;
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
break;
case PERM_USER:
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
- state->rgid = -1;
state->egid = user_gid;
if (setegid(ID(egid))) {
errstr = "setegid(user_gid)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
+ state->rgid = -1;
state->ruid = ROOT_UID;
state->euid = user_uid;
if (seteuid(ID(euid))) {
case PERM_FULL_USER:
/* headed for exec() */
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
- errstr = "setgroups()";
- goto bad;
- }
- }
state->rgid = user_gid;
state->egid = user_gid;
if (setgid(user_gid)) {
errstr = "setgid(user_gid)";
goto bad;
}
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
+ errstr = "setgroups()";
+ goto bad;
+ }
+ }
state->ruid = user_uid;
state->euid = user_uid;
if (setuid(user_uid)) {
break;
case PERM_RUNAS:
- runas_setgroups();
- state->groups = runas_groups;
- state->ngroups = runas_ngroups;
-
state->rgid = -1;
state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
if (setegid(ID(egid))) {
- errstr = "unable to change to runas gid";
+ errstr = _("unable to change to runas gid");
goto bad;
}
+ state->grlist = runas_setgroups();
state->ruid = -1;
state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
if (seteuid(ID(euid))) {
- errstr = "unable to change to runas uid";
+ errstr = _("unable to change to runas uid");
goto bad;
}
break;
case PERM_SUDOERS:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
/* assume euid == ROOT_UID, ruid == user */
state->rgid = -1;
state->egid = sudoers_gid;
if (setegid(ID(egid)))
- error(1, "unable to change to sudoers gid");
+ error(1, _("unable to change to sudoers gid"));
state->ruid = ROOT_UID;
/*
break;
case PERM_TIMESTAMP:
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
state->rgid = -1;
state->egid = -1;
state->ruid = ROOT_UID;
bad:
/* XXX - better warnings inline */
warningx("%s: %s", errstr,
- errno == EAGAIN ? "too many processes" : strerror(errno));
+ errno == EAGAIN ? _("too many processes") : strerror(errno));
if (noexit)
return 0;
exit(1);
warning("setegid(%d)", OID(egid));
goto bad;
}
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(ostate->ngroups, ostate->groups)) {
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
warning("setgroups()");
goto bad;
}
warning("seteuid(%d)", OID(euid));
goto bad;
}
+ grlist_delref(state->grlist);
return;
bad:
int
set_perms(int perm)
{
- struct perm_state *state, *ostate = NULL;
+ struct perm_state *state, *ostate;
const char *errstr;
int noexit;
CLR(perm, PERM_MASK);
if (perm_stack_depth == PERM_STACK_MAX) {
- errstr = "perm stack overflow";
+ errstr = _("perm stack overflow");
errno = EINVAL;
goto bad;
}
state = &perm_stack[perm_stack_depth];
- if (perm_stack_depth)
+ if (perm != PERM_INITIAL) {
+ if (perm_stack_depth == 0) {
+ errstr = _("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
ostate = &perm_stack[perm_stack_depth - 1];
-
- if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0)
- goto done;
+ if (memcmp(state, ostate, sizeof(*state)) == 0)
+ goto done;
+ }
switch (perm) {
case PERM_INITIAL:
/* Stash initial state */
state->ruid = getuid();
state->rgid = getgid();
- state->groups = user_groups;
- state->ngroups = user_ngroups;
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
break;
case PERM_ROOT:
state->ruid = ROOT_UID;
state->rgid = -1;
- state->groups = NULL;
- state->ngroups = -1;
+ state->grlist = ostate->grlist;
+ grlist_addref(state->grlist);
if (setuid(ROOT_UID)) {
errstr = "setuid(ROOT_UID)";
goto bad;
break;
case PERM_FULL_USER:
- state->groups = user_groups;
- state->ngroups = user_ngroups;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(state->ngroups, state->groups)) {
+ state->rgid = user_gid;
+ (void) setgid(user_gid);
+ state->grlist = user_group_list;
+ grlist_addref(state->grlist);
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
errstr = "setgroups()";
goto bad;
}
}
- state->rgid = user_gid;
- (void) setgid(user_gid);
state->ruid = user_uid;
if (setuid(user_uid)) {
errstr = "setuid(user_uid)";
bad:
/* XXX - better warnings inline */
warningx("%s: %s", errstr,
- errno == EAGAIN ? "too many processes" : strerror(errno));
+ errno == EAGAIN ? _("too many processes") : strerror(errno));
if (noexit)
return 0;
exit(1);
ostate = &perm_stack[perm_stack_depth - 2];
perm_stack_depth--;
- if (state->ngroups != -1 && state->groups != ostate->groups) {
- if (setgroups(ostate->ngroups, ostate->groups)) {
- warning("setgroups()");
- goto bad;
- }
- }
if (OID(rgid) != -1 && setgid(ostate->rgid)) {
warning("setgid(%d)", ostate->rgid);
goto bad;
}
+ if (state->grlist != ostate->grlist) {
+ if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
+ warning("setgroups()");
+ goto bad;
+ }
+ }
+ grlist_delref(state->grlist);
if (OID(ruid) != -1 && setuid(ostate->ruid)) {
warning("setuid(%d)", ostate->ruid);
goto bad;
# endif /* HAVE_SETREUID */
#endif /* HAVE_SETRESUID */
-#ifdef HAVE_INITGROUPS
-static void
-runas_setgroups()
+static struct group_list *
+runas_setgroups(void)
{
- static struct passwd *pw;
- struct passwd *opw = pw;
-
- if (def_preserve_groups)
- return;
+ struct passwd *pw;
+ struct group_list *grlist;
- /*
- * Use stashed copy of runas groups if available, else initgroups and stash.
- */
- pw = runas_pw ? runas_pw : sudo_user.pw;
- if (pw != opw) {
- pw = runas_pw ? runas_pw : sudo_user.pw;
-# ifdef HAVE_SETAUTHDB
- aix_setauthdb(pw->pw_name);
-# endif
- if (initgroups(pw->pw_name, pw->pw_gid) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
-# ifdef HAVE_GETGROUPS
- if (runas_groups) {
- efree(runas_groups);
- runas_groups = NULL;
- }
- if ((runas_ngroups = getgroups(0, NULL)) > 0) {
- runas_groups = emalloc2(runas_ngroups, sizeof(GETGROUPS_T));
- if (getgroups(runas_ngroups, runas_groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
- }
-# ifdef HAVE_SETAUTHDB
- aix_restoreauthdb();
-# endif
- } else {
- if (setgroups(runas_ngroups, runas_groups) < 0)
- log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
-# endif /* HAVE_GETGROUPS */
+ if (def_preserve_groups) {
+ grlist_addref(user_group_list);
+ return user_group_list;
}
-}
-#else
-
-static void
-runas_setgroups()
-{
- /* STUB */
+ pw = runas_pw ? runas_pw : sudo_user.pw;
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb(pw->pw_name);
+#endif
+ grlist = get_group_list(pw);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ if (sudo_setgroups(grlist->ngids, grlist->gids) < 0)
+ log_error(USE_ERRNO|MSG_ONLY, _("unable to set runas group vector"));
+ return grlist;
}
-
-#endif /* HAVE_INITGROUPS */