2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

Refactor common alias code out of cvtsudoers and visudo and into alias.c.

This commit is contained in:
Todd C. Miller 2018-04-02 07:41:09 -06:00
parent dbd5613b1a
commit 18ba38ef4c
4 changed files with 124 additions and 192 deletions

View File

@ -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);
}

View File

@ -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;
}
/*

View File

@ -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);

View File

@ -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)