Fix a crash when checking a sudoers file that has aliases that reference

themselves.  Based on a diff from David Wood.
This commit is contained in:
Todd C. Miller
2010-04-29 18:51:04 -04:00
parent 8fc1ebd4f4
commit d26d942c22

View File

@@ -108,6 +108,7 @@ static int install_sudoers(struct sudoersfile *, int);
static int print_unused(void *, void *); static int print_unused(void *, void *);
static int reparse_sudoers(char *, char *, int, int); static int reparse_sudoers(char *, char *, int, int);
static int run_command(char *, char **); static int run_command(char *, char **);
static void print_selfref(char *name, int, int, int);
static void print_undefined(char *name, int, int, int); static void print_undefined(char *name, int, int, int);
static void setup_signals(void); static void setup_signals(void);
static void usage(void) __attribute__((__noreturn__)); static void usage(void) __attribute__((__noreturn__));
@@ -931,15 +932,22 @@ get_hostname(void)
} }
static void static void
alias_remove_recursive(char *name, int type) alias_remove_recursive(char *name, int type, int strict, int quiet)
{ {
struct member *m; struct member *m;
struct alias *a; struct alias *a;
int error = 0;
if ((a = alias_find(name, type)) != NULL) { if ((a = alias_find(name, type)) != NULL) {
tq_foreach_fwd(&a->members, m) { tq_foreach_fwd(&a->members, m) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
alias_remove_recursive(m->name, type); if (strcmp(name, m->name) == 0) {
print_selfref(m->name, type, strict, quiet);
error = 1;
} else {
if (!alias_remove_recursive(m->name, type, strict, quiet))
error = 1;
}
} }
} }
} }
@@ -947,6 +955,7 @@ alias_remove_recursive(char *name, int type)
a = alias_remove(name, type); a = alias_remove(name, type);
if (a) if (a)
rbinsert(alias_freelist, a); rbinsert(alias_freelist, a);
return(error);
} }
/* /*
@@ -1011,21 +1020,28 @@ check_aliases(int strict, int quiet)
tq_foreach_fwd(&userspecs, us) { tq_foreach_fwd(&userspecs, us) {
tq_foreach_fwd(&us->users, m) { tq_foreach_fwd(&us->users, m) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
(void) alias_remove_recursive(m->name, USERALIAS); if (!alias_remove_recursive(m->name, USERALIAS, strict, quiet))
error++;
} }
} }
tq_foreach_fwd(&us->privileges, priv) { tq_foreach_fwd(&us->privileges, priv) {
tq_foreach_fwd(&priv->hostlist, m) { tq_foreach_fwd(&priv->hostlist, m) {
if (m->type == ALIAS) if (m->type == ALIAS)
(void) alias_remove_recursive(m->name, HOSTALIAS); if (!alias_remove_recursive(m->name, HOSTALIAS, strict,
quiet))
error++;
} }
tq_foreach_fwd(&priv->cmndlist, cs) { tq_foreach_fwd(&priv->cmndlist, cs) {
tq_foreach_fwd(&cs->runasuserlist, m) { tq_foreach_fwd(&cs->runasuserlist, m) {
if (m->type == ALIAS) if (m->type == ALIAS)
(void) alias_remove_recursive(m->name, RUNASALIAS); if (!alias_remove_recursive(m->name, RUNASALIAS,
strict, quiet))
error++;
} }
if ((m = cs->cmnd)->type == ALIAS) if ((m = cs->cmnd)->type == ALIAS)
(void) alias_remove_recursive(m->name, CMNDALIAS); if (!alias_remove_recursive(m->name, CMNDALIAS, strict,
quiet))
error++;
} }
} }
} }
@@ -1049,19 +1065,18 @@ check_aliases(int strict, int quiet)
tq_foreach_fwd(&d->binding, binding) { tq_foreach_fwd(&d->binding, binding) {
for (m = binding; m != NULL; m = m->next) { for (m = binding; m != NULL; m = m->next) {
if (m->type == ALIAS) if (m->type == ALIAS)
(void) alias_remove_recursive(m->name, atype); if (!alias_remove_recursive(m->name, atype, strict, quiet))
error++;
} }
} }
} }
rbdestroy(alias_freelist, alias_free); rbdestroy(alias_freelist, alias_free);
/* If all aliases were referenced we will have an empty tree. */ /* If all aliases were referenced we will have an empty tree. */
if (no_aliases()) if (!no_aliases() && !quiet)
return(0);
if (!quiet) {
alias_apply(print_unused, strict ? "Error" : "Warning"); alias_apply(print_unused, strict ? "Error" : "Warning");
}
return (strict ? 1 : 0); return (strict ? error : 0);
} }
static void static void
@@ -1076,6 +1091,22 @@ print_undefined(char *name, int type, int strict, int quiet)
} }
} }
static void
print_selfref(name, type, strict, quiet)
char *name;
int type;
int strict;
int quiet;
{
if (!quiet) {
warningx("%s: %s_Alias `%s' references self",
strict ? "Error" : "Warning",
type == HOSTALIAS ? "Host" : type == CMNDALIAS ? "Cmnd" :
type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" :
"Unknown", name);
}
}
static int static int
print_unused(void *v1, void *v2) print_unused(void *v1, void *v2)
{ {