Add a sequence number in the aliases for loop detection. If we find
an alias with the seqno already set to the current (global) value we know we've visited it before so ignore it.
This commit is contained in:
17
alias.c
17
alias.c
@@ -52,6 +52,7 @@ __unused static const char rcsid[] = "$Sudo$";
|
||||
* Globals
|
||||
*/
|
||||
struct rbtree *aliases;
|
||||
unsigned int alias_seqno;
|
||||
|
||||
/*
|
||||
* Local protoypes
|
||||
@@ -91,11 +92,22 @@ find_alias(name, type)
|
||||
{
|
||||
struct alias key;
|
||||
struct rbnode *node;
|
||||
struct alias *a = NULL;
|
||||
|
||||
key.name = name;
|
||||
key.type = type;
|
||||
node = rbfind(aliases, &key);
|
||||
return(node ? node->data : NULL);
|
||||
if ((node = rbfind(aliases, &key)) != NULL) {
|
||||
/*
|
||||
* Compare the global sequence number with the one stored
|
||||
* in the alias. If they match then we've seen this alias
|
||||
* before and found a loop.
|
||||
*/
|
||||
a = node->data;
|
||||
if (a->seqno == alias_seqno)
|
||||
return(NULL);
|
||||
a->seqno = alias_seqno;
|
||||
}
|
||||
return(a);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -114,6 +126,7 @@ alias_add(name, type, members)
|
||||
a = emalloc(sizeof(*a));
|
||||
a->name = name;
|
||||
a->type = type;
|
||||
a->seqno = 0;
|
||||
list2tq(&a->members, members);
|
||||
if (rbinsert(aliases, a)) {
|
||||
efree(a);
|
||||
|
96
match.c
96
match.c
@@ -102,8 +102,8 @@ __unused static const char rcsid[] = "$Sudo$";
|
||||
* Check for user described by pw in a list of members.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
*/
|
||||
int
|
||||
userlist_matches(pw, list)
|
||||
static int
|
||||
_userlist_matches(pw, list)
|
||||
struct passwd *pw;
|
||||
struct member_list *list;
|
||||
{
|
||||
@@ -126,7 +126,7 @@ userlist_matches(pw, list)
|
||||
break;
|
||||
case ALIAS:
|
||||
if ((a = find_alias(m->name, USERALIAS)) != NULL) {
|
||||
rval = userlist_matches(pw, &a->members);
|
||||
rval = _userlist_matches(pw, &a->members);
|
||||
if (rval != UNSPEC)
|
||||
matched = m->negated ? !rval : rval;
|
||||
break;
|
||||
@@ -143,13 +143,22 @@ userlist_matches(pw, list)
|
||||
return(matched);
|
||||
}
|
||||
|
||||
int
|
||||
userlist_matches(pw, list)
|
||||
struct passwd *pw;
|
||||
struct member_list *list;
|
||||
{
|
||||
alias_seqno++;
|
||||
return(_userlist_matches(pw, list));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for user described by pw in a list of members.
|
||||
* If list is NULL compare against def_runas_default.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
*/
|
||||
int
|
||||
runaslist_matches(list)
|
||||
static int
|
||||
_runaslist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
struct member *m;
|
||||
@@ -174,7 +183,7 @@ runaslist_matches(list)
|
||||
break;
|
||||
case ALIAS:
|
||||
if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
|
||||
rval = runaslist_matches(&a->members);
|
||||
rval = _runaslist_matches(&a->members);
|
||||
if (rval != UNSPEC)
|
||||
matched = m->negated ? !rval : rval;
|
||||
break;
|
||||
@@ -191,12 +200,20 @@ runaslist_matches(list)
|
||||
return(matched);
|
||||
}
|
||||
|
||||
int
|
||||
runaslist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
alias_seqno++;
|
||||
return(_runaslist_matches(list));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for host and shost in a list of members.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
*/
|
||||
int
|
||||
hostlist_matches(list)
|
||||
static int
|
||||
_hostlist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
struct member *m;
|
||||
@@ -218,7 +235,7 @@ hostlist_matches(list)
|
||||
break;
|
||||
case ALIAS:
|
||||
if ((a = find_alias(m->name, HOSTALIAS)) != NULL) {
|
||||
rval = hostlist_matches(&a->members);
|
||||
rval = _hostlist_matches(&a->members);
|
||||
if (rval != UNSPEC)
|
||||
matched = m->negated ? !rval : rval;
|
||||
break;
|
||||
@@ -235,6 +252,43 @@ hostlist_matches(list)
|
||||
return(matched);
|
||||
}
|
||||
|
||||
int
|
||||
hostlist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
alias_seqno++;
|
||||
return(_hostlist_matches(list));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for cmnd and args in a list of members.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
*/
|
||||
static int
|
||||
_cmndlist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
struct member *m;
|
||||
int rval, matched = UNSPEC;
|
||||
|
||||
tq_foreach_rev(list, m) {
|
||||
rval = cmnd_matches(m);
|
||||
if (rval != UNSPEC) {
|
||||
matched = m->negated ? !rval : rval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(matched);
|
||||
}
|
||||
|
||||
int
|
||||
cmndlist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
alias_seqno++;
|
||||
return(_cmndlist_matches(list));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check cmnd and args.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
@@ -252,8 +306,9 @@ cmnd_matches(m)
|
||||
matched = !m->negated;
|
||||
break;
|
||||
case ALIAS:
|
||||
alias_seqno++;
|
||||
if ((a = find_alias(m->name, CMNDALIAS)) != NULL) {
|
||||
rval = cmndlist_matches(&a->members);
|
||||
rval = _cmndlist_matches(&a->members);
|
||||
if (rval != UNSPEC)
|
||||
matched = m->negated ? !rval : rval;
|
||||
}
|
||||
@@ -267,27 +322,6 @@ cmnd_matches(m)
|
||||
return(matched);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for cmnd and args in a list of members.
|
||||
* Returns ALLOW, DENY or UNSPEC.
|
||||
*/
|
||||
int
|
||||
cmndlist_matches(list)
|
||||
struct member_list *list;
|
||||
{
|
||||
struct member *m;
|
||||
int rval, matched = UNSPEC;
|
||||
|
||||
tq_foreach_rev(list, m) {
|
||||
rval = cmnd_matches(m);
|
||||
if (rval != UNSPEC) {
|
||||
matched = m->negated ? !rval : rval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(matched);
|
||||
}
|
||||
|
||||
/*
|
||||
* If path doesn't end in /, return TRUE iff cmnd & path name the same inode;
|
||||
* otherwise, return TRUE if user_cmnd names one of the inodes in path.
|
||||
|
14
parse.c
14
parse.c
@@ -464,7 +464,7 @@ display_cmnd(v, pw)
|
||||
* Print the contents of a struct member to stdout
|
||||
*/
|
||||
static void
|
||||
print_member(lbuf, name, type, negated, alias_type)
|
||||
_print_member(lbuf, name, type, negated, alias_type)
|
||||
struct lbuf *lbuf;
|
||||
char *name;
|
||||
int type, negated, alias_type;
|
||||
@@ -492,7 +492,7 @@ print_member(lbuf, name, type, negated, alias_type)
|
||||
tq_foreach_fwd(&a->members, m) {
|
||||
if (m != tq_first(&a->members))
|
||||
lbuf_append(lbuf, ", ", NULL);
|
||||
print_member(lbuf, m->name, m->type,
|
||||
_print_member(lbuf, m->name, m->type,
|
||||
negated ? !m->negated : m->negated, alias_type);
|
||||
}
|
||||
break;
|
||||
@@ -503,3 +503,13 @@ print_member(lbuf, name, type, negated, alias_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_member(lbuf, name, type, negated, alias_type)
|
||||
struct lbuf *lbuf;
|
||||
char *name;
|
||||
int type, negated, alias_type;
|
||||
{
|
||||
alias_seqno++;
|
||||
_print_member(lbuf, name, type, negated, alias_type);
|
||||
}
|
||||
|
6
parse.h
6
parse.h
@@ -119,6 +119,7 @@ struct member {
|
||||
struct alias {
|
||||
char *name; /* alias name */
|
||||
int type; /* {USER,HOST,RUNAS,CMND}ALIAS */
|
||||
unsigned int seqno; /* sequence number */
|
||||
struct member_list members; /* list of alias members */
|
||||
};
|
||||
|
||||
@@ -140,6 +141,11 @@ struct defaults {
|
||||
extern struct userspec_list userspecs;
|
||||
extern struct defaults_list defaults;
|
||||
|
||||
/*
|
||||
* Alias sequence number to avoid loops.
|
||||
*/
|
||||
extern unsigned int alias_seqno;
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
|
Reference in New Issue
Block a user