From: Todd C. Miller Date: Mon, 2 Apr 2018 13:41:09 +0000 (-0600) Subject: Refactor common alias code out of cvtsudoers and visudo and into alias.c. X-Git-Tag: SUDO_1_8_23^2~47 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18ba38ef4c80f47924b2f497c4e071ba173d54ba;p=sudo Refactor common alias code out of cvtsudoers and visudo and into alias.c. --- diff --git a/plugins/sudoers/alias.c b/plugins/sudoers/alias.c index efd380f7e..1227deee2 100644 --- a/plugins/sudoers/alias.c +++ b/plugins/sudoers/alias.c @@ -237,3 +237,109 @@ alias_type_to_string(int alias_type) alias_type == RUNASALIAS ? "Runas_Alias" : "Invalid_Alias"; } + +/* + * Remove the alias of the specified type as well as any other aliases + * referenced by that alias. Stores removed aliases in a freelist. + */ +static bool +alias_remove_recursive(char *name, int type, struct rbtree *freelist) +{ + struct member *m; + struct alias *a; + bool ret = true; + debug_decl(alias_remove_recursive, SUDOERS_DEBUG_ALIAS) + + if ((a = alias_remove(name, type)) != NULL) { + TAILQ_FOREACH(m, &a->members, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, type, freelist)) + ret = false; + } + } + if (rbinsert(freelist, a, NULL) != 0) + ret = false; + } + debug_return_bool(ret); +} + +/* + * Move all aliases referenced by userspecs to used_aliases. + */ +bool +alias_find_used(struct rbtree *used_aliases) +{ + struct privilege *priv; + struct userspec *us; + struct cmndspec *cs; + struct defaults *d; + struct member *m; + int atype, errors = 0; + debug_decl(alias_find_used, SUDOERS_DEBUG_ALIAS) + + /* Move referenced aliases to used_aliases. */ + TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(m, &us->users, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, USERALIAS, used_aliases)) + errors++; + } + } + TAILQ_FOREACH(priv, &us->privileges, entries) { + TAILQ_FOREACH(m, &priv->hostlist, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, HOSTALIAS, used_aliases)) + errors++; + } + } + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases)) + errors++; + } + } + } + if (cs->runasgrouplist != NULL) { + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases)) + errors++; + } + } + } + if ((m = cs->cmnd)->type == ALIAS) { + if (!alias_remove_recursive(m->name, CMNDALIAS, used_aliases)) + errors++; + } + } + } + } + TAILQ_FOREACH(d, &defaults, entries) { + switch (d->type) { + case DEFAULTS_HOST: + atype = HOSTALIAS; + break; + case DEFAULTS_USER: + atype = USERALIAS; + break; + case DEFAULTS_RUNAS: + atype = RUNASALIAS; + break; + case DEFAULTS_CMND: + atype = CMNDALIAS; + break; + default: + continue; /* not an alias */ + } + TAILQ_FOREACH(m, d->binding, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, atype, used_aliases)) + errors++; + } + } + } + + debug_return_int(errors ? false : true); +} diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c index 61ebb2173..4a3a5c3e1 100644 --- a/plugins/sudoers/cvtsudoers.c +++ b/plugins/sudoers/cvtsudoers.c @@ -81,13 +81,13 @@ static void usage(int); static bool convert_sudoers_sudoers(const char *output_file, struct cvtsudoers_config *conf); static bool parse_sudoers(const char *input_file, struct cvtsudoers_config *conf); static bool cvtsudoers_parse_filter(char *expression); -static bool alias_remove_unused(void); static struct cvtsudoers_config *cvtsudoers_conf_read(const char *conf_file); static void cvtsudoers_conf_free(struct cvtsudoers_config *conf); static int cvtsudoers_parse_defaults(char *expression); static int cvtsudoers_parse_suppression(char *expression); static void filter_userspecs(void); static void filter_defaults(struct cvtsudoers_config *conf); +static void alias_remove_unused(void); int main(int argc, char *argv[]) @@ -892,122 +892,29 @@ filter_defaults(struct cvtsudoers_config *conf) debug_return; } -/* - * Remove the alias of the specified type as well as any other aliases - * referenced by that alias. - * XXX - share with visudo - */ -static bool -alias_remove_recursive(char *name, int type, struct rbtree *freelist) -{ - struct member *m; - struct alias *a; - bool ret = true; - debug_decl(alias_remove_recursive, SUDOERS_DEBUG_ALIAS) - - if ((a = alias_remove(name, type)) != NULL) { - TAILQ_FOREACH(m, &a->members, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, type, freelist)) - ret = false; - } - } - if (rbinsert(freelist, a, NULL) != 0) - ret = false; - } - debug_return_bool(ret); -} - /* * Remove unreferenced aliases. - * XXX - share with visudo */ -static bool +static void alias_remove_unused(void) { - struct cmndspec *cs; - struct member *m; - struct privilege *priv; - struct userspec *us; - struct defaults *d; - int atype, errors = 0; struct rbtree *used_aliases; struct rbtree *unused_aliases; debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS) used_aliases = rbcreate(alias_compare); - if (used_aliases == NULL) { - sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - debug_return_int(-1); - } + if (used_aliases == NULL) + sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - /* Move referenced aliases to used_aliases. */ - TAILQ_FOREACH(us, &userspecs, entries) { - TAILQ_FOREACH(m, &us->users, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, USERALIAS, used_aliases)) - errors++; - } - } - TAILQ_FOREACH(priv, &us->privileges, entries) { - TAILQ_FOREACH(m, &priv->hostlist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, HOSTALIAS, used_aliases)) - errors++; - } - } - TAILQ_FOREACH(cs, &priv->cmndlist, entries) { - if (cs->runasuserlist != NULL) { - TAILQ_FOREACH(m, cs->runasuserlist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases)) - errors++; - } - } - } - if (cs->runasgrouplist != NULL) { - TAILQ_FOREACH(m, cs->runasgrouplist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases)) - errors++; - } - } - } - if ((m = cs->cmnd)->type == ALIAS) { - if (!alias_remove_recursive(m->name, CMNDALIAS, used_aliases)) - errors++; - } - } - } - } - TAILQ_FOREACH(d, &defaults, entries) { - switch (d->type) { - case DEFAULTS_HOST: - atype = HOSTALIAS; - break; - case DEFAULTS_USER: - atype = USERALIAS; - break; - case DEFAULTS_RUNAS: - atype = RUNASALIAS; - break; - case DEFAULTS_CMND: - atype = CMNDALIAS; - break; - default: - continue; /* not an alias */ - } - TAILQ_FOREACH(m, d->binding, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, atype, used_aliases)) - errors++; - } - } - } + /* Move all referenced aliases to used_aliases. */ + if (!alias_find_used(used_aliases)) + sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + + /* Only unreferenced aliases are left, swap and free the unused ones. */ unused_aliases = replace_aliases(used_aliases); rbdestroy(unused_aliases, alias_free); - debug_return_int(errors ? false : true); + debug_return; } /* diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 229cf5a7c..91555af91 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -258,6 +258,7 @@ const char *alias_type_to_string(int alias_type); int alias_compare(const void *a1, const void *a2); struct alias *alias_get(char *name, int type); struct alias *alias_remove(char *name, int type); +bool alias_find_used(struct rbtree *used_aliases); void alias_apply(int (*func)(void *, void *), void *cookie); void alias_free(void *a); void alias_put(struct alias *a); diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 749ea9c97..cf787fed3 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -109,7 +109,6 @@ extern void sudoersrestart(FILE *); struct sudo_user sudo_user; struct passwd *list_pw; static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist); -static struct rbtree *alias_freelist; static bool checkonly; static const char short_opts[] = "cf:hqsVx:"; static struct option long_opts[] = { @@ -1014,27 +1013,6 @@ open_sudoers(const char *path, bool doedit, bool *keepopen) debug_return_ptr(fp); } -static bool -alias_remove_recursive(char *name, int type) -{ - struct member *m; - struct alias *a; - bool ret = true; - debug_decl(alias_remove_recursive, SUDOERS_DEBUG_ALIAS) - - if ((a = alias_remove(name, type)) != NULL) { - TAILQ_FOREACH(m, &a->members, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, type)) - ret = false; - } - } - if (rbinsert(alias_freelist, a, NULL) != 0) - ret = false; - } - debug_return_bool(ret); -} - static int check_alias(char *name, int type, char *file, int lineno, bool strict, bool quiet) { @@ -1083,16 +1061,16 @@ check_alias(char *name, int type, char *file, int lineno, bool strict, bool quie static int check_aliases(bool strict, bool quiet) { + struct rbtree *used_aliases; struct cmndspec *cs; struct member *m; struct privilege *priv; struct userspec *us; - struct defaults *d; - int atype, errors = 0; + int errors = 0; debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS) - alias_freelist = rbcreate(alias_compare); - if (alias_freelist == NULL) { + used_aliases = rbcreate(alias_compare); + if (used_aliases == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); debug_return_int(-1); } @@ -1138,69 +1116,9 @@ check_aliases(bool strict, bool quiet) } /* Reverse check (destructive) */ - TAILQ_FOREACH(us, &userspecs, entries) { - TAILQ_FOREACH(m, &us->users, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, USERALIAS)) - errors++; - } - } - TAILQ_FOREACH(priv, &us->privileges, entries) { - TAILQ_FOREACH(m, &priv->hostlist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, HOSTALIAS)) - errors++; - } - } - TAILQ_FOREACH(cs, &priv->cmndlist, entries) { - if (cs->runasuserlist != NULL) { - TAILQ_FOREACH(m, cs->runasuserlist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS)) - errors++; - } - } - } - if (cs->runasgrouplist != NULL) { - TAILQ_FOREACH(m, cs->runasgrouplist, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS)) - errors++; - } - } - } - if ((m = cs->cmnd)->type == ALIAS) { - if (!alias_remove_recursive(m->name, CMNDALIAS)) - errors++; - } - } - } - } - TAILQ_FOREACH(d, &defaults, entries) { - switch (d->type) { - case DEFAULTS_HOST: - atype = HOSTALIAS; - break; - case DEFAULTS_USER: - atype = USERALIAS; - break; - case DEFAULTS_RUNAS: - atype = RUNASALIAS; - break; - case DEFAULTS_CMND: - atype = CMNDALIAS; - break; - default: - continue; /* not an alias */ - } - TAILQ_FOREACH(m, d->binding, entries) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, atype)) - errors++; - } - } - } - rbdestroy(alias_freelist, alias_free); + if (!alias_find_used(used_aliases)) + errors++; + rbdestroy(used_aliases, alias_free); /* If all aliases were referenced we will have an empty tree. */ if (!no_aliases() && !quiet)