o Move userspecs, defaults and aliases into a new struct sudoers_parse_tree.

o The parse tree is now passed to the alias, match and defaults functions.
o The nss API has been changed so that the nss parse() function returns
  a pointer to a struct sudoers_parse_tree which will be filled in
  by the getdefs() and query() functions.
This commit is contained in:
Todd C. Miller
2018-07-26 15:12:33 -06:00
parent 86413f95ec
commit 70d519c8ad
19 changed files with 736 additions and 640 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005, 2007-2016
* Copyright (c) 2004-2005, 2007-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -35,16 +35,11 @@
#include "redblack.h"
#include <gram.h>
/*
* Globals
*/
static struct rbtree *aliases;
/*
* Comparison function for the red-black tree.
* Aliases are sorted by name with the type used as a tie-breaker.
*/
int
static int
alias_compare(const void *v1, const void *v2)
{
const struct alias *a1 = (const struct alias *)v1;
@@ -68,16 +63,19 @@ alias_compare(const void *v1, const void *v2)
* alias to mark it as unused.
*/
struct alias *
alias_get(const char *name, int type)
alias_get(struct sudoers_parse_tree *parse_tree, const char *name, int type)
{
struct alias key;
struct rbnode *node;
struct alias *a = NULL;
debug_decl(alias_get, SUDOERS_DEBUG_ALIAS)
if (parse_tree->aliases == NULL)
debug_return_ptr(NULL);
key.name = (char *)name;
key.type = type;
if ((node = rbfind(aliases, &key)) != NULL) {
if ((node = rbfind(parse_tree->aliases, &key)) != NULL) {
/*
* Check whether this alias is already in use.
* If so, we've detected a loop. If not, set the flag,
@@ -112,12 +110,20 @@ alias_put(struct alias *a)
* Returns NULL on success and an error string on failure.
*/
const char *
alias_add(char *name, int type, char *file, int lineno, struct member *members)
alias_add(struct sudoers_parse_tree *parse_tree, char *name, int type,
char *file, int lineno, struct member *members)
{
static char errbuf[512];
struct alias *a;
debug_decl(alias_add, SUDOERS_DEBUG_ALIAS)
if (parse_tree->aliases == NULL) {
if ((parse_tree->aliases = alloc_aliases()) == NULL) {
strlcpy(errbuf, N_("unable to allocate memory"), sizeof(errbuf));
debug_return_str(errbuf);
}
}
a = calloc(1, sizeof(*a));
if (a == NULL) {
strlcpy(errbuf, N_("unable to allocate memory"), sizeof(errbuf));
@@ -129,9 +135,10 @@ alias_add(char *name, int type, char *file, int lineno, struct member *members)
a->file = rcstr_addref(file);
a->lineno = lineno;
HLTQ_TO_TAILQ(&a->members, members, entries);
switch (rbinsert(aliases, a, NULL)) {
switch (rbinsert(parse_tree->aliases, a, NULL)) {
case 1:
snprintf(errbuf, sizeof(errbuf), N_("Alias \"%s\" already defined"), name);
snprintf(errbuf, sizeof(errbuf), N_("Alias \"%s\" already defined"),
name);
alias_free(a);
debug_return_str(errbuf);
case -1:
@@ -146,37 +153,26 @@ alias_add(char *name, int type, char *file, int lineno, struct member *members)
* Apply a function to each alias entry and pass in a cookie.
*/
void
alias_apply(int (*func)(void *, void *), void *cookie)
alias_apply(struct sudoers_parse_tree *parse_tree, int (*func)(void *, void *),
void *cookie)
{
debug_decl(alias_apply, SUDOERS_DEBUG_ALIAS)
rbapply(aliases, func, cookie, inorder);
if (parse_tree->aliases != NULL)
rbapply(parse_tree->aliases, func, cookie, inorder);
debug_return;
}
/*
* Returns true if there are no aliases, else false.
* Returns true if there are no aliases in the parse_tree, else false.
*/
bool
no_aliases(void)
no_aliases(struct sudoers_parse_tree *parse_tree)
{
debug_decl(no_aliases, SUDOERS_DEBUG_ALIAS)
debug_return_bool(rbisempty(aliases));
}
/*
* Replace the aliases tree with a new one, returns the old.
*/
struct rbtree *
replace_aliases(struct rbtree *new_aliases)
{
struct rbtree *old_aliases = aliases;
debug_decl(replace_aliases, SUDOERS_DEBUG_ALIAS)
aliases = new_aliases;
debug_return_ptr(old_aliases);
debug_return_bool(parse_tree->aliases == NULL ||
rbisempty(parse_tree->aliases));
}
/*
@@ -202,31 +198,37 @@ alias_free(void *v)
* Find the named alias, remove it from the tree and return it.
*/
struct alias *
alias_remove(char *name, int type)
alias_remove(struct sudoers_parse_tree *parse_tree, char *name, int type)
{
struct rbnode *node;
struct alias key;
debug_decl(alias_remove, SUDOERS_DEBUG_ALIAS)
if (parse_tree->aliases != NULL) {
key.name = name;
key.type = type;
if ((node = rbfind(aliases, &key)) == NULL) {
errno = ENOENT;
return NULL;
if ((node = rbfind(parse_tree->aliases, &key)) != NULL)
debug_return_ptr(rbdelete(parse_tree->aliases, node));
}
debug_return_ptr(rbdelete(aliases, node));
errno = ENOENT;
debug_return_ptr(NULL);
}
bool
init_aliases(void)
struct rbtree *
alloc_aliases(void)
{
debug_decl(init_aliases, SUDOERS_DEBUG_ALIAS)
debug_decl(alloc_aliases, SUDOERS_DEBUG_ALIAS)
debug_return_ptr(rbcreate(alias_compare));
}
void
free_aliases(struct rbtree *aliases)
{
debug_decl(free_aliases, SUDOERS_DEBUG_ALIAS)
if (aliases != NULL)
rbdestroy(aliases, alias_free);
aliases = rbcreate(alias_compare);
debug_return_bool(aliases != NULL);
}
const char *
@@ -244,17 +246,18 @@ alias_type_to_string(int alias_type)
* referenced by that alias. Stores removed aliases in a freelist.
*/
static bool
alias_remove_recursive(char *name, int type, struct rbtree *freelist)
alias_remove_recursive(struct sudoers_parse_tree *parse_tree, 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) {
if ((a = alias_remove(parse_tree, name, type)) != NULL) {
TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, type, freelist))
if (!alias_remove_recursive(parse_tree, m->name, type, freelist))
ret = false;
}
}
@@ -264,81 +267,80 @@ alias_remove_recursive(char *name, int type, struct rbtree *freelist)
debug_return_bool(ret);
}
static int
alias_find_used_members(struct sudoers_parse_tree *parse_tree,
struct member_list *members, int atype, struct rbtree *used_aliases)
{
struct member *m;
int errors = 0;
debug_decl(alias_find_used_members, SUDOERS_DEBUG_ALIAS)
if (members != NULL) {
TAILQ_FOREACH(m, members, entries) {
if (m->type != ALIAS)
continue;
if (!alias_remove_recursive(parse_tree, m->name, atype, used_aliases))
errors++;
}
}
debug_return_int(errors);
}
/*
* Move all aliases referenced by userspecs to used_aliases.
*/
bool
alias_find_used(struct rbtree *used_aliases)
alias_find_used(struct sudoers_parse_tree *parse_tree, struct rbtree *used_aliases)
{
struct privilege *priv;
struct userspec *us;
struct cmndspec *cs;
struct defaults *d;
struct member *m;
int atype, errors = 0;
int 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(us, &parse_tree->userspecs, entries) {
errors += alias_find_used_members(parse_tree, &us->users,
USERALIAS, used_aliases);
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++;
}
}
errors += alias_find_used_members(parse_tree, &priv->hostlist,
HOSTALIAS, used_aliases);
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++;
}
}
}
errors += alias_find_used_members(parse_tree, cs->runasuserlist,
RUNASALIAS, used_aliases);
errors += alias_find_used_members(parse_tree, cs->runasgrouplist,
RUNASALIAS, used_aliases);
if ((m = cs->cmnd)->type == ALIAS) {
if (!alias_remove_recursive(m->name, CMNDALIAS, used_aliases))
if (!alias_remove_recursive(parse_tree, m->name, CMNDALIAS,
used_aliases))
errors++;
}
}
}
}
TAILQ_FOREACH(d, &defaults, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
atype = HOSTALIAS;
errors += alias_find_used_members(parse_tree, d->binding,
HOSTALIAS, used_aliases);
break;
case DEFAULTS_USER:
atype = USERALIAS;
errors += alias_find_used_members(parse_tree, d->binding,
USERALIAS, used_aliases);
break;
case DEFAULTS_RUNAS:
atype = RUNASALIAS;
errors += alias_find_used_members(parse_tree, d->binding,
RUNASALIAS, used_aliases);
break;
case DEFAULTS_CMND:
atype = CMNDALIAS;
errors += alias_find_used_members(parse_tree, d->binding,
CMNDALIAS, used_aliases);
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++;
}
break;
}
}

View File

