From d26d942c22420ffda6f6541478b70fd00c4437c8 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 29 Apr 2010 18:51:04 -0400 Subject: [PATCH] Fix a crash when checking a sudoers file that has aliases that reference themselves. Based on a diff from David Wood. --- plugins/sudoers/visudo.c | 55 +++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 24633843a..1393e1313 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -108,6 +108,7 @@ static int install_sudoers(struct sudoersfile *, int); static int print_unused(void *, void *); static int reparse_sudoers(char *, char *, int, int); 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 setup_signals(void); static void usage(void) __attribute__((__noreturn__)); @@ -931,15 +932,22 @@ get_hostname(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 alias *a; + int error = 0; if ((a = alias_find(name, type)) != NULL) { tq_foreach_fwd(&a->members, m) { 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); if (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(&us->users, m) { 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(&priv->hostlist, m) { 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(&cs->runasuserlist, m) { 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) - (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) { for (m = binding; m != NULL; m = m->next) { 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); /* If all aliases were referenced we will have an empty tree. */ - if (no_aliases()) - return(0); - if (!quiet) { + if (!no_aliases() && !quiet) alias_apply(print_unused, strict ? "Error" : "Warning"); - } - return (strict ? 1 : 0); + + return (strict ? error : 0); } 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 print_unused(void *v1, void *v2) { -- 2.50.1