When matching the runas user and runas group (-u and -g command

line options), keep track of runas group and runas user matches
separately.  Only return a positive match if we have a match for
both runas user and runas group (if specified).
This commit is contained in:
Todd C. Miller
2010-09-06 07:56:15 -04:00
parent df8ec6fc25
commit 8ec596c7d9

View File

@@ -161,15 +161,9 @@ _runaslist_matches(struct member_list *user_list, struct member_list *group_list
{ {
struct member *m; struct member *m;
struct alias *a; struct alias *a;
int rval, matched = UNSPEC; int rval;
int user_matched = UNSPEC;
if (runas_gr != NULL) { int group_matched = UNSPEC;
if (tq_empty(group_list))
return(DENY); /* group was specified but none in sudoers */
if (runas_pw != NULL && strcmp(runas_pw->pw_name, user_name) &&
tq_empty(user_list))
return(DENY); /* user was specified but none in sudoers */
}
if (tq_empty(user_list) && tq_empty(group_list)) if (tq_empty(user_list) && tq_empty(group_list))
return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
@@ -178,59 +172,67 @@ _runaslist_matches(struct member_list *user_list, struct member_list *group_list
tq_foreach_rev(user_list, m) { tq_foreach_rev(user_list, m) {
switch (m->type) { switch (m->type) {
case ALL: case ALL:
matched = !m->negated; user_matched = !m->negated;
break; break;
case NETGROUP: case NETGROUP:
if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
matched = !m->negated; user_matched = !m->negated;
break; break;
case USERGROUP: case USERGROUP:
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
matched = !m->negated; user_matched = !m->negated;
break; break;
case ALIAS: case ALIAS:
if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { if ((a = alias_find(m->name, RUNASALIAS)) != NULL) {
rval = _runaslist_matches(&a->members, &empty); rval = _runaslist_matches(&a->members, &empty);
if (rval != UNSPEC) if (rval != UNSPEC)
matched = m->negated ? !rval : rval; user_matched = m->negated ? !rval : rval;
break; break;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case WORD: case WORD:
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
matched = !m->negated; user_matched = !m->negated;
break; break;
} }
if (matched != UNSPEC) if (user_matched != UNSPEC)
break; break;
} }
} }
if (runas_gr != NULL) { if (runas_gr != NULL) {
if (user_matched == UNSPEC) {
if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0)
user_matched = ALLOW; /* only changing group */
}
tq_foreach_rev(group_list, m) { tq_foreach_rev(group_list, m) {
switch (m->type) { switch (m->type) {
case ALL: case ALL:
matched = !m->negated; group_matched = !m->negated;
break; break;
case ALIAS: case ALIAS:
if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { if ((a = alias_find(m->name, RUNASALIAS)) != NULL) {
rval = _runaslist_matches(&a->members, &empty); rval = _runaslist_matches(&a->members, &empty);
if (rval != UNSPEC) if (rval != UNSPEC)
matched = m->negated ? !rval : rval; group_matched = m->negated ? !rval : rval;
break; break;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case WORD: case WORD:
if (group_matches(m->name, runas_gr)) if (group_matches(m->name, runas_gr))
matched = !m->negated; group_matched = !m->negated;
break; break;
} }
if (matched != UNSPEC) if (group_matched != UNSPEC)
break; break;
} }
} }
return(matched); if (user_matched == DENY || group_matched == DENY)
return(DENY);
if (user_matched == group_matched || runas_gr == NULL)
return(user_matched);
return(UNSPEC);
} }
int int