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:
parent
dbd5613b1a
commit
18ba38ef4c
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user