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:
@@ -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)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user