mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-28 12:57:50 +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" :
|
alias_type == RUNASALIAS ? "Runas_Alias" :
|
||||||
"Invalid_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 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 parse_sudoers(const char *input_file, struct cvtsudoers_config *conf);
|
||||||
static bool cvtsudoers_parse_filter(char *expression);
|
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 struct cvtsudoers_config *cvtsudoers_conf_read(const char *conf_file);
|
||||||
static void cvtsudoers_conf_free(struct cvtsudoers_config *conf);
|
static void cvtsudoers_conf_free(struct cvtsudoers_config *conf);
|
||||||
static int cvtsudoers_parse_defaults(char *expression);
|
static int cvtsudoers_parse_defaults(char *expression);
|
||||||
static int cvtsudoers_parse_suppression(char *expression);
|
static int cvtsudoers_parse_suppression(char *expression);
|
||||||
static void filter_userspecs(void);
|
static void filter_userspecs(void);
|
||||||
static void filter_defaults(struct cvtsudoers_config *conf);
|
static void filter_defaults(struct cvtsudoers_config *conf);
|
||||||
|
static void alias_remove_unused(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@ -892,122 +892,29 @@ filter_defaults(struct cvtsudoers_config *conf)
|
|||||||
debug_return;
|
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.
|
* Remove unreferenced aliases.
|
||||||
* XXX - share with visudo
|
|
||||||
*/
|
*/
|
||||||
static bool
|
static void
|
||||||
alias_remove_unused(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 *used_aliases;
|
||||||
struct rbtree *unused_aliases;
|
struct rbtree *unused_aliases;
|
||||||
debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
used_aliases = rbcreate(alias_compare);
|
used_aliases = rbcreate(alias_compare);
|
||||||
if (used_aliases == NULL) {
|
if (used_aliases == NULL)
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
debug_return_int(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move referenced aliases to used_aliases. */
|
/* Move all referenced aliases to used_aliases. */
|
||||||
TAILQ_FOREACH(us, &userspecs, entries) {
|
if (!alias_find_used(used_aliases))
|
||||||
TAILQ_FOREACH(m, &us->users, entries) {
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
if (m->type == ALIAS) {
|
|
||||||
if (!alias_remove_recursive(m->name, USERALIAS, used_aliases))
|
/* Only unreferenced aliases are left, swap and free the unused ones. */
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unused_aliases = replace_aliases(used_aliases);
|
unused_aliases = replace_aliases(used_aliases);
|
||||||
rbdestroy(unused_aliases, alias_free);
|
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);
|
int alias_compare(const void *a1, const void *a2);
|
||||||
struct alias *alias_get(char *name, int type);
|
struct alias *alias_get(char *name, int type);
|
||||||
struct alias *alias_remove(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_apply(int (*func)(void *, void *), void *cookie);
|
||||||
void alias_free(void *a);
|
void alias_free(void *a);
|
||||||
void alias_put(struct alias *a);
|
void alias_put(struct alias *a);
|
||||||
|
@ -109,7 +109,6 @@ extern void sudoersrestart(FILE *);
|
|||||||
struct sudo_user sudo_user;
|
struct sudo_user sudo_user;
|
||||||
struct passwd *list_pw;
|
struct passwd *list_pw;
|
||||||
static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist);
|
static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist);
|
||||||
static struct rbtree *alias_freelist;
|
|
||||||
static bool checkonly;
|
static bool checkonly;
|
||||||
static const char short_opts[] = "cf:hqsVx:";
|
static const char short_opts[] = "cf:hqsVx:";
|
||||||
static struct option long_opts[] = {
|
static struct option long_opts[] = {
|
||||||
@ -1014,27 +1013,6 @@ open_sudoers(const char *path, bool doedit, bool *keepopen)
|
|||||||
debug_return_ptr(fp);
|
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
|
static int
|
||||||
check_alias(char *name, int type, char *file, int lineno, bool strict, bool quiet)
|
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
|
static int
|
||||||
check_aliases(bool strict, bool quiet)
|
check_aliases(bool strict, bool quiet)
|
||||||
{
|
{
|
||||||
|
struct rbtree *used_aliases;
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
struct defaults *d;
|
int errors = 0;
|
||||||
int atype, errors = 0;
|
|
||||||
debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS)
|
debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
alias_freelist = rbcreate(alias_compare);
|
used_aliases = rbcreate(alias_compare);
|
||||||
if (alias_freelist == NULL) {
|
if (used_aliases == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
@ -1138,69 +1116,9 @@ check_aliases(bool strict, bool quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reverse check (destructive) */
|
/* Reverse check (destructive) */
|
||||||
TAILQ_FOREACH(us, &userspecs, entries) {
|
if (!alias_find_used(used_aliases))
|
||||||
TAILQ_FOREACH(m, &us->users, entries) {
|
|
||||||
if (m->type == ALIAS) {
|
|
||||||
if (!alias_remove_recursive(m->name, USERALIAS))
|
|
||||||
errors++;
|
errors++;
|
||||||
}
|
rbdestroy(used_aliases, alias_free);
|
||||||
}
|
|
||||||
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 all aliases were referenced we will have an empty tree. */
|
/* If all aliases were referenced we will have an empty tree. */
|
||||||
if (!no_aliases() && !quiet)
|
if (!no_aliases() && !quiet)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user