@@ -703,7 +703,7 @@ userlist_matches_filter(struct member_list *users, struct cvtsudoers_config *con
pw.pw_uid = (uid_t)-1;
pw.pw_gid = (gid_t)-1;
if (user_matches(&pw, m) == true)
if (user_matches(&parsed_policy, &pw, m) == true)
matched = true;
} else {
STAILQ_FOREACH(s, &filters->users, entries) {
@@ -729,7 +729,7 @@ userlist_matches_filter(struct member_list *users, struct cvtsudoers_config *con
if (pw == NULL)
continue;
if (user_matches(pw, m) == true)
if (user_matches(&parsed_policy, pw, m) == true)
matched = true;
sudo_pw_delref(pw);
@@ -804,7 +804,7 @@ hostlist_matches_filter(struct member_list *hostlist, struct cvtsudoers_config *
/* Only need one host in the filter to match. */
/* XXX - can't use netgroup_tuple with NULL pw */
if (host_matches(NULL, lhost, shost, m) == true) {
if (host_matches(&parsed_policy, NULL, lhost, shost, m) == true) {
matched = true;
break;
}
@@ -840,8 +840,10 @@ print_defaults_sudoers(struct sudo_lbuf *lbuf, bool expand_aliases)
struct defaults *def, *next;
debug_decl(print_defaults_sudoers, SUDOERS_DEBUG_UTIL)
TAILQ_FOREACH_SAFE(def, &defaults, entries, next)
sudoers_format_default_line(lbuf, def, &next, expand_aliases);
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next) {
sudoers_format_default_line(lbuf, &parsed_policy, def, &next,
expand_aliases);
}
debug_return_bool(!sudo_lbuf_error(lbuf));
}
@@ -859,7 +861,7 @@ print_alias_sudoers(void *v1, void *v2)
TAILQ_FOREACH(m, &a->members, entries) {
if (m != TAILQ_FIRST(&a->members))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, NULL, UNSPEC);
sudoers_format_member(lbuf, &parsed_policy, m, NULL, UNSPEC);
}
sudo_lbuf_append(lbuf, "\n");
@@ -874,7 +876,7 @@ print_aliases_sudoers(struct sudo_lbuf *lbuf)
{
debug_decl(print_aliases_sudoers, SUDOERS_DEBUG_UTIL)
alias_apply(print_alias_sudoers, lbuf);
alias_apply(&parsed_policy, print_alias_sudoers, lbuf);
debug_return_bool(!sudo_lbuf_error(lbuf));
}
@@ -905,9 +907,9 @@ filter_userspecs(struct cvtsudoers_config *conf)
* host lists. It acts more like a grep than a true filter.
* In the future, we may want to add a prune option.
*/
TAILQ_FOREACH_SAFE(us, &userspecs, entries, next_us) {
TAILQ_FOREACH_SAFE(us, &parsed_policy.userspecs, entries, next_us) {
if (!userlist_matches_filter(&us->users, conf)) {
TAILQ_REMOVE(&userspecs, us, entries);
TAILQ_REMOVE(&parsed_policy.userspecs, us, entries);
free_userspec(us);
continue;
}
@@ -918,7 +920,7 @@ filter_userspecs(struct cvtsudoers_config *conf)
}
}
if (TAILQ_EMPTY(&us->privileges)) {
TAILQ_REMOVE(&userspecs, us, entries);
TAILQ_REMOVE(&parsed_policy.userspecs, us, entries);
free_userspec(us);
continue;
}
@@ -942,7 +944,8 @@ alias_matches(const char *name, const char *alias_name, int alias_type)
if (strcmp(name, alias_name) == 0)
debug_return_bool(true);
if ((a = alias_get(alias_name, alias_type)) != NULL) {
a = alias_get(&parsed_policy, alias_name, alias_type);
if (a != NULL) {
TAILQ_FOREACH(m, &a->members, entries) {
if (m->type != ALIAS)
continue;
@@ -975,7 +978,7 @@ alias_used_by_userspecs(struct member_list *user_aliases,
debug_decl(alias_used_by_userspecs, SUDOERS_DEBUG_ALIAS)
/* Iterate over the policy, checking for aliases. */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) {
TAILQ_FOREACH_SAFE(us, &parsed_policy.userspecs, entries, us_next) {
TAILQ_FOREACH_SAFE(m, &us->users, entries, m_next) {
if (m->type == ALIAS) {
/* If alias is used, remove from user_aliases and free. */
@@ -1055,13 +1058,14 @@ filter_defaults(struct cvtsudoers_config *conf)
struct member_list *prev_binding = NULL;
struct defaults *def, *def_next;
struct member *m, *m_next;
struct alias *a;
int alias_type;
debug_decl(filter_defaults, SUDOERS_DEBUG_DEFAULTS)
if (filters == NULL && conf->defaults == CVT_DEFAULTS_ALL)
debug_return;
TAILQ_FOREACH_SAFE(def, &defaults, entries, def_next) {
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, def_next) {
bool keep = true;
switch (def->type) {
@@ -1118,20 +1122,21 @@ filter_defaults(struct cvtsudoers_config *conf)
TAILQ_INSERT_TAIL(&cmnd_aliases, m, entries);
break;
default:
sudo_fatalx_nodebug("unexpected alias type %d", alias_type);
sudo_fatalx_nodebug("unexpected alias type %d",
alias_type);
break;
}
}
}
}
TAILQ_REMOVE(&defaults, def, entries);
TAILQ_REMOVE(&parsed_policy.defaults, def, entries);
free_default(def, &prev_binding);
if (prev_binding != NULL) {
/* Remove and free Defaults that share the same binding. */
while (def_next != NULL && def_next->binding == prev_binding) {
def = def_next;
def_next = TAILQ_NEXT(def, entries);
TAILQ_REMOVE(&defaults, def, entries);
TAILQ_REMOVE(&parsed_policy.defaults, def, entries);
free_default(def, &prev_binding);
}
}
@@ -1144,22 +1149,22 @@ filter_defaults(struct cvtsudoers_config *conf)
alias_used_by_userspecs(&user_aliases, &runas_aliases, &host_aliases,
&cmnd_aliases);
TAILQ_FOREACH_SAFE(m, &user_aliases, entries, m_next) {
struct alias *a = alias_remove(m->name, USERALIAS);
a = alias_remove(&parsed_policy, m->name, USERALIAS);
alias_free(a);
free_member(m);
}
TAILQ_FOREACH_SAFE(m, &runas_aliases, entries, m_next) {
struct alias *a = alias_remove(m->name, RUNASALIAS);
a = alias_remove(&parsed_policy, m->name, RUNASALIAS);
alias_free(a);
free_member(m);
}
TAILQ_FOREACH_SAFE(m, &host_aliases, entries, m_next) {
struct alias *a = alias_remove(m->name, HOSTALIAS);
a = alias_remove(&parsed_policy, m->name, HOSTALIAS);
alias_free(a);
free_member(m);
}
TAILQ_FOREACH_SAFE(m, &cmnd_aliases, entries, m_next) {
struct alias *a = alias_remove(m->name, CMNDALIAS);
a = alias_remove(&parsed_policy, m->name, CMNDALIAS);
alias_free(a);
free_member(m);
}
@@ -1174,20 +1179,19 @@ static void
alias_remove_unused(void)
{
struct rbtree *used_aliases;
struct rbtree *unused_aliases;
debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS)
used_aliases = rbcreate(alias_compare);
used_aliases = alloc_aliases();
if (used_aliases == NULL)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
/* Move all referenced aliases to used_aliases. */
if (!alias_find_used(used_aliases))
if (!alias_find_used(&parsed_policy, 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);
free_aliases(parsed_policy.aliases);
parsed_policy.aliases = used_aliases;
debug_return;
}
@@ -1224,7 +1228,7 @@ alias_prune(struct cvtsudoers_config *conf)
{
debug_decl(alias_prune, SUDOERS_DEBUG_ALIAS)
alias_apply(alias_prune_helper, conf);
alias_apply(&parsed_policy, alias_prune_helper, conf);
debug_return;
}
@@ -1271,7 +1275,7 @@ convert_sudoers_sudoers(const char *output_file, struct cvtsudoers_config *conf)
/* Print User_Specs, separated by blank lines. */
if (!ISSET(conf->suppress, SUPPRESS_PRIVS)) {
if (!sudoers_format_userspecs(&lbuf, &userspecs, "\n",
if (!sudoers_format_userspecs(&lbuf, &parsed_policy, "\n",
conf->expand_aliases, true)) {
goto done;
}

View File

@@ -475,7 +475,7 @@ print_member_json_int(FILE *fp, char *name, int type, bool negated,
struct alias *a;
struct member *m;
if ((a = alias_get(value.u.string, alias_type)) != NULL) {
if ((a = alias_get(&parsed_policy, value.u.string, alias_type)) != NULL) {
TAILQ_FOREACH(m, &a->members, entries) {
print_member_json_int(fp, m->name, m->type,
negated ? !m->negated : m->negated,
@@ -661,13 +661,13 @@ print_defaults_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
int type;
debug_decl(print_defaults_json, SUDOERS_DEBUG_UTIL)
if (TAILQ_EMPTY(&defaults))
if (TAILQ_EMPTY(&parsed_policy.defaults))
debug_return_bool(need_comma);
fprintf(fp, "%s\n%*s\"Defaults\": [\n", need_comma ? "," : "", indent, "");
indent += 4;
TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next) {
type = get_defaults_type(def);
if (type == -1) {
sudo_warnx(U_("unknown defaults entry \"%s\""), def->var);
@@ -745,7 +745,7 @@ print_aliases_by_type_json(FILE *fp, int alias_type, const char *title,
closure.alias_type = alias_type;
closure.title = title;
closure.need_comma = need_comma;
alias_apply(print_alias_json, &closure);
alias_apply(&parsed_policy, print_alias_json, &closure);
if (closure.count != 0) {
print_indent(fp, closure.indent);
fputs("]\n", fp);
@@ -1083,12 +1083,12 @@ print_userspecs_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
struct userspec *us;
debug_decl(print_userspecs_json, SUDOERS_DEBUG_UTIL)
if (TAILQ_EMPTY(&userspecs))
if (TAILQ_EMPTY(&parsed_policy.userspecs))
debug_return_bool(need_comma);
fprintf(fp, "%s\n%*s\"User_Specs\": [\n", need_comma ? "," : "", indent, "");
indent += 4;
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(us, &parsed_policy.userspecs, entries) {
print_userspec_json(fp, us, indent, expand_aliases);
}
indent -= 4;

View File

@@ -167,14 +167,14 @@ print_global_defaults_ldif(FILE *fp, const char *base)
sudo_lbuf_init(&lbuf, NULL, 0, NULL, 80);
TAILQ_FOREACH(opt, &defaults, entries) {
TAILQ_FOREACH(opt, &parsed_policy.defaults, entries) {
/* Skip bound Defaults (unsupported). */
if (opt->type == DEFAULTS) {
count++;
} else {
lbuf.len = 0;
sudo_lbuf_append(&lbuf, "# ");
sudoers_format_default_line(&lbuf, opt, false, true);
sudoers_format_default_line(&lbuf, &parsed_policy, opt, false, true);
fprintf(fp, "# Unable to translate %s:%d\n%s\n",
opt->file, opt->lineno, lbuf.buf);
}
@@ -195,7 +195,7 @@ print_global_defaults_ldif(FILE *fp, const char *base)
print_attribute_ldif(fp, "cn", "defaults");
print_attribute_ldif(fp, "description", "Default sudoOption's go here");
print_options_ldif(fp, &defaults);
print_options_ldif(fp, &parsed_policy.defaults);
putc('\n', fp);
debug_return_bool(!ferror(fp));
@@ -239,7 +239,7 @@ print_member_ldif(FILE *fp, char *name, int type, bool negated,
free(attr_val);
break;
case ALIAS:
if ((a = alias_get(name, alias_type)) != NULL) {
if ((a = alias_get(&parsed_policy, name, alias_type)) != NULL) {
TAILQ_FOREACH(m, &a->members, entries) {
print_member_ldif(fp, m->name, m->type,
negated ? !m->negated : m->negated, alias_type, attr_name);
@@ -601,7 +601,7 @@ print_userspecs_ldif(FILE *fp, struct cvtsudoers_config *conf)
struct userspec *us;
debug_decl(print_userspecs_ldif, SUDOERS_DEBUG_UTIL)
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(us, &parsed_policy.userspecs, entries) {
if (!print_userspec_ldif(fp, us, conf))
debug_return_bool(false);
}
@@ -860,7 +860,7 @@ ldif_store_options(struct cvtsudoers_str_list *options)
U_("unable to allocate memory"));
}
}
TAILQ_INSERT_TAIL(&defaults, d, entries);
TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
}
debug_return;
}
@@ -928,7 +928,7 @@ role_to_sudoers(struct sudo_role *role, bool store_options,
if (reuse_userspec) {
/* Re-use the previous userspec */
us = TAILQ_LAST(&userspecs, userspec_list);
us = TAILQ_LAST(&parsed_policy.userspecs, userspec_list);
} else {
/* Allocate a new userspec and fill in the user list. */
if ((us = calloc(1, sizeof(*us))) == NULL) {
@@ -1039,7 +1039,7 @@ role_to_sudoers(struct sudo_role *role, bool store_options,
/* Add finished userspec to the list if new. */
if (!reuse_userspec)
TAILQ_INSERT_TAIL(&userspecs, us, entries);
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, us, entries);
debug_return;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005, 2007-2017
* Copyright (c) 1999-2005, 2007-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -696,7 +696,8 @@ default_type_matches(struct defaults *d, int what)
* Returns true if it matches, else false.
*/
static bool
default_binding_matches(struct defaults *d, int what)
default_binding_matches(struct sudoers_parse_tree *parse_tree,
struct defaults *d, int what)
{
debug_decl(default_binding_matches, SUDOERS_DEBUG_DEFAULTS)
@@ -705,19 +706,19 @@ default_binding_matches(struct defaults *d, int what)
debug_return_bool(true);
break;
case DEFAULTS_USER:
if (userlist_matches(sudo_user.pw, d->binding) == ALLOW)
if (userlist_matches(parse_tree, sudo_user.pw, d->binding) == ALLOW)
debug_return_bool(true);
break;
case DEFAULTS_RUNAS:
if (runaslist_matches(d->binding, NULL, NULL, NULL) == ALLOW)
if (runaslist_matches(parse_tree, d->binding, NULL, NULL, NULL) == ALLOW)
debug_return_bool(true);
break;
case DEFAULTS_HOST:
if (hostlist_matches(sudo_user.pw, d->binding) == ALLOW)
if (hostlist_matches(parse_tree, sudo_user.pw, d->binding) == ALLOW)
debug_return_bool(true);
break;
case DEFAULTS_CMND:
if (cmndlist_matches(d->binding) == ALLOW)
if (cmndlist_matches(parse_tree, d->binding) == ALLOW)
debug_return_bool(true);
break;
}
@@ -729,7 +730,7 @@ default_binding_matches(struct defaults *d, int what)
* Pass in an OR'd list of which default types to update.
*/
bool
update_defaults(struct defaults_list *defs, int what, bool quiet)
update_defaults(struct sudoers_parse_tree *parse_tree, int what, bool quiet)
{
struct defaults *d;
bool ret = true;
@@ -741,14 +742,14 @@ update_defaults(struct defaults_list *defs, int what, bool quiet)
/*
* First apply Defaults values marked as early.
*/
TAILQ_FOREACH(d, defs, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
struct early_default *early = is_early_default(d->var);
if (early == NULL)
continue;
/* Defaults type and binding must match. */
if (!default_type_matches(d, what) ||
!default_binding_matches(d, what))
!default_binding_matches(parse_tree, d, what))
continue;
/* Copy the value to sudo_defs_table and mark as early. */
@@ -763,14 +764,14 @@ update_defaults(struct defaults_list *defs, int what, bool quiet)
/*
* Then set the rest of the defaults.
*/
TAILQ_FOREACH(d, defs, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
/* Skip Defaults marked as early, we already did them. */
if (is_early_default(d->var))
continue;
/* Defaults type and binding must match. */
if (!default_type_matches(d, what) ||
!default_binding_matches(d, what))
!default_binding_matches(parse_tree, d, what))
continue;
/* Copy the value to sudo_defs_table and run callback (if any) */
@@ -784,14 +785,14 @@ update_defaults(struct defaults_list *defs, int what, bool quiet)
* Check all defaults entries without actually setting them.
*/
bool
check_defaults(bool quiet)
check_defaults(struct sudoers_parse_tree *parse_tree, bool quiet)
{
struct defaults *d;
bool ret = true;
int idx;
debug_decl(check_defaults, SUDOERS_DEBUG_DEFAULTS)
TAILQ_FOREACH(d, &defaults, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
idx = find_default(d->var, d->file, d->lineno, quiet);
if (idx != -1) {
struct sudo_defs_types *def = &sudo_defs_table[idx];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005, 2008-2016
* Copyright (c) 1999-2005, 2008-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -122,15 +122,15 @@ struct early_default {
/*
* Prototypes
*/
struct defaults_list;
struct sudoers_parse_tree;
void dump_default(void);
bool init_defaults(void);
struct early_default *is_early_default(const char *name);
bool run_early_defaults(void);
bool set_early_default(const char *var, const char *val, int op, const char *file, int lineno, bool quiet, struct early_default *early);
bool set_default(const char *var, const char *val, int op, const char *file, int lineno, bool quiet);
bool update_defaults(struct defaults_list *defs, int what, bool quiet);
bool check_defaults(bool quiet);
bool update_defaults(struct sudoers_parse_tree *parse_tree, int what, bool quiet);
bool check_defaults(struct sudoers_parse_tree *parse_tree, bool quiet);
extern struct sudo_defs_types sudo_defs_table[];

View File

@@ -40,8 +40,7 @@
struct sudo_file_handle {
FILE *fp;
struct defaults_list defaults;
struct userspec_list userspecs;
struct sudoers_parse_tree parse_tree;
};
static int
@@ -54,9 +53,7 @@ sudo_file_close(struct sudo_nss *nss)
fclose(handle->fp);
sudoersin = NULL;
free_userspecs(&handle->userspecs);
free_defaults(&handle->defaults);
free_parse_tree(&handle->parse_tree);
free(handle);
nss->handle = NULL;
}
@@ -83,8 +80,7 @@ sudo_file_open(struct sudo_nss *nss)
if (handle != NULL) {
handle->fp = open_sudoers(sudoers_file, false, NULL);
if (handle->fp != NULL) {
TAILQ_INIT(&handle->userspecs);
TAILQ_INIT(&handle->defaults);
init_parse_tree(&handle->parse_tree);
} else {
free(handle);
handle = NULL;
@@ -95,9 +91,9 @@ sudo_file_open(struct sudo_nss *nss)
}
/*
* Parse the specified sudoers file.
* Parse and return the specified sudoers file.
*/
static int
static struct sudoers_parse_tree *
sudo_file_parse(struct sudo_nss *nss)
{
debug_decl(sudo_file_close, SUDOERS_DEBUG_NSS)
@@ -106,7 +102,7 @@ sudo_file_parse(struct sudo_nss *nss)
if (handle == NULL || handle->fp == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: called with NULL %s",
__func__, handle ? "file pointer" : "handle");
debug_return_int(-1);
debug_return_ptr(NULL);
}
sudoersin = handle->fp;
@@ -117,49 +113,33 @@ sudo_file_parse(struct sudo_nss *nss)
} else {
log_warningx(SLOG_SEND_MAIL, N_("parse error in %s"), errorfile);
}
debug_return_int(-1);
debug_return_ptr(NULL);
}
/* Move parsed userspecs and defaults to nss structure. */
TAILQ_CONCAT(&handle->userspecs, &userspecs, entries);
TAILQ_CONCAT(&handle->defaults, &defaults, entries);
/* Move parsed sudoers policy to nss handle. */
reparent_parse_tree(&handle->parse_tree);
debug_return_ptr(&handle->parse_tree);
}
/*
* No need for explicit sudoers queries, the parse function handled it.
*/
static int
sudo_file_query(struct sudo_nss *nss, struct passwd *pw)
{
debug_decl(sudo_file_query, SUDOERS_DEBUG_NSS)
debug_return_int(0);
}
/*
* We return all cached userspecs, the parse functions will
* perform matching against pw for us.
* No need to get defaults for sudoers file, the parse function handled it.
*/
static struct userspec_list *
sudo_file_query(struct sudo_nss *nss, struct passwd *pw)
{
struct sudo_file_handle *handle = nss->handle;
debug_decl(sudo_file_query, SUDOERS_DEBUG_NSS)
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
}
debug_return_ptr(&handle->userspecs);
}
/*
* Return cached defaults entries.
*/
static struct defaults_list *
static int
sudo_file_getdefs(struct sudo_nss *nss)
{
debug_decl(sudo_file_getdefs, SUDOERS_DEBUG_NSS)
struct sudo_file_handle *handle = nss->handle;
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
}
debug_return_ptr(&handle->defaults);
debug_return_int(0);
}
/* sudo_nss implementation */

View File

@@ -37,8 +37,9 @@
* the specified separator (which must not be NULL in the UNSPEC case).
*/
static bool
sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
bool negated, const char *separator, int alias_type)
sudoers_format_member_int(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, char *name, int type, bool negated,
const char *separator, int alias_type)
{
struct alias *a;
struct member *m;
@@ -81,13 +82,13 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
goto print_word;
case ALIAS:
if (alias_type != UNSPEC) {
if ((a = alias_get(name, alias_type)) != NULL) {
if ((a = alias_get(parse_tree, name, alias_type)) != NULL) {
TAILQ_FOREACH(m, &a->members, entries) {
if (m != TAILQ_FIRST(&a->members))
sudo_lbuf_append(lbuf, "%s", separator);
sudoers_format_member_int(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, separator,
alias_type);
sudoers_format_member_int(lbuf, parse_tree, m->name,
m->type, negated ? !m->negated : m->negated,
separator, alias_type);
}
alias_put(a);
break;
@@ -116,11 +117,12 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
}
bool
sudoers_format_member(struct sudo_lbuf *lbuf, struct member *m,
sudoers_format_member(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, struct member *m,
const char *separator, int alias_type)
{
return sudoers_format_member_int(lbuf, m->name, m->type, m->negated,
separator, alias_type);
return sudoers_format_member_int(lbuf, parse_tree, m->name, m->type,
m->negated, separator, alias_type);
}
#define FIELD_CHANGED(ocs, ncs, fld) \
@@ -133,7 +135,8 @@ sudoers_format_member(struct sudo_lbuf *lbuf, struct member *m,
* Write a cmndspec to lbuf in sudoers format.
*/
bool
sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs,
sudoers_format_cmndspec(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, struct cmndspec *cs,
struct cmndspec *prev_cs, bool expand_aliases)
{
debug_decl(sudoers_format_cmndspec, SUDOERS_DEBUG_UTIL)
@@ -185,7 +188,7 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs,
sudo_lbuf_append(lbuf, cs->tags.send_mail ? "MAIL: " : "NOMAIL: ");
if (TAG_CHANGED(prev_cs, cs, follow))
sudo_lbuf_append(lbuf, cs->tags.follow ? "FOLLOW: " : "NOFOLLOW: ");
sudoers_format_member(lbuf, cs->cmnd, ", ",
sudoers_format_member(lbuf, parse_tree, cs->cmnd, ", ",
expand_aliases ? CMNDALIAS : UNSPEC);
debug_return_bool(!sudo_lbuf_error(lbuf));
}
@@ -194,7 +197,8 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs,
* Write a privilege to lbuf in sudoers format.
*/
bool
sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
sudoers_format_privilege(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, struct privilege *priv,
bool expand_aliases)
{
struct cmndspec *cs, *prev_cs;
@@ -205,7 +209,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m != TAILQ_FIRST(&priv->hostlist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ",
sudoers_format_member(lbuf, parse_tree, m, ", ",
expand_aliases ? HOSTALIAS : UNSPEC);
}
@@ -222,7 +226,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ",
sudoers_format_member(lbuf, parse_tree, m, ", ",
expand_aliases ? RUNASALIAS : UNSPEC);
}
}
@@ -231,7 +235,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ",
sudoers_format_member(lbuf, parse_tree, m, ", ",
expand_aliases ? RUNASALIAS : UNSPEC);
}
}
@@ -240,7 +244,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
sudo_lbuf_append(lbuf, ", ");
}
sudoers_format_cmndspec(lbuf, cs, prev_cs, expand_aliases);
sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, expand_aliases);
prev_cs = cs;
}
@@ -251,8 +255,9 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
* Write a userspec to lbuf in sudoers format.
*/
bool
sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
bool expand_aliases)
sudoers_format_userspec(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree,
struct userspec *us, bool expand_aliases)
{
struct privilege *priv;
struct sudoers_comment *comment;
@@ -268,7 +273,7 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
TAILQ_FOREACH(m, &us->users, entries) {
if (m != TAILQ_FIRST(&us->users))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ",
sudoers_format_member(lbuf, parse_tree, m, ", ",
expand_aliases ? USERALIAS : UNSPEC);
}
@@ -277,7 +282,7 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
sudo_lbuf_append(lbuf, " : ");
else
sudo_lbuf_append(lbuf, " ");
if (!sudoers_format_privilege(lbuf, priv, expand_aliases))
if (!sudoers_format_privilege(lbuf, parse_tree, priv, expand_aliases))
break;
}
sudo_lbuf_append(lbuf, "\n");
@@ -289,16 +294,17 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
* Write a userspec_list to lbuf in sudoers format.
*/
bool
sudoers_format_userspecs(struct sudo_lbuf *lbuf, struct userspec_list *usl,
const char *separator, bool expand_aliases, bool flush)
sudoers_format_userspecs(struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, const char *separator,
bool expand_aliases, bool flush)
{
struct userspec *us;
debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL)
TAILQ_FOREACH(us, usl, entries) {
if (separator != NULL && us != TAILQ_FIRST(usl))
TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
if (separator != NULL && us != TAILQ_FIRST(&parse_tree->userspecs))
sudo_lbuf_append(lbuf, "%s", separator);
if (!sudoers_format_userspec(lbuf, us, expand_aliases))
if (!sudoers_format_userspec(lbuf, parse_tree, us, expand_aliases))
break;
sudo_lbuf_print(lbuf);
}
@@ -336,7 +342,8 @@ sudoers_format_default(struct sudo_lbuf *lbuf, struct defaults *d)
* entries with the same binding on a single line.
*/
bool
sudoers_format_default_line(struct sudo_lbuf *lbuf, struct defaults *d,
sudoers_format_default_line( struct sudo_lbuf *lbuf,
struct sudoers_parse_tree *parse_tree, struct defaults *d,
struct defaults **next, bool expand_aliases)
{
struct member *m;
@@ -369,7 +376,7 @@ sudoers_format_default_line(struct sudo_lbuf *lbuf, struct defaults *d,
TAILQ_FOREACH(m, d->binding, entries) {
if (m != TAILQ_FIRST(d->binding))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ", alias_type);
sudoers_format_member(lbuf, parse_tree, m, ", ", alias_type);
}
sudo_lbuf_append(lbuf, " ");

View File

@@ -38,7 +38,7 @@
#define YYPREFIX "sudoers"
#line 2 "gram.y"
/*
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2017
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -98,8 +98,11 @@ bool parse_error = false;
int errorlineno = -1;
char *errorfile = NULL;
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
struct sudoers_parse_tree parsed_policy = {
TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
NULL /* aliases */
};
/*
* Local protoypes
@@ -110,7 +113,7 @@ static bool add_userspec(struct member *, struct privilege *);
static struct defaults *new_default(char *, char *, short);
static struct member *new_member(char *, int);
static struct command_digest *new_digest(int, char *);
#line 77 "gram.y"
#line 80 "gram.y"
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {
@@ -127,7 +130,7 @@ typedef union {
int tok;
} YYSTYPE;
#endif /* YYSTYPE_DEFINED */
#line 130 "gram.c"
#line 133 "gram.c"
#define COMMAND 257
#define ALIAS 258
#define DEFVAR 259
@@ -667,7 +670,7 @@ short *yysslim;
YYSTYPE *yyvs;
unsigned int yystacksize;
int yyparse(void);
#line 899 "gram.y"
#line 906 "gram.y"
void
sudoerserror(const char *s)
{
@@ -799,7 +802,7 @@ add_defaults(int type, struct member *bmem, struct defaults *defs)
HLTQ_FOREACH_SAFE(d, defs, entries, next) {
d->type = type;
d->binding = binding;
TAILQ_INSERT_TAIL(&defaults, d, entries);
TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
}
}
@@ -826,7 +829,7 @@ add_userspec(struct member *members, struct privilege *privs)
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
STAILQ_INIT(&u->comments);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
debug_return_bool(true);
}
@@ -1007,6 +1010,41 @@ free_userspec(struct userspec *us)
debug_return;
}
/*
* Initialized a sudoers parse tree.
*/
void
init_parse_tree(struct sudoers_parse_tree *parse_tree)
{
TAILQ_INIT(&parse_tree->userspecs);
TAILQ_INIT(&parse_tree->defaults);
parse_tree->aliases = NULL;
}
/*
* Move the contents of parsed_policy to new_tree.
*/
void
reparent_parse_tree(struct sudoers_parse_tree *new_tree)
{
TAILQ_CONCAT(&new_tree->userspecs, &parsed_policy.userspecs, entries);
TAILQ_CONCAT(&new_tree->defaults, &parsed_policy.defaults, entries);
new_tree->aliases = parsed_policy.aliases;
parsed_policy.aliases = NULL;
}
/*
* Free the contents of a sudoers parse tree and initialize it.
*/
void
free_parse_tree(struct sudoers_parse_tree *parse_tree)
{
free_userspecs(&parse_tree->userspecs);
free_defaults(&parse_tree->defaults);
free_aliases(parse_tree->aliases);
parse_tree->aliases = NULL;
}
/*
* Free up space used by data structures from a previous parser run and sets
* the current sudoers file to path.
@@ -1017,15 +1055,9 @@ init_parser(const char *path, bool quiet)
bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
free_userspecs(&userspecs);
free_defaults(&defaults);
free_parse_tree(&parsed_policy);
init_lexer();
if (!init_aliases()) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
ret = false;
}
rcstr_delref(sudoers);
if (path != NULL) {
if ((sudoers = rcstr_dup(path)) == NULL) {
@@ -1063,7 +1095,7 @@ init_options(struct command_options *opts)
opts->limitprivs = NULL;
#endif
}
#line 1014 "gram.c"
#line 1046 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void)
@@ -1272,23 +1304,23 @@ yyreduce:
switch (yyn)
{
case 1:
#line 175 "gram.y"
#line 178 "gram.y"
{ ; }
break;
case 5:
#line 183 "gram.y"
#line 186 "gram.y"
{
;
}
break;
case 6:
#line 186 "gram.y"
#line 189 "gram.y"
{
yyerrok;
}
break;
case 7:
#line 189 "gram.y"
#line 192 "gram.y"
{
if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
sudoerserror(N_("unable to allocate memory"));
@@ -1297,73 +1329,73 @@ case 7:
}
break;
case 8:
#line 195 "gram.y"
{
;
}
break;
case 9:
#line 198 "gram.y"
{
;
}
break;
case 10:
case 9:
#line 201 "gram.y"
{
;
}
break;
case 11:
case 10:
#line 204 "gram.y"
{
;
}
break;
case 12:
case 11:
#line 207 "gram.y"
{
;
}
break;
case 12:
#line 210 "gram.y"
{
if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
YYERROR;
}
break;
case 13:
#line 211 "gram.y"
#line 214 "gram.y"
{
if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 14:
#line 215 "gram.y"
#line 218 "gram.y"
{
if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 15:
#line 219 "gram.y"
#line 222 "gram.y"
{
if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 16:
#line 223 "gram.y"
#line 226 "gram.y"
{
if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 18:
#line 230 "gram.y"
#line 233 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
yyval.defaults = yyvsp[-2].defaults;
}
break;
case 19:
#line 236 "gram.y"
#line 239 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, true);
if (yyval.defaults == NULL) {
@@ -1373,7 +1405,7 @@ case 19:
}
break;
case 20:
#line 243 "gram.y"
#line 246 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, false);
if (yyval.defaults == NULL) {
@@ -1383,7 +1415,7 @@ case 20:
}
break;
case 21:
#line 250 "gram.y"
#line 253 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
if (yyval.defaults == NULL) {
@@ -1393,7 +1425,7 @@ case 21:
}
break;
case 22:
#line 257 "gram.y"
#line 260 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
if (yyval.defaults == NULL) {
@@ -1403,7 +1435,7 @@ case 22:
}
break;
case 23:
#line 264 "gram.y"
#line 267 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
if (yyval.defaults == NULL) {
@@ -1413,14 +1445,14 @@ case 23:
}
break;
case 25:
#line 274 "gram.y"
#line 277 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
yyval.privilege = yyvsp[-2].privilege;
}
break;
case 26:
#line 280 "gram.y"
#line 283 "gram.y"
{
struct privilege *p = calloc(1, sizeof(*p));
if (p == NULL) {
@@ -1435,21 +1467,21 @@ case 26:
}
break;
case 27:
#line 294 "gram.y"
#line 297 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 28:
#line 298 "gram.y"
#line 301 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 29:
#line 304 "gram.y"
#line 307 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
@@ -1459,7 +1491,7 @@ case 29:
}
break;
case 30:
#line 311 "gram.y"
#line 314 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
@@ -1469,7 +1501,7 @@ case 30:
}
break;
case 31:
#line 318 "gram.y"
#line 321 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
@@ -1479,7 +1511,7 @@ case 31:
}
break;
case 32:
#line 325 "gram.y"
#line 328 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
if (yyval.member == NULL) {
@@ -1489,7 +1521,7 @@ case 32:
}
break;
case 33:
#line 332 "gram.y"
#line 335 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
@@ -1499,7 +1531,7 @@ case 33:
}
break;
case 35:
#line 342 "gram.y"
#line 345 "gram.y"
{
struct cmndspec *prev;
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
@@ -1553,7 +1585,7 @@ case 35:
}
break;
case 36:
#line 395 "gram.y"
#line 398 "gram.y"
{
struct cmndspec *cs = calloc(1, sizeof(*cs));
if (cs == NULL) {
@@ -1605,7 +1637,7 @@ case 36:
}
break;
case 37:
#line 446 "gram.y"
#line 449 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
if (yyval.digest == NULL) {
@@ -1615,7 +1647,7 @@ case 37:
}
break;
case 38:
#line 453 "gram.y"
#line 456 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
if (yyval.digest == NULL) {
@@ -1625,7 +1657,7 @@ case 38:
}
break;
case 39:
#line 460 "gram.y"
#line 463 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
if (yyval.digest == NULL) {
@@ -1635,7 +1667,7 @@ case 39:
}
break;
case 40:
#line 467 "gram.y"
#line 470 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
if (yyval.digest == NULL) {
@@ -1645,13 +1677,13 @@ case 40:
}
break;
case 41:
#line 476 "gram.y"
#line 479 "gram.y"
{
yyval.member = yyvsp[0].member;
}
break;
case 42:
#line 479 "gram.y"
#line 482 "gram.y"
{
if (yyvsp[0].member->type != COMMAND) {
sudoerserror(N_("a digest requires a path name"));
@@ -1663,75 +1695,75 @@ case 42:
}
break;
case 43:
#line 490 "gram.y"
#line 493 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 44:
#line 494 "gram.y"
#line 497 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 45:
#line 500 "gram.y"
#line 503 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 46:
#line 505 "gram.y"
#line 508 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 47:
#line 509 "gram.y"
#line 512 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 48:
#line 514 "gram.y"
#line 517 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 49:
#line 519 "gram.y"
#line 522 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 50:
#line 524 "gram.y"
#line 527 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 51:
#line 528 "gram.y"
#line 531 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 52:
#line 533 "gram.y"
#line 536 "gram.y"
{
yyval.runas = NULL;
}
break;
case 53:
#line 536 "gram.y"
#line 539 "gram.y"
{
yyval.runas = yyvsp[-1].runas;
}
break;
case 54:
#line 541 "gram.y"
#line 544 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) {
@@ -1749,7 +1781,7 @@ case 54:
}
break;
case 55:
#line 556 "gram.y"
#line 559 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
@@ -1761,7 +1793,7 @@ case 55:
}
break;
case 56:
#line 565 "gram.y"
#line 568 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
@@ -1773,7 +1805,7 @@ case 56:
}
break;
case 57:
#line 574 "gram.y"
#line 577 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
@@ -1785,7 +1817,7 @@ case 57:
}
break;
case 58:
#line 583 "gram.y"
#line 586 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) {
@@ -1803,13 +1835,13 @@ case 58:
}
break;
case 59:
#line 600 "gram.y"
#line 603 "gram.y"
{
init_options(&yyval.options);
}
break;
case 60:
#line 603 "gram.y"
#line 606 "gram.y"
{
yyval.options.notbefore = parse_gentime(yyvsp[0].string);
free(yyvsp[0].string);
@@ -1820,7 +1852,7 @@ case 60:
}
break;
case 61:
#line 611 "gram.y"
#line 614 "gram.y"
{
yyval.options.notafter = parse_gentime(yyvsp[0].string);
free(yyvsp[0].string);
@@ -1831,7 +1863,7 @@ case 61:
}
break;
case 62:
#line 619 "gram.y"
#line 622 "gram.y"
{
yyval.options.timeout = parse_timeout(yyvsp[0].string);
free(yyvsp[0].string);
@@ -1845,7 +1877,7 @@ case 62:
}
break;
case 63:
#line 630 "gram.y"
#line 633 "gram.y"
{
#ifdef HAVE_SELINUX
free(yyval.options.role);
@@ -1854,7 +1886,7 @@ case 63:
}
break;
case 64:
#line 636 "gram.y"
#line 639 "gram.y"
{
#ifdef HAVE_SELINUX
free(yyval.options.type);
@@ -1863,7 +1895,7 @@ case 64:
}
break;
case 65:
#line 642 "gram.y"
#line 645 "gram.y"
{
#ifdef HAVE_PRIV_SET
free(yyval.options.privs);
@@ -1872,7 +1904,7 @@ case 65:
}
break;
case 66:
#line 648 "gram.y"
#line 651 "gram.y"
{
#ifdef HAVE_PRIV_SET
free(yyval.options.limitprivs);
@@ -1881,97 +1913,97 @@ case 66:
}
break;
case 67:
#line 656 "gram.y"
#line 659 "gram.y"
{
TAGS_INIT(yyval.tag);
}
break;
case 68:
#line 659 "gram.y"
#line 662 "gram.y"
{
yyval.tag.nopasswd = true;
}
break;
case 69:
#line 662 "gram.y"
#line 665 "gram.y"
{
yyval.tag.nopasswd = false;
}
break;
case 70:
#line 665 "gram.y"
#line 668 "gram.y"
{
yyval.tag.noexec = true;
}
break;
case 71:
#line 668 "gram.y"
#line 671 "gram.y"
{
yyval.tag.noexec = false;
}
break;
case 72:
#line 671 "gram.y"
#line 674 "gram.y"
{
yyval.tag.setenv = true;
}
break;
case 73:
#line 674 "gram.y"
#line 677 "gram.y"
{
yyval.tag.setenv = false;
}
break;
case 74:
#line 677 "gram.y"
#line 680 "gram.y"
{
yyval.tag.log_input = true;
}
break;
case 75:
#line 680 "gram.y"
#line 683 "gram.y"
{
yyval.tag.log_input = false;
}
break;
case 76:
#line 683 "gram.y"
#line 686 "gram.y"
{
yyval.tag.log_output = true;
}
break;
case 77:
#line 686 "gram.y"
#line 689 "gram.y"
{
yyval.tag.log_output = false;
}
break;
case 78:
#line 689 "gram.y"
#line 692 "gram.y"
{
yyval.tag.follow = true;
}
break;
case 79:
#line 692 "gram.y"
#line 695 "gram.y"
{
yyval.tag.follow = false;
}
break;
case 80:
#line 695 "gram.y"
#line 698 "gram.y"
{
yyval.tag.send_mail = true;
}
break;
case 81:
#line 698 "gram.y"
#line 701 "gram.y"
{
yyval.tag.send_mail = false;
}
break;
case 82:
#line 703 "gram.y"
#line 706 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
@@ -1981,7 +2013,7 @@ case 82:
}
break;
case 83:
#line 710 "gram.y"
#line 713 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
@@ -1991,7 +2023,7 @@ case 83:
}
break;
case 84:
#line 717 "gram.y"
#line 720 "gram.y"
{
struct sudo_command *c = calloc(1, sizeof(*c));
if (c == NULL) {
@@ -2009,10 +2041,11 @@ case 84:
}
break;
case 87:
#line 738 "gram.y"
#line 741 "gram.y"
{
const char *s;
s = alias_add(yyvsp[-2].string, HOSTALIAS, sudoers, this_lineno, yyvsp[0].member);
s = alias_add(&parsed_policy, yyvsp[-2].string, HOSTALIAS,
sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -2020,17 +2053,18 @@ case 87:
}
break;
case 89:
#line 749 "gram.y"
#line 753 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 92:
#line 759 "gram.y"
#line 763 "gram.y"
{
const char *s;
s = alias_add(yyvsp[-2].string, CMNDALIAS, sudoers, this_lineno, yyvsp[0].member);
s = alias_add(&parsed_policy, yyvsp[-2].string, CMNDALIAS,
sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -2038,17 +2072,18 @@ case 92:
}
break;
case 94:
#line 770 "gram.y"
#line 775 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 97:
#line 780 "gram.y"
#line 785 "gram.y"
{
const char *s;
s = alias_add(yyvsp[-2].string, RUNASALIAS, sudoers, this_lineno, yyvsp[0].member);
s = alias_add(&parsed_policy, yyvsp[-2].string, RUNASALIAS,
sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -2056,10 +2091,11 @@ case 97:
}
break;
case 100:
#line 794 "gram.y"
#line 800 "gram.y"
{
const char *s;
s = alias_add(yyvsp[-2].string, USERALIAS, sudoers, this_lineno, yyvsp[0].member);
s = alias_add(&parsed_policy, yyvsp[-2].string, USERALIAS,
sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -2067,28 +2103,28 @@ case 100:
}
break;
case 102:
#line 805 "gram.y"
#line 812 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 103:
#line 811 "gram.y"
#line 818 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 104:
#line 815 "gram.y"
#line 822 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 105:
#line 821 "gram.y"
#line 828 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
@@ -2098,7 +2134,7 @@ case 105:
}
break;
case 106:
#line 828 "gram.y"
#line 835 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
@@ -2108,7 +2144,7 @@ case 106:
}
break;
case 107:
#line 835 "gram.y"
#line 842 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
@@ -2118,7 +2154,7 @@ case 107:
}
break;
case 108:
#line 842 "gram.y"
#line 849 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
if (yyval.member == NULL) {
@@ -2128,7 +2164,7 @@ case 108:
}
break;
case 109:
#line 849 "gram.y"
#line 856 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
@@ -2138,28 +2174,28 @@ case 109:
}
break;
case 111:
#line 859 "gram.y"
#line 866 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 112:
#line 865 "gram.y"
#line 872 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 113:
#line 869 "gram.y"
#line 876 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 114:
#line 875 "gram.y"
#line 882 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
@@ -2169,7 +2205,7 @@ case 114:
}
break;
case 115:
#line 882 "gram.y"
#line 889 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
@@ -2179,7 +2215,7 @@ case 115:
}
break;
case 116:
#line 889 "gram.y"
#line 896 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
@@ -2188,7 +2224,7 @@ case 116:
}
}
break;
#line 2139 "gram.c"
#line 2175 "gram.c"
}
yyssp -= yym;
yystate = *yyssp;

View File

@@ -1,6 +1,6 @@
%{
/*
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2017
* Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -60,8 +60,11 @@ bool parse_error = false;
int errorlineno = -1;
char *errorfile = NULL;
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
struct sudoers_parse_tree parsed_policy = {
TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
NULL /* aliases */
};
/*
* Local protoypes
@@ -737,7 +740,8 @@ hostaliases : hostalias
hostalias : ALIAS '=' hostlist {
const char *s;
s = alias_add($1, HOSTALIAS, sudoers, this_lineno, $3);
s = alias_add(&parsed_policy, $1, HOSTALIAS,
sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -758,7 +762,8 @@ cmndaliases : cmndalias
cmndalias : ALIAS '=' cmndlist {
const char *s;
s = alias_add($1, CMNDALIAS, sudoers, this_lineno, $3);
s = alias_add(&parsed_policy, $1, CMNDALIAS,
sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -779,7 +784,8 @@ runasaliases : runasalias
runasalias : ALIAS '=' userlist {
const char *s;
s = alias_add($1, RUNASALIAS, sudoers, this_lineno, $3);
s = alias_add(&parsed_policy, $1, RUNASALIAS,
sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -793,7 +799,8 @@ useraliases : useralias
useralias : ALIAS '=' userlist {
const char *s;
s = alias_add($1, USERALIAS, sudoers, this_lineno, $3);
s = alias_add(&parsed_policy, $1, USERALIAS,
sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s);
YYERROR;
@@ -1027,7 +1034,7 @@ add_defaults(int type, struct member *bmem, struct defaults *defs)
HLTQ_FOREACH_SAFE(d, defs, entries, next) {
d->type = type;
d->binding = binding;
TAILQ_INSERT_TAIL(&defaults, d, entries);
TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
}
}
@@ -1054,7 +1061,7 @@ add_userspec(struct member *members, struct privilege *privs)
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
STAILQ_INIT(&u->comments);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
debug_return_bool(true);
}
@@ -1235,6 +1242,41 @@ free_userspec(struct userspec *us)
debug_return;
}
/*
* Initialized a sudoers parse tree.
*/
void
init_parse_tree(struct sudoers_parse_tree *parse_tree)
{
TAILQ_INIT(&parse_tree->userspecs);
TAILQ_INIT(&parse_tree->defaults);
parse_tree->aliases = NULL;
}
/*
* Move the contents of parsed_policy to new_tree.
*/
void
reparent_parse_tree(struct sudoers_parse_tree *new_tree)
{
TAILQ_CONCAT(&new_tree->userspecs, &parsed_policy.userspecs, entries);
TAILQ_CONCAT(&new_tree->defaults, &parsed_policy.defaults, entries);
new_tree->aliases = parsed_policy.aliases;
parsed_policy.aliases = NULL;
}
/*
* Free the contents of a sudoers parse tree and initialize it.
*/
void
free_parse_tree(struct sudoers_parse_tree *parse_tree)
{
free_userspecs(&parse_tree->userspecs);
free_defaults(&parse_tree->defaults);
free_aliases(parse_tree->aliases);
parse_tree->aliases = NULL;
}
/*
* Free up space used by data structures from a previous parser run and sets
* the current sudoers file to path.
@@ -1245,15 +1287,9 @@ init_parser(const char *path, bool quiet)
bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
free_userspecs(&userspecs);
free_defaults(&defaults);
free_parse_tree(&parsed_policy);
init_lexer();
if (!init_aliases()) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
ret = false;
}
rcstr_delref(sudoers);
if (path != NULL) {
if ((sudoers = rcstr_dup(path)) == NULL) {

View File

@@ -152,9 +152,7 @@ STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
struct sudo_ldap_handle {
LDAP *ld;
struct passwd *pw;
struct userspec_list userspecs;
struct defaults_list defaults;
bool cached_defaults;
struct sudoers_parse_tree parse_tree;
};
#ifdef HAVE_LDAP_INITIALIZE
@@ -1553,8 +1551,7 @@ sudo_ldap_close(struct sudo_nss *nss)
/* Free the handle container. */
if (handle->pw != NULL)
sudo_pw_delref(handle->pw);
free_userspecs(&handle->userspecs);
free_defaults(&handle->defaults);
free_parse_tree(&handle->parse_tree);
free(handle);
nss->handle = NULL;
}
@@ -1660,40 +1657,39 @@ sudo_ldap_open(struct sudo_nss *nss)
}
handle->ld = ld;
/* handle->pw = NULL; */
TAILQ_INIT(&handle->userspecs);
TAILQ_INIT(&handle->defaults);
init_parse_tree(&handle->parse_tree);
nss->handle = handle;
done:
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
}
static struct defaults_list *
static int
sudo_ldap_getdefs(struct sudo_nss *nss)
{
struct sudo_ldap_handle *handle = nss->handle;
struct defaults_list *ret = &handle->defaults;
struct timeval tv, *tvp = NULL;
struct ldap_config_str *base;
LDAPMessage *entry, *result = NULL;
char *filt = NULL;
int rc;
int rc, ret = -1;
static bool cached;
debug_decl(sudo_ldap_getdefs, SUDOERS_DEBUG_LDAP)
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
debug_return_int(-1);
}
/* Use cached result if present. */
if (handle->cached_defaults)
goto done;
if (cached)
debug_return_int(0);
filt = sudo_ldap_build_default_filter();
if (filt == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_ptr(NULL);
debug_return_int(-1);
}
DPRINTF1("Looking for cn=defaults: %s", filt);
@@ -1711,21 +1707,20 @@ sudo_ldap_getdefs(struct sudo_nss *nss)
filt, NULL, 0, NULL, NULL, tvp, 0, &result);
if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
DPRINTF1("found:%s", ldap_get_dn(ld, entry));
if (!sudo_ldap_parse_options(ld, entry, &handle->defaults)) {
ret = NULL;
if (!sudo_ldap_parse_options(ld, entry, &handle->parse_tree.defaults))
goto done;
}
} else {
DPRINTF1("no default options found in %s", base->val);
}
}
handle->cached_defaults = true;
cached = true;
ret = 0;
done:
ldap_msgfree(result);
free(filt);
debug_return_ptr(ret);
debug_return_int(ret);
}
/*
@@ -1918,67 +1913,73 @@ oom:
* Perform LDAP query for user and host and convert to sudoers
* parse tree.
*/
static struct userspec_list *
static int
sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
{
struct sudo_ldap_handle *handle = nss->handle;
struct ldap_result *lres = NULL;
struct userspec_list *ret = &handle->userspecs;
int ret = -1;
debug_decl(sudo_ldap_query, SUDOERS_DEBUG_LDAP)
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_int(-1);
}
/* Use cached result if it matches pw. */
if (handle->pw != NULL) {
if (pw == handle->pw) {
ret = 0;
goto done;
}
sudo_pw_delref(handle->pw);
handle->pw = NULL;
}
/* Free old userspecs, if any. */
free_userspecs(&handle->parse_tree.userspecs);
DPRINTF1("%s: ldap search user %s, host %s", __func__, pw->pw_name,
user_runhost);
if ((lres = sudo_ldap_result_get(nss, pw)) == NULL)
goto done;
/* Convert to sudoers parse tree. */
if (!ldap_to_sudoers(handle->ld, lres, &handle->parse_tree.userspecs))
goto done;
/* Stash a ref to the passwd struct in the handle. */
sudo_pw_addref(pw);
handle->pw = pw;
ret = 0;
done:
/* Cleanup. */
sudo_ldap_result_free(lres);
if (ret == -1)
free_userspecs(&handle->parse_tree.userspecs);
debug_return_int(ret);
}
/*
* Return the initialized (but empty) sudoers parse tree.
* The contents will be populated by the getdefs() and query() functions.
*/
static struct sudoers_parse_tree *
sudo_ldap_parse(struct sudo_nss *nss)
{
struct sudo_ldap_handle *handle = nss->handle;
debug_decl(sudo_ldap_parse, SUDOERS_DEBUG_LDAP)
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
}
/* Use cached result if it matches pw. */
if (handle->pw != NULL) {
if (pw == handle->pw)
goto done;
sudo_pw_delref(handle->pw);
handle->pw = NULL;
}
/* Free old userspecs, if any. */
free_userspecs(&handle->userspecs);
DPRINTF1("%s: ldap search user %s, host %s", __func__, pw->pw_name,
user_runhost);
if ((lres = sudo_ldap_result_get(nss, pw)) == NULL) {
ret = NULL;
goto done;
}
/* Convert to sudoers parse tree. */
if (!ldap_to_sudoers(handle->ld, lres, &handle->userspecs)) {
ret = NULL;
goto done;
}
/* Stash a ref to the passwd struct in the handle. */
sudo_pw_addref(pw);
handle->pw = pw;
ret = &handle->userspecs;
done:
/* Cleanup. */
sudo_ldap_result_free(lres);
if (ret == NULL) {
free_userspecs(&handle->userspecs);
debug_return_ptr(NULL);
}
debug_return_ptr(ret);
}
/*
* STUB
*/
static int
sudo_ldap_parse(struct sudo_nss *nss)
{
return 0;
debug_return_ptr(&handle->parse_tree);
}
#if 0

View File

@@ -93,7 +93,8 @@ static bool digest_matches(int fd, const char *file, const struct command_digest
* Returns ALLOW, DENY or UNSPEC.
*/
int
user_matches(const struct passwd *pw, const struct member *m)
user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
const struct member *m)
{
struct alias *a;
int matched = UNSPEC;
@@ -114,9 +115,9 @@ user_matches(const struct passwd *pw, const struct member *m)
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, USERALIAS)) != NULL) {
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
/* XXX */
int rc = userlist_matches(pw, &a->members);
int rc = userlist_matches(parse_tree, pw, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
@@ -136,14 +137,15 @@ user_matches(const struct passwd *pw, const struct member *m)
* Returns ALLOW, DENY or UNSPEC.
*/
int
userlist_matches(const struct passwd *pw, const struct member_list *list)
userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
const struct member_list *list)
{
struct member *m;
int matched = UNSPEC;
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
if ((matched = user_matches(pw, m)) != UNSPEC)
if ((matched = user_matches(parse_tree, pw, m)) != UNSPEC)
break;
}
debug_return_int(matched);
@@ -155,9 +157,9 @@ userlist_matches(const struct passwd *pw, const struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
runaslist_matches(const struct member_list *user_list,
const struct member_list *group_list, struct member **matching_user,
struct member **matching_group)
runaslist_matches(struct sudoers_parse_tree *parse_tree,
const struct member_list *user_list, const struct member_list *group_list,
struct member **matching_user, struct member **matching_group)
{
struct member *m;
struct alias *a;
@@ -191,9 +193,10 @@ runaslist_matches(const struct member_list *user_list,
user_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rc = runaslist_matches(&a->members, &empty,
matching_user, NULL);
a = alias_get(parse_tree, m->name, RUNASALIAS);
if (a != NULL) {
rc = runaslist_matches(parse_tree, &a->members,
&empty, matching_user, NULL);
if (rc != UNSPEC)
user_matched = m->negated ? !rc : rc;
alias_put(a);
@@ -234,9 +237,10 @@ runaslist_matches(const struct member_list *user_list,
group_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rc = runaslist_matches(&empty, &a->members,
NULL, matching_group);
a = alias_get(parse_tree, m->name, RUNASALIAS);
if (a != NULL) {
rc = runaslist_matches(parse_tree, &empty,
&a->members, NULL, matching_group);
if (rc != UNSPEC)
group_matched = m->negated ? !rc : rc;
alias_put(a);
@@ -273,15 +277,16 @@ runaslist_matches(const struct member_list *user_list,
* Returns ALLOW, DENY or UNSPEC.
*/
static int
hostlist_matches_int(const struct passwd *pw, const char *lhost,
const char *shost, const struct member_list *list)
hostlist_matches_int(struct sudoers_parse_tree *parse_tree,
const struct passwd *pw, const char *lhost, const char *shost,
const struct member_list *list)
{
struct member *m;
int matched = UNSPEC;
debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = host_matches(pw, lhost, shost, m);
matched = host_matches(parse_tree, pw, lhost, shost, m);
if (matched != UNSPEC)
break;
}
@@ -293,9 +298,10 @@ hostlist_matches_int(const struct passwd *pw, const char *lhost,
* Returns ALLOW, DENY or UNSPEC.
*/
int
hostlist_matches(const struct passwd *pw, const struct member_list *list)
hostlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
const struct member_list *list)
{
return hostlist_matches_int(pw, user_runhost, user_srunhost, list);
return hostlist_matches_int(parse_tree, pw, user_runhost, user_srunhost, list);
}
/*
@@ -303,8 +309,8 @@ hostlist_matches(const struct passwd *pw, const struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
host_matches(const struct passwd *pw, const char *lhost, const char *shost,
const struct member *m)
host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
const char *lhost, const char *shost, const struct member *m)
{
struct alias *a;
int matched = UNSPEC;
@@ -324,9 +330,11 @@ host_matches(const struct passwd *pw, const char *lhost, const char *shost,
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, HOSTALIAS)) != NULL) {
a = alias_get(parse_tree, m->name, HOSTALIAS);
if (a != NULL) {
/* XXX */
int rc = hostlist_matches_int(pw, lhost, shost, &a->members);
int rc = hostlist_matches_int(parse_tree, pw, lhost, shost,
&a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
@@ -346,14 +354,15 @@ host_matches(const struct passwd *pw, const char *lhost, const char *shost,
* Returns ALLOW, DENY or UNSPEC.
*/
int
cmndlist_matches(const struct member_list *list)
cmndlist_matches(struct sudoers_parse_tree *parse_tree,
const struct member_list *list)
{
struct member *m;
int matched = UNSPEC;
debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = cmnd_matches(m);
matched = cmnd_matches(parse_tree, m);
if (matched != UNSPEC)
break;
}
@@ -365,7 +374,7 @@ cmndlist_matches(const struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
cmnd_matches(const struct member *m)
cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
{
struct alias *a;
struct sudo_command *c;
@@ -377,8 +386,9 @@ cmnd_matches(const struct member *m)
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, CMNDALIAS)) != NULL) {
rc = cmndlist_matches(&a->members);
a = alias_get(parse_tree, m->name, CMNDALIAS);
if (a != NULL) {
rc = cmndlist_matches(parse_tree, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);

View File

@@ -65,19 +65,18 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
CLR(validated, FLAG_NO_HOST);
match = DENY;
TAILQ_FOREACH(nss, snl, entries) {
struct userspec_list *usl = nss->query(nss, pw);
if (usl == NULL) {
if (nss->query(nss, pw) == -1) {
/* The query function should have printed an error message. */
SET(validated, VALIDATE_ERROR);
break;
}
TAILQ_FOREACH(us, usl, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
TAILQ_FOREACH(us, &nss->parse_tree->userspecs, entries) {
if (userlist_matches(nss->parse_tree, pw, &us->users) != ALLOW)
continue;
TAILQ_FOREACH(priv, &us->privileges, entries) {
int priv_nopass = UNSPEC;
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
if (hostlist_matches(nss->parse_tree, pw, &priv->hostlist) != ALLOW)
continue;
TAILQ_FOREACH(def, &priv->defaults, entries) {
if (strcmp(def->var, "authenticate") == 0)
@@ -96,7 +95,7 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
/* Only check the command when listing another user. */
if (user_uid == 0 || list_pw == NULL ||
user_uid == list_pw->pw_uid ||
cmnd_matches(cs->cmnd) == ALLOW)
cmnd_matches(nss->parse_tree, cs->cmnd) == ALLOW)
match = ALLOW;
}
}
@@ -115,7 +114,7 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
}
static int
sudoers_lookup_check(struct userspec_list *usl, struct passwd *pw,
sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
int *validated, struct cmndspec **matching_cs,
struct defaults_list **defs, time_t now)
{
@@ -126,12 +125,12 @@ sudoers_lookup_check(struct userspec_list *usl, struct passwd *pw,
struct member *matching_user;
debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER)
TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) {
if (userlist_matches(nss->parse_tree, pw, &us->users) != ALLOW)
continue;
CLR(*validated, FLAG_NO_USER);
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(pw, &priv->hostlist);
host_match = hostlist_matches(nss->parse_tree, pw, &priv->hostlist);
if (host_match == ALLOW)
CLR(*validated, FLAG_NO_HOST);
else
@@ -146,10 +145,11 @@ sudoers_lookup_check(struct userspec_list *usl, struct passwd *pw,
continue;
}
matching_user = NULL;
runas_match = runaslist_matches(cs->runasuserlist,
cs->runasgrouplist, &matching_user, NULL);
runas_match = runaslist_matches(nss->parse_tree,
cs->runasuserlist, cs->runasgrouplist, &matching_user,
NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd);
if (cmnd_match != UNSPEC) {
/*
* If user is running command as himself,
@@ -273,6 +273,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
int pwflag)
{
struct defaults_list *defs = NULL;
struct sudoers_parse_tree *parse_tree = NULL;
struct cmndspec *cs = NULL;
struct sudo_nss *nss;
int m, match = UNSPEC;
@@ -292,23 +293,24 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
/* Query each sudoers source and check the user. */
time(&now);
TAILQ_FOREACH(nss, snl, entries) {
struct userspec_list *usl = nss->query(nss, pw);
if (usl == NULL) {
if (nss->query(nss, pw) == -1) {
/* The query function should have printed an error message. */
SET(validated, VALIDATE_ERROR);
break;
}
m = sudoers_lookup_check(usl, pw, &validated, &cs, &defs, now);
if (m != UNSPEC)
m = sudoers_lookup_check(nss, pw, &validated, &cs, &defs, now);
if (m != UNSPEC) {
match = m;
parse_tree = nss->parse_tree;
}
if (!sudo_nss_can_continue(nss, m))
break;
}
if (defs != NULL)
update_defaults(defs, SETDEF_GENERIC, false);
if (match != UNSPEC) {
if (defs != NULL)
update_defaults(parse_tree, SETDEF_GENERIC, false);
if (!apply_cmndspec(cs))
SET(validated, VALIDATE_ERROR);
else if (match == ALLOW)
@@ -322,8 +324,8 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
}
static int
display_priv_short(struct passwd *pw, struct userspec *us,
struct sudo_lbuf *lbuf)
display_priv_short(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
struct userspec *us, struct sudo_lbuf *lbuf)
{
struct cmndspec *cs, *prev_cs;
struct member *m;
@@ -332,7 +334,7 @@ display_priv_short(struct passwd *pw, struct userspec *us,
debug_decl(display_priv_short, SUDOERS_DEBUG_PARSER)
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
@@ -345,7 +347,8 @@ display_priv_short(struct passwd *pw, struct userspec *us,
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
sudoers_format_member(lbuf, parse_tree, m, ", ",
RUNASALIAS);
}
} else if (cs->runasgrouplist == NULL) {
sudo_lbuf_append(lbuf, "%s", def_runas_default);
@@ -357,14 +360,15 @@ display_priv_short(struct passwd *pw, struct userspec *us,
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
sudoers_format_member(lbuf, parse_tree, m, ", ",
RUNASALIAS);
}
}
sudo_lbuf_append(lbuf, ") ");
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
sudo_lbuf_append(lbuf, ", ");
}
sudoers_format_cmndspec(lbuf, cs, prev_cs, true);
sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, true);
prev_cs = cs;
nfound++;
}
@@ -409,8 +413,8 @@ new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
}
static int
display_priv_long(struct passwd *pw, struct userspec *us,
struct sudo_lbuf *lbuf)
display_priv_long(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
struct userspec *us, struct sudo_lbuf *lbuf)
{
struct cmndspec *cs, *prev_cs;
struct privilege *priv;
@@ -418,7 +422,7 @@ display_priv_long(struct passwd *pw, struct userspec *us,
debug_decl(display_priv_long, SUDOERS_DEBUG_PARSER)
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
@@ -437,7 +441,8 @@ display_priv_long(struct passwd *pw, struct userspec *us,
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
sudoers_format_member(lbuf, parse_tree, m, ", ",
RUNASALIAS);
}
} else if (cs->runasgrouplist == NULL) {
sudo_lbuf_append(lbuf, "%s", def_runas_default);
@@ -450,7 +455,8 @@ display_priv_long(struct passwd *pw, struct userspec *us,
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
sudoers_format_member(lbuf, parse_tree, m, ", ",
RUNASALIAS);
}
sudo_lbuf_append(lbuf, "\n");
}
@@ -512,7 +518,8 @@ display_priv_long(struct passwd *pw, struct userspec *us,
sudo_lbuf_append(lbuf, _(" Commands:\n"));
}
sudo_lbuf_append(lbuf, "\t");
sudoers_format_member(lbuf, cs->cmnd, "\n\t", CMNDALIAS);
sudoers_format_member(lbuf, parse_tree, cs->cmnd, "\n\t",
CMNDALIAS);
sudo_lbuf_append(lbuf, "\n");
prev_cs = cs;
nfound++;
@@ -522,21 +529,21 @@ display_priv_long(struct passwd *pw, struct userspec *us,
}
static int
sudo_display_userspecs(struct userspec_list *usl, struct passwd *pw,
sudo_display_userspecs(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
struct sudo_lbuf *lbuf)
{
struct userspec *us;
int nfound = 0;
debug_decl(sudo_display_userspecs, SUDOERS_DEBUG_PARSER)
TAILQ_FOREACH(us, usl, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
continue;
if (long_list)
nfound += display_priv_long(pw, us, lbuf);
nfound += display_priv_long(parse_tree, pw, us, lbuf);
else
nfound += display_priv_short(pw, us, lbuf);
nfound += display_priv_short(parse_tree, pw, us, lbuf);
}
if (sudo_lbuf_error(lbuf))
debug_return_int(-1);
@@ -547,7 +554,7 @@ sudo_display_userspecs(struct userspec_list *usl, struct passwd *pw,
* Display matching Defaults entries for the given user on this host.
*/
static int
display_defaults(struct defaults_list *defs, struct passwd *pw,
display_defaults(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
struct sudo_lbuf *lbuf)
{
struct defaults *d;
@@ -560,14 +567,14 @@ display_defaults(struct defaults_list *defs, struct passwd *pw,
else
prefix = ", ";
TAILQ_FOREACH(d, defs, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
if (hostlist_matches(pw, d->binding) != ALLOW)
if (hostlist_matches(parse_tree, pw, d->binding) != ALLOW)
continue;
break;
case DEFAULTS_USER:
if (userlist_matches(pw, d->binding) != ALLOW)
if (userlist_matches(parse_tree, pw, d->binding) != ALLOW)
continue;
break;
case DEFAULTS_RUNAS:
@@ -588,8 +595,8 @@ display_defaults(struct defaults_list *defs, struct passwd *pw,
* Display Defaults entries of the given type.
*/
static int
display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
struct sudo_lbuf *lbuf)
display_bound_defaults_by_type(struct sudoers_parse_tree *parse_tree,
int deftype, struct sudo_lbuf *lbuf)
{
struct defaults *d;
struct member_list *binding = NULL;
@@ -618,7 +625,7 @@ display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
default:
debug_return_int(-1);
}
TAILQ_FOREACH(d, defs, entries) {
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
if (d->type != deftype)
continue;
@@ -631,7 +638,7 @@ display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
TAILQ_FOREACH(m, binding, entries) {
if (m != TAILQ_FIRST(binding))
sudo_lbuf_append(lbuf, ",");
sudoers_format_member(lbuf, m, ", ", atype);
sudoers_format_member(lbuf, parse_tree, m, ", ", atype);
sudo_lbuf_append(lbuf, " ");
}
} else
@@ -648,15 +655,15 @@ display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
* Display Defaults entries that are per-runas or per-command
*/
static int
display_bound_defaults(struct defaults_list *defs, struct passwd *pw,
struct sudo_lbuf *lbuf)
display_bound_defaults(struct sudoers_parse_tree *parse_tree,
struct passwd *pw, struct sudo_lbuf *lbuf)
{
int nfound = 0;
debug_decl(display_bound_defaults, SUDOERS_DEBUG_PARSER)
/* XXX - should only print ones that match what the user can do. */
nfound += display_bound_defaults_by_type(defs, DEFAULTS_RUNAS, lbuf);
nfound += display_bound_defaults_by_type(defs, DEFAULTS_CMND, lbuf);
nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_RUNAS, lbuf);
nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_CMND, lbuf);
if (sudo_lbuf_error(lbuf))
debug_return_int(-1);
@@ -703,14 +710,11 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
pw->pw_name, user_srunhost);
count = 0;
TAILQ_FOREACH(nss, snl, entries) {
struct defaults_list *defs = nss->getdefs(nss);
if (defs != NULL) {
n = display_defaults(defs, pw, &def_buf);
n = display_defaults(nss->parse_tree, pw, &def_buf);
if (n == -1)
goto bad;
count += n;
}
}
if (count != 0) {
sudo_lbuf_append(&def_buf, "\n\n");
} else {
@@ -724,14 +728,11 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
pw->pw_name);
count = 0;
TAILQ_FOREACH(nss, snl, entries) {
struct defaults_list *defs = nss->getdefs(nss);
if (defs != NULL) {
n = display_bound_defaults(defs, pw, &def_buf);
n = display_bound_defaults(nss->parse_tree, pw, &def_buf);
if (n == -1)
goto bad;
count += n;
}
}
if (count != 0) {
sudo_lbuf_append(&def_buf, "\n\n");
} else {
@@ -745,9 +746,8 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
pw->pw_name, user_srunhost);
count = 0;
TAILQ_FOREACH(nss, snl, entries) {
struct userspec_list *usl = nss->query(nss, pw);
if (usl != NULL) {
n = sudo_display_userspecs(usl, pw, &priv_buf);
if (nss->query(nss, pw) != -1) {
n = sudo_display_userspecs(nss->parse_tree, pw, &priv_buf);
if (n == -1)
goto bad;
count += n;
@@ -778,7 +778,8 @@ bad:
}
static int
display_cmnd_check(struct userspec_list *usl, struct passwd *pw, time_t now)
display_cmnd_check(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
time_t now)
{
int host_match, runas_match, cmnd_match;
struct cmndspec *cs;
@@ -786,11 +787,11 @@ display_cmnd_check(struct userspec_list *usl, struct passwd *pw, time_t now)
struct userspec *us;
debug_decl(display_cmnd_check, SUDOERS_DEBUG_PARSER)
TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
TAILQ_FOREACH_REVERSE(us, &parse_tree->userspecs, userspec_list, entries) {
if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
continue;
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(pw, &priv->hostlist);
host_match = hostlist_matches(parse_tree, pw, &priv->hostlist);
if (host_match != ALLOW)
continue;
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
@@ -802,10 +803,10 @@ display_cmnd_check(struct userspec_list *usl, struct passwd *pw, time_t now)
if (now > cs->notafter)
continue;
}
runas_match = runaslist_matches(cs->runasuserlist,
runas_match = runaslist_matches(parse_tree, cs->runasuserlist,
cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
cmnd_match = cmnd_matches(parse_tree, cs->cmnd);
if (cmnd_match != UNSPEC)
debug_return_int(cmnd_match);
}
@@ -832,13 +833,12 @@ display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
/* Iterate over each source, checking for the command. */
time(&now);
TAILQ_FOREACH(nss, snl, entries) {
struct userspec_list *usl = nss->query(nss, pw);
if (usl == NULL) {
if (nss->query(nss, pw) == -1) {
/* The query function should have printed an error message. */
debug_return_int(-1);
}
m = display_cmnd_check(usl, pw, now);
m = display_cmnd_check(nss->parse_tree, pw, now);
if (m != UNSPEC)
match = m;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 1998-2000, 2004, 2007-2016
* Copyright (c) 1996, 1998-2000, 2004, 2007-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -239,26 +239,29 @@ struct defaults {
};
/*
* Parsed sudoers info.
* Parsed sudoers policy.
*/
extern struct userspec_list userspecs;
extern struct defaults_list defaults;
struct sudoers_parse_tree {
struct userspec_list userspecs;
struct defaults_list defaults;
struct rbtree *aliases;
};
/* alias.c */
bool no_aliases(void);
struct rbtree *replace_aliases(struct rbtree *new_aliases);
const char *alias_add(char *name, int type, char *file, int lineno, struct member *members);
struct rbtree *alloc_aliases(void);
void free_aliases(struct rbtree *aliases);
bool no_aliases(struct sudoers_parse_tree *parse_tree);
const char *alias_add(struct sudoers_parse_tree *parse_tree, char *name, int type, char *file, int lineno, struct member *members);
const char *alias_type_to_string(int alias_type);
int alias_compare(const void *a1, const void *a2);
struct alias *alias_get(const 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);
struct alias *alias_get(struct sudoers_parse_tree *parse_tree, const char *name, int type);
struct alias *alias_remove(struct sudoers_parse_tree *parse_tree, char *name, int type);
bool alias_find_used(struct sudoers_parse_tree *parse_tree, struct rbtree *used_aliases);
void alias_apply(struct sudoers_parse_tree *parse_tree, int (*func)(void *, void *), void *cookie);
void alias_free(void *a);
void alias_put(struct alias *a);
bool init_aliases(void);
/* gram.c */
extern struct sudoers_parse_tree parsed_policy;
bool init_parser(const char *path, bool quiet);
void free_member(struct member *m);
void free_members(struct member_list *members);
@@ -267,6 +270,9 @@ void free_userspec(struct userspec *us);
void free_userspecs(struct userspec_list *usl);
void free_default(struct defaults *def, struct member_list **binding);
void free_defaults(struct defaults_list *defs);
void init_parse_tree(struct sudoers_parse_tree *parse_tree);
void free_parse_tree(struct sudoers_parse_tree *parse_tree);
void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
/* match_addr.c */
bool addr_matches(char *n);
@@ -280,13 +286,13 @@ bool hostname_matches(const char *shost, const char *lhost, const char *pattern)
bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user);
bool usergr_matches(const char *group, const char *user, const struct passwd *pw);
bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
int cmnd_matches(const struct member *m);
int cmndlist_matches(const struct member_list *list);
int host_matches(const struct passwd *pw, const char *host, const char *shost, const struct member *m);
int hostlist_matches(const struct passwd *pw, const struct member_list *list);
int runaslist_matches(const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group);
int user_matches(const struct passwd *pw, const struct member *m);
int userlist_matches(const struct passwd *pw, const struct member_list *list);
int cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m);
int cmndlist_matches(struct sudoers_parse_tree *parse_tree, const struct member_list *list);
int host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const char *host, const char *shost, const struct member *m);
int hostlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
int runaslist_matches(struct sudoers_parse_tree *parse_tree, const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group);
int user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member *m);
int userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
const char *sudo_getdomainname(void);
/* toke.c */
@@ -322,12 +328,12 @@ int display_cmnd(struct sudo_nss_list *snl, struct passwd *pw);
/* fmtsudoers.c */
struct sudo_lbuf;
bool sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs, struct cmndspec *prev_cs, bool expand_aliases);
bool sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, struct cmndspec *cs, struct cmndspec *prev_cs, bool expand_aliases);
bool sudoers_format_default(struct sudo_lbuf *lbuf, struct defaults *d);
bool sudoers_format_default_line(struct sudo_lbuf *lbuf, struct defaults *d, struct defaults **next, bool expand_aliases);
bool sudoers_format_member(struct sudo_lbuf *lbuf, struct member *m, const char *separator, int alias_type);
bool sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv, bool expand_aliases);
bool sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us, bool expand_aliases);
bool sudoers_format_userspecs(struct sudo_lbuf *lbuf, struct userspec_list *usl, const char *separator, bool expand_aliases, bool flush);
bool sudoers_format_default_line(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, struct defaults *d, struct defaults **next, bool expand_aliases);
bool sudoers_format_member(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, struct member *m, const char *separator, int alias_type);
bool sudoers_format_privilege(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, struct privilege *priv, bool expand_aliases);
bool sudoers_format_userspec(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, struct userspec *us, bool expand_aliases);
bool sudoers_format_userspecs(struct sudo_lbuf *lbuf, struct sudoers_parse_tree *parse_tree, const char *separator, bool expand_aliases, bool flush);
#endif /* SUDOERS_PARSE_H */

View File

@@ -83,9 +83,7 @@ struct sudo_sss_handle {
char *ipa_shost;
struct passwd *pw;
void *ssslib;
struct userspec_list userspecs;
struct defaults_list defaults;
bool cached_defaults;
struct sudoers_parse_tree parse_tree;
sss_sudo_send_recv_t fn_send_recv;
sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
sss_sudo_free_result_t fn_free_result;
@@ -237,7 +235,7 @@ val_array_iter(void **vp)
static bool
sss_to_sudoers(struct sudo_sss_handle *handle,
struct sss_sudo_result *sss_result, struct userspec_list *sss_userspecs)
struct sss_sudo_result *sss_result)
{
struct userspec *us;
struct member *m;
@@ -250,7 +248,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle,
TAILQ_INIT(&us->users);
TAILQ_INIT(&us->privileges);
STAILQ_INIT(&us->comments);
TAILQ_INSERT_TAIL(sss_userspecs, us, entries);
TAILQ_INSERT_TAIL(&handle->parse_tree.userspecs, us, entries);
/* We only include rules where the user matches. */
if ((m = calloc(1, sizeof(*m))) == NULL)
@@ -387,7 +385,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle,
oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free_userspecs(sss_userspecs);
free_userspecs(&handle->parse_tree.userspecs);
debug_return_bool(false);
}
@@ -517,8 +515,7 @@ sudo_sss_close(struct sudo_nss *nss)
free(handle->ipa_host);
if (handle->ipa_host != handle->ipa_shost)
free(handle->ipa_shost);
free_userspecs(&handle->userspecs);
free_defaults(&handle->defaults);
free_parse_tree(&handle->parse_tree);
free(handle);
nss->handle = NULL;
}
@@ -544,9 +541,7 @@ sudo_sss_open(struct sudo_nss *nss)
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(ENOMEM);
}
TAILQ_INIT(&handle->userspecs);
TAILQ_INIT(&handle->defaults);
init_parse_tree(&handle->parse_tree);
/* Load symbols */
handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
@@ -625,18 +620,18 @@ sudo_sss_open(struct sudo_nss *nss)
/*
* Perform query for user and host and convert to sudoers parse tree.
*/
static struct userspec_list *
static int
sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
{
struct sudo_sss_handle *handle = nss->handle;
struct sss_sudo_result *sss_result = NULL;
struct userspec_list *ret = &handle->userspecs;
int ret = 0;
debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
debug_return_int(-1);
}
/* Use cached result if it matches pw. */
@@ -648,7 +643,7 @@ sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
}
/* Free old userspecs, if any. */
free_userspecs(&handle->userspecs);
free_userspecs(&handle->parse_tree.userspecs);
/* Fetch list of sudoRole entries that match user and host. */
sss_result = sudo_sss_result_get(nss, pw);
@@ -657,45 +652,59 @@ sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
"searching SSSD/LDAP for sudoers entries for user %s, host %s",
pw->pw_name, user_runhost);
if (sss_result == NULL)
goto done;
/* Stash a ref to the passwd struct in the handle. */
sudo_pw_addref(pw);
handle->pw = pw;
/* Convert to sudoers parse tree. */
if (!sss_to_sudoers(handle, sss_result, &handle->userspecs)) {
ret = NULL;
/* Convert to sudoers parse tree if the user was found. */
if (sss_result != NULL) {
if (!sss_to_sudoers(handle, sss_result)) {
ret = -1;
goto done;
}
}
done:
/* Cleanup */
handle->fn_free_result(sss_result);
if (ret == NULL) {
free_userspecs(&handle->userspecs);
if (ret == -1) {
free_userspecs(&handle->parse_tree.userspecs);
if (handle->pw != NULL) {
sudo_pw_delref(handle->pw);
handle->pw = NULL;
}
}
sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
debug_return_ptr(ret);
debug_return_int(ret);
}
/*
* Return the initialized (but empty) sudoers parse tree.
* The contents will be populated by the getdefs() and query() functions.
*/
static struct sudoers_parse_tree *
sudo_sss_parse(struct sudo_nss *nss)
{
struct sudo_sss_handle *handle = nss->handle;
debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
}
debug_return_ptr(&handle->parse_tree);
}
static int
sudo_sss_parse(struct sudo_nss *nss)
{
debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
debug_return_int(0);
}
static struct defaults_list *
sudo_sss_getdefs(struct sudo_nss *nss)
{
struct sudo_sss_handle *handle = nss->handle;
struct sss_sudo_result *sss_result = NULL;
static bool cached;
uint32_t sss_error;
unsigned int i;
int rc;
@@ -704,12 +713,12 @@ sudo_sss_getdefs(struct sudo_nss *nss)
if (handle == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: called with NULL handle", __func__);
debug_return_ptr(NULL);
debug_return_int(-1);
}
/* Use cached result if present. */
if (handle->cached_defaults)
debug_return_ptr(&handle->defaults);
if (cached)
debug_return_int(0);
sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
@@ -725,7 +734,7 @@ sudo_sss_getdefs(struct sudo_nss *nss)
default:
sudo_debug_printf(SUDO_DEBUG_ERROR,
"handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_error);
debug_return_ptr(NULL);
debug_return_int(-1);
}
switch (sss_error) {
@@ -735,7 +744,8 @@ sudo_sss_getdefs(struct sudo_nss *nss)
struct sss_sudo_rule *sss_rule = sss_result->rules + i;
sudo_debug_printf(SUDO_DEBUG_DIAG,
"Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
if (!sudo_sss_parse_options(handle, sss_rule, &handle->defaults))
if (!sudo_sss_parse_options(handle, sss_rule,
&handle->parse_tree.defaults))
goto bad;
}
break;
@@ -747,13 +757,13 @@ sudo_sss_getdefs(struct sudo_nss *nss)
sudo_debug_printf(SUDO_DEBUG_ERROR, "sss_error=%u\n", sss_error);
goto bad;
}
handle->cached_defaults = true;
handle->fn_free_result(sss_result);
debug_return_ptr(&handle->defaults);
cached = true;
debug_return_int(0);
bad:
handle->fn_free_result(sss_result);
debug_return_ptr(NULL);
debug_return_int(-1);
}
/* sudo_nss implementation */

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2007-2011, 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2007-2011, 2013-2015, 2017-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -21,14 +22,16 @@ struct passwd;
struct userspec_list;
struct defaults_list;
/* XXX - parse_tree, ret_if_found and ret_if_notfound should be private */
struct sudo_nss {
TAILQ_ENTRY(sudo_nss) entries;
int (*open)(struct sudo_nss *nss);
int (*close)(struct sudo_nss *nss);
int (*parse)(struct sudo_nss *nss);
struct userspec_list *(*query)(struct sudo_nss *nss, struct passwd *pw);
struct defaults_list *(*getdefs)(struct sudo_nss *nss);
struct sudoers_parse_tree *(*parse)(struct sudo_nss *nss);
int (*query)(struct sudo_nss *nss, struct passwd *pw);
int (*getdefs)(struct sudo_nss *nss);
void *handle;
struct sudoers_parse_tree *parse_tree;
bool ret_if_found;
bool ret_if_notfound;
};

View File

@@ -192,17 +192,17 @@ sudoers_policy_init(void *info, char * const envp[])
sudo_warn_set_locale_func(sudoers_warn_setlocale);
init_parser(sudoers_file, false);
TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
struct defaults_list *defs = nss->getdefs(nss);
if (nss->open(nss) == -1 || (nss->parse_tree = nss->parse(nss)) == NULL) {
TAILQ_REMOVE(snl, nss, entries);
continue;
}
sources++;
if (defs == NULL || !update_defaults(defs,
if (nss->getdefs(nss) == -1 || !update_defaults(nss->parse_tree,
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false)) {
log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
N_("problem with defaults entries"));
}
} else {
TAILQ_REMOVE(snl, nss, entries);
}
}
if (sources == 0) {
sudo_warnx(U_("no valid sudoers sources found, quitting"));
@@ -854,8 +854,7 @@ set_cmnd(void)
user_base = user_cmnd;
TAILQ_FOREACH(nss, snl, entries) {
struct defaults_list *defs = nss->getdefs(nss);
if (defs == NULL || !update_defaults(defs, SETDEF_CMND, false)) {
if (!update_defaults(nss->parse_tree, SETDEF_CMND, false)) {
log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
N_("problem with defaults entries"));
}

View File

@@ -285,7 +285,7 @@ main(int argc, char *argv[])
(void) fputs("Parses OK", stdout);
}
if (!update_defaults(&defaults, SETDEF_ALL, false))
if (!update_defaults(&parsed_policy, SETDEF_ALL, false))
(void) fputs(" (problem with defaults entries)", stdout);
puts(".");
@@ -301,22 +301,23 @@ main(int argc, char *argv[])
/* This loop must match the one in sudo_file_lookup() */
printf("\nEntries for user %s:\n", user_name);
match = UNSPEC;
TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
TAILQ_FOREACH_REVERSE(us, &parsed_policy.userspecs, userspec_list, entries) {
if (userlist_matches(&parsed_policy, sudo_user.pw, &us->users) != ALLOW)
continue;
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
sudo_lbuf_append(&lbuf, "\n");
sudoers_format_privilege(&lbuf, priv, false);
sudoers_format_privilege(&lbuf, &parsed_policy, priv, false);
sudo_lbuf_print(&lbuf);
host_match = hostlist_matches(sudo_user.pw, &priv->hostlist);
host_match = hostlist_matches(&parsed_policy, sudo_user.pw,
&priv->hostlist);
if (host_match == ALLOW) {
puts("\thost matched");
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
runas_match = runaslist_matches(cs->runasuserlist,
cs->runasgrouplist, NULL, NULL);
runas_match = runaslist_matches(&parsed_policy,
cs->runasuserlist, cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
puts("\trunas matched");
cmnd_match = cmnd_matches(cs->cmnd);
cmnd_match = cmnd_matches(&parsed_policy, cs->cmnd);
if (cmnd_match != UNSPEC)
match = cmnd_match;
printf("\tcmnd %s\n", match == ALLOW ? "allowed" :
@@ -483,8 +484,8 @@ print_defaults(struct sudo_lbuf *lbuf)
struct defaults *def, *next;
debug_decl(print_defaults, SUDOERS_DEBUG_UTIL)
TAILQ_FOREACH_SAFE(def, &defaults, entries, next)
sudoers_format_default_line(lbuf, def, &next, false);
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next)
sudoers_format_default_line(lbuf, &parsed_policy, def, &next, false);
debug_return_bool(!sudo_lbuf_error(lbuf));
}
@@ -502,7 +503,7 @@ print_alias(void *v1, void *v2)
TAILQ_FOREACH(m, &a->members, entries) {
if (m != TAILQ_FIRST(&a->members))
sudo_lbuf_append(lbuf, ", ");
sudoers_format_member(lbuf, m, NULL, UNSPEC);
sudoers_format_member(lbuf, &parsed_policy, m, NULL, UNSPEC);
}
sudo_lbuf_append(lbuf, "\n");
@@ -514,7 +515,7 @@ print_aliases(struct sudo_lbuf *lbuf)
{
debug_decl(print_aliases, SUDOERS_DEBUG_UTIL)
alias_apply(print_alias, lbuf);
alias_apply(&parsed_policy, print_alias, lbuf);
debug_return_bool(!sudo_lbuf_error(lbuf));
}
@@ -541,7 +542,7 @@ dump_sudoers(struct sudo_lbuf *lbuf)
}
/* Print User_Specs */
if (!sudoers_format_userspecs(lbuf, &userspecs, NULL, false, true))
if (!sudoers_format_userspecs(lbuf, &parsed_policy, NULL, false, true))
goto done;
if (lbuf->len > 1) {
sudo_lbuf_print(lbuf);

View File

@@ -246,8 +246,8 @@ main(int argc, char *argv[])
init_parser(sudoers_file, quiet);
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
(void) sudoersparse();
(void) update_defaults(&defaults, SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER,
quiet);
(void) update_defaults(&parsed_policy,
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, quiet);
sudoers_setlocale(oldlocale, NULL);
editor = get_editor(&editor_argc, &editor_argv);
@@ -538,13 +538,13 @@ check_defaults_and_aliases(bool strict, bool quiet)
{
debug_decl(check_defaults_and_aliases, SUDOERS_DEBUG_UTIL)
if (!check_defaults(quiet)) {
if (!check_defaults(&parsed_policy, quiet)) {
struct defaults *d;
rcstr_delref(errorfile);
errorfile = NULL;
errorlineno = -1;
/* XXX - should edit all files with errors */
TAILQ_FOREACH(d, &defaults, entries) {
TAILQ_FOREACH(d, &parsed_policy.defaults, entries) {
if (d->error) {
/* Defaults parse error, set errorfile/errorlineno. */
errorfile = rcstr_addref(d->file);
@@ -602,7 +602,7 @@ reparse_sudoers(char *editor, int editor_argc, char **editor_argv,
}
fclose(sudoersin);
if (!parse_error) {
(void) update_defaults(&defaults,
(void) update_defaults(&parsed_policy,
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
check_defaults_and_aliases(strict, quiet);
}
@@ -920,7 +920,7 @@ check_syntax(const char *sudoers_file, bool quiet, bool strict, bool oldperms)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
}
if (!parse_error) {
(void) update_defaults(&defaults,
(void) update_defaults(&parsed_policy,
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
check_defaults_and_aliases(strict, quiet);
}
@@ -1023,7 +1023,7 @@ check_alias(char *name, int type, char *file, int lineno, bool strict, bool quie
int errors = 0;
debug_decl(check_alias, SUDOERS_DEBUG_ALIAS)
if ((a = alias_get(name, type)) != NULL) {
if ((a = alias_get(&parsed_policy, name, type)) != NULL) {
/* check alias contents */
TAILQ_FOREACH(m, &a->members, entries) {
if (m->type != ALIAS)
@@ -1071,14 +1071,14 @@ check_aliases(bool strict, bool quiet)
int errors = 0;
debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS)
used_aliases = rbcreate(alias_compare);
used_aliases = alloc_aliases();
if (used_aliases == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1);
}
/* Forward check. */
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(us, &parsed_policy.userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, USERALIAS,
@@ -1118,13 +1118,13 @@ check_aliases(bool strict, bool quiet)
}
/* Reverse check (destructive) */
if (!alias_find_used(used_aliases))
if (!alias_find_used(&parsed_policy, used_aliases))
errors++;
rbdestroy(used_aliases, alias_free);
free_aliases(used_aliases);
/* If all aliases were referenced we will have an empty tree. */
if (!no_aliases() && !quiet)
alias_apply(print_unused, NULL);
if (!no_aliases(&parsed_policy) && !quiet)
alias_apply(&parsed_policy, print_unused, NULL);
debug_return_int(strict ? errors : 0);
}