mirror of
https://github.com/sudo-project/sudo.git
synced 2025-09-02 15:25:58 +00:00
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:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2005, 2007-2016
|
* Copyright (c) 2004-2005, 2007-2018
|
||||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -35,16 +35,11 @@
|
|||||||
#include "redblack.h"
|
#include "redblack.h"
|
||||||
#include <gram.h>
|
#include <gram.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* Globals
|
|
||||||
*/
|
|
||||||
static struct rbtree *aliases;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Comparison function for the red-black tree.
|
* Comparison function for the red-black tree.
|
||||||
* Aliases are sorted by name with the type used as a tie-breaker.
|
* Aliases are sorted by name with the type used as a tie-breaker.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
alias_compare(const void *v1, const void *v2)
|
alias_compare(const void *v1, const void *v2)
|
||||||
{
|
{
|
||||||
const struct alias *a1 = (const struct alias *)v1;
|
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.
|
* alias to mark it as unused.
|
||||||
*/
|
*/
|
||||||
struct alias *
|
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 alias key;
|
||||||
struct rbnode *node;
|
struct rbnode *node;
|
||||||
struct alias *a = NULL;
|
struct alias *a = NULL;
|
||||||
debug_decl(alias_get, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_get, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
|
if (parse_tree->aliases == NULL)
|
||||||
|
debug_return_ptr(NULL);
|
||||||
|
|
||||||
key.name = (char *)name;
|
key.name = (char *)name;
|
||||||
key.type = type;
|
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.
|
* Check whether this alias is already in use.
|
||||||
* If so, we've detected a loop. If not, set the flag,
|
* 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.
|
* Returns NULL on success and an error string on failure.
|
||||||
*/
|
*/
|
||||||
const char *
|
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];
|
static char errbuf[512];
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
debug_decl(alias_add, SUDOERS_DEBUG_ALIAS)
|
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));
|
a = calloc(1, sizeof(*a));
|
||||||
if (a == NULL) {
|
if (a == NULL) {
|
||||||
strlcpy(errbuf, N_("unable to allocate memory"), sizeof(errbuf));
|
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->file = rcstr_addref(file);
|
||||||
a->lineno = lineno;
|
a->lineno = lineno;
|
||||||
HLTQ_TO_TAILQ(&a->members, members, entries);
|
HLTQ_TO_TAILQ(&a->members, members, entries);
|
||||||
switch (rbinsert(aliases, a, NULL)) {
|
switch (rbinsert(parse_tree->aliases, a, NULL)) {
|
||||||
case 1:
|
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);
|
alias_free(a);
|
||||||
debug_return_str(errbuf);
|
debug_return_str(errbuf);
|
||||||
case -1:
|
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.
|
* Apply a function to each alias entry and pass in a cookie.
|
||||||
*/
|
*/
|
||||||
void
|
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)
|
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;
|
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
|
bool
|
||||||
no_aliases(void)
|
no_aliases(struct sudoers_parse_tree *parse_tree)
|
||||||
{
|
{
|
||||||
debug_decl(no_aliases, SUDOERS_DEBUG_ALIAS)
|
debug_decl(no_aliases, SUDOERS_DEBUG_ALIAS)
|
||||||
debug_return_bool(rbisempty(aliases));
|
debug_return_bool(parse_tree->aliases == NULL ||
|
||||||
}
|
rbisempty(parse_tree->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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -202,31 +198,37 @@ alias_free(void *v)
|
|||||||
* Find the named alias, remove it from the tree and return it.
|
* Find the named alias, remove it from the tree and return it.
|
||||||
*/
|
*/
|
||||||
struct alias *
|
struct alias *
|
||||||
alias_remove(char *name, int type)
|
alias_remove(struct sudoers_parse_tree *parse_tree, char *name, int type)
|
||||||
{
|
{
|
||||||
struct rbnode *node;
|
struct rbnode *node;
|
||||||
struct alias key;
|
struct alias key;
|
||||||
debug_decl(alias_remove, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_remove, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
key.name = name;
|
if (parse_tree->aliases != NULL) {
|
||||||
key.type = type;
|
key.name = name;
|
||||||
if ((node = rbfind(aliases, &key)) == NULL) {
|
key.type = type;
|
||||||
errno = ENOENT;
|
if ((node = rbfind(parse_tree->aliases, &key)) != NULL)
|
||||||
return NULL;
|
debug_return_ptr(rbdelete(parse_tree->aliases, node));
|
||||||
}
|
}
|
||||||
debug_return_ptr(rbdelete(aliases, node));
|
errno = ENOENT;
|
||||||
|
debug_return_ptr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
struct rbtree *
|
||||||
init_aliases(void)
|
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)
|
if (aliases != NULL)
|
||||||
rbdestroy(aliases, alias_free);
|
rbdestroy(aliases, alias_free);
|
||||||
aliases = rbcreate(alias_compare);
|
|
||||||
|
|
||||||
debug_return_bool(aliases != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@@ -244,17 +246,18 @@ alias_type_to_string(int alias_type)
|
|||||||
* referenced by that alias. Stores removed aliases in a freelist.
|
* referenced by that alias. Stores removed aliases in a freelist.
|
||||||
*/
|
*/
|
||||||
static bool
|
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 member *m;
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
debug_decl(alias_remove_recursive, SUDOERS_DEBUG_ALIAS)
|
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) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m->type == ALIAS) {
|
if (m->type == ALIAS) {
|
||||||
if (!alias_remove_recursive(m->name, type, freelist))
|
if (!alias_remove_recursive(parse_tree, m->name, type, freelist))
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,81 +267,80 @@ alias_remove_recursive(char *name, int type, struct rbtree *freelist)
|
|||||||
debug_return_bool(ret);
|
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.
|
* Move all aliases referenced by userspecs to used_aliases.
|
||||||
*/
|
*/
|
||||||
bool
|
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 privilege *priv;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
int atype, errors = 0;
|
int errors = 0;
|
||||||
debug_decl(alias_find_used, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_find_used, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
/* Move referenced aliases to used_aliases. */
|
/* Move referenced aliases to used_aliases. */
|
||||||
TAILQ_FOREACH(us, &userspecs, entries) {
|
TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
|
||||||
TAILQ_FOREACH(m, &us->users, entries) {
|
errors += alias_find_used_members(parse_tree, &us->users,
|
||||||
if (m->type == ALIAS) {
|
USERALIAS, used_aliases);
|
||||||
if (!alias_remove_recursive(m->name, USERALIAS, used_aliases))
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
||||||
TAILQ_FOREACH(m, &priv->hostlist, entries) {
|
errors += alias_find_used_members(parse_tree, &priv->hostlist,
|
||||||
if (m->type == ALIAS) {
|
HOSTALIAS, used_aliases);
|
||||||
if (!alias_remove_recursive(m->name, HOSTALIAS, used_aliases))
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
|
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
|
||||||
if (cs->runasuserlist != NULL) {
|
errors += alias_find_used_members(parse_tree, cs->runasuserlist,
|
||||||
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
|
RUNASALIAS, used_aliases);
|
||||||
if (m->type == ALIAS) {
|
errors += alias_find_used_members(parse_tree, cs->runasgrouplist,
|
||||||
if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases))
|
RUNASALIAS, used_aliases);
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cs->runasgrouplist != NULL) {
|
|
||||||
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
|
|
||||||
if (m->type == ALIAS) {
|
|
||||||
if (!alias_remove_recursive(m->name, RUNASALIAS, used_aliases))
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((m = cs->cmnd)->type == ALIAS) {
|
if ((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++;
|
errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(d, &defaults, entries) {
|
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case DEFAULTS_HOST:
|
case DEFAULTS_HOST:
|
||||||
atype = HOSTALIAS;
|
errors += alias_find_used_members(parse_tree, d->binding,
|
||||||
|
HOSTALIAS, used_aliases);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_USER:
|
case DEFAULTS_USER:
|
||||||
atype = USERALIAS;
|
errors += alias_find_used_members(parse_tree, d->binding,
|
||||||
|
USERALIAS, used_aliases);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_RUNAS:
|
case DEFAULTS_RUNAS:
|
||||||
atype = RUNASALIAS;
|
errors += alias_find_used_members(parse_tree, d->binding,
|
||||||
|
RUNASALIAS, used_aliases);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_CMND:
|
case DEFAULTS_CMND:
|
||||||
atype = CMNDALIAS;
|
errors += alias_find_used_members(parse_tree, d->binding,
|
||||||
|
CMNDALIAS, used_aliases);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue; /* not an alias */
|
break;
|
||||||
}
|
|
||||||
TAILQ_FOREACH(m, d->binding, entries) {
|
|
||||||
if (m->type == ALIAS) {
|
|
||||||
if (!alias_remove_recursive(m->name, atype, used_aliases))
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -703,7 +703,7 @@ userlist_matches_filter(struct member_list *users, struct cvtsudoers_config *con
|
|||||||
pw.pw_uid = (uid_t)-1;
|
pw.pw_uid = (uid_t)-1;
|
||||||
pw.pw_gid = (gid_t)-1;
|
pw.pw_gid = (gid_t)-1;
|
||||||
|
|
||||||
if (user_matches(&pw, m) == true)
|
if (user_matches(&parsed_policy, &pw, m) == true)
|
||||||
matched = true;
|
matched = true;
|
||||||
} else {
|
} else {
|
||||||
STAILQ_FOREACH(s, &filters->users, entries) {
|
STAILQ_FOREACH(s, &filters->users, entries) {
|
||||||
@@ -729,7 +729,7 @@ userlist_matches_filter(struct member_list *users, struct cvtsudoers_config *con
|
|||||||
if (pw == NULL)
|
if (pw == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (user_matches(pw, m) == true)
|
if (user_matches(&parsed_policy, pw, m) == true)
|
||||||
matched = true;
|
matched = true;
|
||||||
sudo_pw_delref(pw);
|
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. */
|
/* Only need one host in the filter to match. */
|
||||||
/* XXX - can't use netgroup_tuple with NULL pw */
|
/* 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;
|
matched = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -840,8 +840,10 @@ print_defaults_sudoers(struct sudo_lbuf *lbuf, bool expand_aliases)
|
|||||||
struct defaults *def, *next;
|
struct defaults *def, *next;
|
||||||
debug_decl(print_defaults_sudoers, SUDOERS_DEBUG_UTIL)
|
debug_decl(print_defaults_sudoers, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(def, &defaults, entries, next)
|
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next) {
|
||||||
sudoers_format_default_line(lbuf, def, &next, expand_aliases);
|
sudoers_format_default_line(lbuf, &parsed_policy, def, &next,
|
||||||
|
expand_aliases);
|
||||||
|
}
|
||||||
|
|
||||||
debug_return_bool(!sudo_lbuf_error(lbuf));
|
debug_return_bool(!sudo_lbuf_error(lbuf));
|
||||||
}
|
}
|
||||||
@@ -859,7 +861,7 @@ print_alias_sudoers(void *v1, void *v2)
|
|||||||
TAILQ_FOREACH(m, &a->members, entries) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m != TAILQ_FIRST(&a->members))
|
if (m != TAILQ_FIRST(&a->members))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
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");
|
sudo_lbuf_append(lbuf, "\n");
|
||||||
|
|
||||||
@@ -874,7 +876,7 @@ print_aliases_sudoers(struct sudo_lbuf *lbuf)
|
|||||||
{
|
{
|
||||||
debug_decl(print_aliases_sudoers, SUDOERS_DEBUG_UTIL)
|
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));
|
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.
|
* host lists. It acts more like a grep than a true filter.
|
||||||
* In the future, we may want to add a prune option.
|
* 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)) {
|
if (!userlist_matches_filter(&us->users, conf)) {
|
||||||
TAILQ_REMOVE(&userspecs, us, entries);
|
TAILQ_REMOVE(&parsed_policy.userspecs, us, entries);
|
||||||
free_userspec(us);
|
free_userspec(us);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -918,7 +920,7 @@ filter_userspecs(struct cvtsudoers_config *conf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TAILQ_EMPTY(&us->privileges)) {
|
if (TAILQ_EMPTY(&us->privileges)) {
|
||||||
TAILQ_REMOVE(&userspecs, us, entries);
|
TAILQ_REMOVE(&parsed_policy.userspecs, us, entries);
|
||||||
free_userspec(us);
|
free_userspec(us);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -942,7 +944,8 @@ alias_matches(const char *name, const char *alias_name, int alias_type)
|
|||||||
if (strcmp(name, alias_name) == 0)
|
if (strcmp(name, alias_name) == 0)
|
||||||
debug_return_bool(true);
|
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) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m->type != ALIAS)
|
if (m->type != ALIAS)
|
||||||
continue;
|
continue;
|
||||||
@@ -975,7 +978,7 @@ alias_used_by_userspecs(struct member_list *user_aliases,
|
|||||||
debug_decl(alias_used_by_userspecs, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_used_by_userspecs, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
/* Iterate over the policy, checking for aliases. */
|
/* 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) {
|
TAILQ_FOREACH_SAFE(m, &us->users, entries, m_next) {
|
||||||
if (m->type == ALIAS) {
|
if (m->type == ALIAS) {
|
||||||
/* If alias is used, remove from user_aliases and free. */
|
/* 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 member_list *prev_binding = NULL;
|
||||||
struct defaults *def, *def_next;
|
struct defaults *def, *def_next;
|
||||||
struct member *m, *m_next;
|
struct member *m, *m_next;
|
||||||
|
struct alias *a;
|
||||||
int alias_type;
|
int alias_type;
|
||||||
debug_decl(filter_defaults, SUDOERS_DEBUG_DEFAULTS)
|
debug_decl(filter_defaults, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
if (filters == NULL && conf->defaults == CVT_DEFAULTS_ALL)
|
if (filters == NULL && conf->defaults == CVT_DEFAULTS_ALL)
|
||||||
debug_return;
|
debug_return;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(def, &defaults, entries, def_next) {
|
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, def_next) {
|
||||||
bool keep = true;
|
bool keep = true;
|
||||||
|
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
@@ -1118,20 +1122,21 @@ filter_defaults(struct cvtsudoers_config *conf)
|
|||||||
TAILQ_INSERT_TAIL(&cmnd_aliases, m, entries);
|
TAILQ_INSERT_TAIL(&cmnd_aliases, m, entries);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sudo_fatalx_nodebug("unexpected alias type %d", alias_type);
|
sudo_fatalx_nodebug("unexpected alias type %d",
|
||||||
|
alias_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TAILQ_REMOVE(&defaults, def, entries);
|
TAILQ_REMOVE(&parsed_policy.defaults, def, entries);
|
||||||
free_default(def, &prev_binding);
|
free_default(def, &prev_binding);
|
||||||
if (prev_binding != NULL) {
|
if (prev_binding != NULL) {
|
||||||
/* Remove and free Defaults that share the same binding. */
|
/* Remove and free Defaults that share the same binding. */
|
||||||
while (def_next != NULL && def_next->binding == prev_binding) {
|
while (def_next != NULL && def_next->binding == prev_binding) {
|
||||||
def = def_next;
|
def = def_next;
|
||||||
def_next = TAILQ_NEXT(def, entries);
|
def_next = TAILQ_NEXT(def, entries);
|
||||||
TAILQ_REMOVE(&defaults, def, entries);
|
TAILQ_REMOVE(&parsed_policy.defaults, def, entries);
|
||||||
free_default(def, &prev_binding);
|
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,
|
alias_used_by_userspecs(&user_aliases, &runas_aliases, &host_aliases,
|
||||||
&cmnd_aliases);
|
&cmnd_aliases);
|
||||||
TAILQ_FOREACH_SAFE(m, &user_aliases, entries, m_next) {
|
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);
|
alias_free(a);
|
||||||
free_member(m);
|
free_member(m);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH_SAFE(m, &runas_aliases, entries, m_next) {
|
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);
|
alias_free(a);
|
||||||
free_member(m);
|
free_member(m);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH_SAFE(m, &host_aliases, entries, m_next) {
|
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);
|
alias_free(a);
|
||||||
free_member(m);
|
free_member(m);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH_SAFE(m, &cmnd_aliases, entries, m_next) {
|
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);
|
alias_free(a);
|
||||||
free_member(m);
|
free_member(m);
|
||||||
}
|
}
|
||||||
@@ -1174,20 +1179,19 @@ static void
|
|||||||
alias_remove_unused(void)
|
alias_remove_unused(void)
|
||||||
{
|
{
|
||||||
struct rbtree *used_aliases;
|
struct rbtree *used_aliases;
|
||||||
struct rbtree *unused_aliases;
|
|
||||||
debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
used_aliases = rbcreate(alias_compare);
|
used_aliases = alloc_aliases();
|
||||||
if (used_aliases == NULL)
|
if (used_aliases == NULL)
|
||||||
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
|
||||||
/* Move all referenced aliases to used_aliases. */
|
/* 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"));
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
|
||||||
/* Only unreferenced aliases are left, swap and free the unused ones. */
|
/* Only unreferenced aliases are left, swap and free the unused ones. */
|
||||||
unused_aliases = replace_aliases(used_aliases);
|
free_aliases(parsed_policy.aliases);
|
||||||
rbdestroy(unused_aliases, alias_free);
|
parsed_policy.aliases = used_aliases;
|
||||||
|
|
||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
@@ -1224,7 +1228,7 @@ alias_prune(struct cvtsudoers_config *conf)
|
|||||||
{
|
{
|
||||||
debug_decl(alias_prune, SUDOERS_DEBUG_ALIAS)
|
debug_decl(alias_prune, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
alias_apply(alias_prune_helper, conf);
|
alias_apply(&parsed_policy, alias_prune_helper, conf);
|
||||||
|
|
||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
@@ -1271,7 +1275,7 @@ convert_sudoers_sudoers(const char *output_file, struct cvtsudoers_config *conf)
|
|||||||
|
|
||||||
/* Print User_Specs, separated by blank lines. */
|
/* Print User_Specs, separated by blank lines. */
|
||||||
if (!ISSET(conf->suppress, SUPPRESS_PRIVS)) {
|
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)) {
|
conf->expand_aliases, true)) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@@ -475,7 +475,7 @@ print_member_json_int(FILE *fp, char *name, int type, bool negated,
|
|||||||
struct alias *a;
|
struct alias *a;
|
||||||
struct member *m;
|
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) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
print_member_json_int(fp, m->name, m->type,
|
print_member_json_int(fp, m->name, m->type,
|
||||||
negated ? !m->negated : m->negated,
|
negated ? !m->negated : m->negated,
|
||||||
@@ -661,13 +661,13 @@ print_defaults_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
|
|||||||
int type;
|
int type;
|
||||||
debug_decl(print_defaults_json, SUDOERS_DEBUG_UTIL)
|
debug_decl(print_defaults_json, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&defaults))
|
if (TAILQ_EMPTY(&parsed_policy.defaults))
|
||||||
debug_return_bool(need_comma);
|
debug_return_bool(need_comma);
|
||||||
|
|
||||||
fprintf(fp, "%s\n%*s\"Defaults\": [\n", need_comma ? "," : "", indent, "");
|
fprintf(fp, "%s\n%*s\"Defaults\": [\n", need_comma ? "," : "", indent, "");
|
||||||
indent += 4;
|
indent += 4;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
|
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next) {
|
||||||
type = get_defaults_type(def);
|
type = get_defaults_type(def);
|
||||||
if (type == -1) {
|
if (type == -1) {
|
||||||
sudo_warnx(U_("unknown defaults entry \"%s\""), def->var);
|
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.alias_type = alias_type;
|
||||||
closure.title = title;
|
closure.title = title;
|
||||||
closure.need_comma = need_comma;
|
closure.need_comma = need_comma;
|
||||||
alias_apply(print_alias_json, &closure);
|
alias_apply(&parsed_policy, print_alias_json, &closure);
|
||||||
if (closure.count != 0) {
|
if (closure.count != 0) {
|
||||||
print_indent(fp, closure.indent);
|
print_indent(fp, closure.indent);
|
||||||
fputs("]\n", fp);
|
fputs("]\n", fp);
|
||||||
@@ -1083,12 +1083,12 @@ print_userspecs_json(FILE *fp, int indent, bool expand_aliases, bool need_comma)
|
|||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
debug_decl(print_userspecs_json, SUDOERS_DEBUG_UTIL)
|
debug_decl(print_userspecs_json, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&userspecs))
|
if (TAILQ_EMPTY(&parsed_policy.userspecs))
|
||||||
debug_return_bool(need_comma);
|
debug_return_bool(need_comma);
|
||||||
|
|
||||||
fprintf(fp, "%s\n%*s\"User_Specs\": [\n", need_comma ? "," : "", indent, "");
|
fprintf(fp, "%s\n%*s\"User_Specs\": [\n", need_comma ? "," : "", indent, "");
|
||||||
indent += 4;
|
indent += 4;
|
||||||
TAILQ_FOREACH(us, &userspecs, entries) {
|
TAILQ_FOREACH(us, &parsed_policy.userspecs, entries) {
|
||||||
print_userspec_json(fp, us, indent, expand_aliases);
|
print_userspec_json(fp, us, indent, expand_aliases);
|
||||||
}
|
}
|
||||||
indent -= 4;
|
indent -= 4;
|
||||||
|
@@ -167,14 +167,14 @@ print_global_defaults_ldif(FILE *fp, const char *base)
|
|||||||
|
|
||||||
sudo_lbuf_init(&lbuf, NULL, 0, NULL, 80);
|
sudo_lbuf_init(&lbuf, NULL, 0, NULL, 80);
|
||||||
|
|
||||||
TAILQ_FOREACH(opt, &defaults, entries) {
|
TAILQ_FOREACH(opt, &parsed_policy.defaults, entries) {
|
||||||
/* Skip bound Defaults (unsupported). */
|
/* Skip bound Defaults (unsupported). */
|
||||||
if (opt->type == DEFAULTS) {
|
if (opt->type == DEFAULTS) {
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
lbuf.len = 0;
|
lbuf.len = 0;
|
||||||
sudo_lbuf_append(&lbuf, "# ");
|
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",
|
fprintf(fp, "# Unable to translate %s:%d\n%s\n",
|
||||||
opt->file, opt->lineno, lbuf.buf);
|
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, "cn", "defaults");
|
||||||
print_attribute_ldif(fp, "description", "Default sudoOption's go here");
|
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);
|
putc('\n', fp);
|
||||||
|
|
||||||
debug_return_bool(!ferror(fp));
|
debug_return_bool(!ferror(fp));
|
||||||
@@ -239,7 +239,7 @@ print_member_ldif(FILE *fp, char *name, int type, bool negated,
|
|||||||
free(attr_val);
|
free(attr_val);
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
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) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
print_member_ldif(fp, m->name, m->type,
|
print_member_ldif(fp, m->name, m->type,
|
||||||
negated ? !m->negated : m->negated, alias_type, attr_name);
|
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;
|
struct userspec *us;
|
||||||
debug_decl(print_userspecs_ldif, SUDOERS_DEBUG_UTIL)
|
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))
|
if (!print_userspec_ldif(fp, us, conf))
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
@@ -860,7 +860,7 @@ ldif_store_options(struct cvtsudoers_str_list *options)
|
|||||||
U_("unable to allocate memory"));
|
U_("unable to allocate memory"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TAILQ_INSERT_TAIL(&defaults, d, entries);
|
TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
|
||||||
}
|
}
|
||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
@@ -928,7 +928,7 @@ role_to_sudoers(struct sudo_role *role, bool store_options,
|
|||||||
|
|
||||||
if (reuse_userspec) {
|
if (reuse_userspec) {
|
||||||
/* Re-use the previous userspec */
|
/* Re-use the previous userspec */
|
||||||
us = TAILQ_LAST(&userspecs, userspec_list);
|
us = TAILQ_LAST(&parsed_policy.userspecs, userspec_list);
|
||||||
} else {
|
} else {
|
||||||
/* Allocate a new userspec and fill in the user list. */
|
/* Allocate a new userspec and fill in the user list. */
|
||||||
if ((us = calloc(1, sizeof(*us))) == NULL) {
|
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. */
|
/* Add finished userspec to the list if new. */
|
||||||
if (!reuse_userspec)
|
if (!reuse_userspec)
|
||||||
TAILQ_INSERT_TAIL(&userspecs, us, entries);
|
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, us, entries);
|
||||||
|
|
||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2005, 2007-2017
|
* Copyright (c) 1999-2005, 2007-2018
|
||||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* 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.
|
* Returns true if it matches, else false.
|
||||||
*/
|
*/
|
||||||
static bool
|
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)
|
debug_decl(default_binding_matches, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
@@ -705,19 +706,19 @@ default_binding_matches(struct defaults *d, int what)
|
|||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_USER:
|
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);
|
debug_return_bool(true);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_RUNAS:
|
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);
|
debug_return_bool(true);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_HOST:
|
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);
|
debug_return_bool(true);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_CMND:
|
case DEFAULTS_CMND:
|
||||||
if (cmndlist_matches(d->binding) == ALLOW)
|
if (cmndlist_matches(parse_tree, d->binding) == ALLOW)
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
break;
|
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.
|
* Pass in an OR'd list of which default types to update.
|
||||||
*/
|
*/
|
||||||
bool
|
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;
|
struct defaults *d;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
@@ -741,14 +742,14 @@ update_defaults(struct defaults_list *defs, int what, bool quiet)
|
|||||||
/*
|
/*
|
||||||
* First apply Defaults values marked as early.
|
* 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);
|
struct early_default *early = is_early_default(d->var);
|
||||||
if (early == NULL)
|
if (early == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Defaults type and binding must match. */
|
/* Defaults type and binding must match. */
|
||||||
if (!default_type_matches(d, what) ||
|
if (!default_type_matches(d, what) ||
|
||||||
!default_binding_matches(d, what))
|
!default_binding_matches(parse_tree, d, what))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Copy the value to sudo_defs_table and mark as early. */
|
/* 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.
|
* 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. */
|
/* Skip Defaults marked as early, we already did them. */
|
||||||
if (is_early_default(d->var))
|
if (is_early_default(d->var))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Defaults type and binding must match. */
|
/* Defaults type and binding must match. */
|
||||||
if (!default_type_matches(d, what) ||
|
if (!default_type_matches(d, what) ||
|
||||||
!default_binding_matches(d, what))
|
!default_binding_matches(parse_tree, d, what))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Copy the value to sudo_defs_table and run callback (if any) */
|
/* 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.
|
* Check all defaults entries without actually setting them.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
check_defaults(bool quiet)
|
check_defaults(struct sudoers_parse_tree *parse_tree, bool quiet)
|
||||||
{
|
{
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
int idx;
|
int idx;
|
||||||
debug_decl(check_defaults, SUDOERS_DEBUG_DEFAULTS)
|
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);
|
idx = find_default(d->var, d->file, d->lineno, quiet);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
struct sudo_defs_types *def = &sudo_defs_table[idx];
|
struct sudo_defs_types *def = &sudo_defs_table[idx];
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2005, 2008-2016
|
* Copyright (c) 1999-2005, 2008-2018
|
||||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -122,15 +122,15 @@ struct early_default {
|
|||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
struct defaults_list;
|
struct sudoers_parse_tree;
|
||||||
void dump_default(void);
|
void dump_default(void);
|
||||||
bool init_defaults(void);
|
bool init_defaults(void);
|
||||||
struct early_default *is_early_default(const char *name);
|
struct early_default *is_early_default(const char *name);
|
||||||
bool run_early_defaults(void);
|
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_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 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 update_defaults(struct sudoers_parse_tree *parse_tree, int what, bool quiet);
|
||||||
bool check_defaults(bool quiet);
|
bool check_defaults(struct sudoers_parse_tree *parse_tree, bool quiet);
|
||||||
|
|
||||||
extern struct sudo_defs_types sudo_defs_table[];
|
extern struct sudo_defs_types sudo_defs_table[];
|
||||||
|
|
||||||
|
@@ -40,8 +40,7 @@
|
|||||||
|
|
||||||
struct sudo_file_handle {
|
struct sudo_file_handle {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
struct defaults_list defaults;
|
struct sudoers_parse_tree parse_tree;
|
||||||
struct userspec_list userspecs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -54,9 +53,7 @@ sudo_file_close(struct sudo_nss *nss)
|
|||||||
fclose(handle->fp);
|
fclose(handle->fp);
|
||||||
sudoersin = NULL;
|
sudoersin = NULL;
|
||||||
|
|
||||||
free_userspecs(&handle->userspecs);
|
free_parse_tree(&handle->parse_tree);
|
||||||
free_defaults(&handle->defaults);
|
|
||||||
|
|
||||||
free(handle);
|
free(handle);
|
||||||
nss->handle = NULL;
|
nss->handle = NULL;
|
||||||
}
|
}
|
||||||
@@ -83,8 +80,7 @@ sudo_file_open(struct sudo_nss *nss)
|
|||||||
if (handle != NULL) {
|
if (handle != NULL) {
|
||||||
handle->fp = open_sudoers(sudoers_file, false, NULL);
|
handle->fp = open_sudoers(sudoers_file, false, NULL);
|
||||||
if (handle->fp != NULL) {
|
if (handle->fp != NULL) {
|
||||||
TAILQ_INIT(&handle->userspecs);
|
init_parse_tree(&handle->parse_tree);
|
||||||
TAILQ_INIT(&handle->defaults);
|
|
||||||
} else {
|
} else {
|
||||||
free(handle);
|
free(handle);
|
||||||
handle = NULL;
|
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)
|
sudo_file_parse(struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
debug_decl(sudo_file_close, SUDOERS_DEBUG_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) {
|
if (handle == NULL || handle->fp == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: called with NULL %s",
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: called with NULL %s",
|
||||||
__func__, handle ? "file pointer" : "handle");
|
__func__, handle ? "file pointer" : "handle");
|
||||||
debug_return_int(-1);
|
debug_return_ptr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sudoersin = handle->fp;
|
sudoersin = handle->fp;
|
||||||
@@ -117,49 +113,33 @@ sudo_file_parse(struct sudo_nss *nss)
|
|||||||
} else {
|
} else {
|
||||||
log_warningx(SLOG_SEND_MAIL, N_("parse error in %s"), errorfile);
|
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. */
|
/* Move parsed sudoers policy to nss handle. */
|
||||||
TAILQ_CONCAT(&handle->userspecs, &userspecs, entries);
|
reparent_parse_tree(&handle->parse_tree);
|
||||||
TAILQ_CONCAT(&handle->defaults, &defaults, entries);
|
|
||||||
|
|
||||||
|
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);
|
debug_return_int(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We return all cached userspecs, the parse functions will
|
* No need to get defaults for sudoers file, the parse function handled it.
|
||||||
* perform matching against pw for us.
|
|
||||||
*/
|
*/
|
||||||
static struct userspec_list *
|
static int
|
||||||
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 *
|
|
||||||
sudo_file_getdefs(struct sudo_nss *nss)
|
sudo_file_getdefs(struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
debug_decl(sudo_file_getdefs, SUDOERS_DEBUG_NSS)
|
debug_decl(sudo_file_getdefs, SUDOERS_DEBUG_NSS)
|
||||||
struct sudo_file_handle *handle = nss->handle;
|
debug_return_int(0);
|
||||||
|
|
||||||
if (handle == NULL) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
|
||||||
"%s: called with NULL handle", __func__);
|
|
||||||
debug_return_ptr(NULL);
|
|
||||||
}
|
|
||||||
debug_return_ptr(&handle->defaults);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sudo_nss implementation */
|
/* sudo_nss implementation */
|
||||||
|
@@ -37,8 +37,9 @@
|
|||||||
* the specified separator (which must not be NULL in the UNSPEC case).
|
* the specified separator (which must not be NULL in the UNSPEC case).
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
|
sudoers_format_member_int(struct sudo_lbuf *lbuf,
|
||||||
bool negated, const char *separator, int alias_type)
|
struct sudoers_parse_tree *parse_tree, char *name, int type, bool negated,
|
||||||
|
const char *separator, int alias_type)
|
||||||
{
|
{
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
@@ -81,13 +82,13 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
|
|||||||
goto print_word;
|
goto print_word;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if (alias_type != UNSPEC) {
|
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) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m != TAILQ_FIRST(&a->members))
|
if (m != TAILQ_FIRST(&a->members))
|
||||||
sudo_lbuf_append(lbuf, "%s", separator);
|
sudo_lbuf_append(lbuf, "%s", separator);
|
||||||
sudoers_format_member_int(lbuf, m->name, m->type,
|
sudoers_format_member_int(lbuf, parse_tree, m->name,
|
||||||
negated ? !m->negated : m->negated, separator,
|
m->type, negated ? !m->negated : m->negated,
|
||||||
alias_type);
|
separator, alias_type);
|
||||||
}
|
}
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
break;
|
break;
|
||||||
@@ -116,11 +117,12 @@ sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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)
|
const char *separator, int alias_type)
|
||||||
{
|
{
|
||||||
return sudoers_format_member_int(lbuf, m->name, m->type, m->negated,
|
return sudoers_format_member_int(lbuf, parse_tree, m->name, m->type,
|
||||||
separator, alias_type);
|
m->negated, separator, alias_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIELD_CHANGED(ocs, ncs, fld) \
|
#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.
|
* Write a cmndspec to lbuf in sudoers format.
|
||||||
*/
|
*/
|
||||||
bool
|
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)
|
struct cmndspec *prev_cs, bool expand_aliases)
|
||||||
{
|
{
|
||||||
debug_decl(sudoers_format_cmndspec, SUDOERS_DEBUG_UTIL)
|
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: ");
|
sudo_lbuf_append(lbuf, cs->tags.send_mail ? "MAIL: " : "NOMAIL: ");
|
||||||
if (TAG_CHANGED(prev_cs, cs, follow))
|
if (TAG_CHANGED(prev_cs, cs, follow))
|
||||||
sudo_lbuf_append(lbuf, cs->tags.follow ? "FOLLOW: " : "NOFOLLOW: ");
|
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);
|
expand_aliases ? CMNDALIAS : UNSPEC);
|
||||||
debug_return_bool(!sudo_lbuf_error(lbuf));
|
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.
|
* Write a privilege to lbuf in sudoers format.
|
||||||
*/
|
*/
|
||||||
bool
|
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)
|
bool expand_aliases)
|
||||||
{
|
{
|
||||||
struct cmndspec *cs, *prev_cs;
|
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) {
|
TAILQ_FOREACH(m, &priv->hostlist, entries) {
|
||||||
if (m != TAILQ_FIRST(&priv->hostlist))
|
if (m != TAILQ_FIRST(&priv->hostlist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ",
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
expand_aliases ? HOSTALIAS : UNSPEC);
|
expand_aliases ? HOSTALIAS : UNSPEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +226,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
|
|||||||
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
|
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasuserlist))
|
if (m != TAILQ_FIRST(cs->runasuserlist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ",
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
expand_aliases ? RUNASALIAS : UNSPEC);
|
expand_aliases ? RUNASALIAS : UNSPEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +235,7 @@ sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv,
|
|||||||
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ",
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
expand_aliases ? RUNASALIAS : UNSPEC);
|
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)) {
|
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
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;
|
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.
|
* Write a userspec to lbuf in sudoers format.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
|
sudoers_format_userspec(struct sudo_lbuf *lbuf,
|
||||||
bool expand_aliases)
|
struct sudoers_parse_tree *parse_tree,
|
||||||
|
struct userspec *us, bool expand_aliases)
|
||||||
{
|
{
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct sudoers_comment *comment;
|
struct sudoers_comment *comment;
|
||||||
@@ -268,7 +273,7 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
|
|||||||
TAILQ_FOREACH(m, &us->users, entries) {
|
TAILQ_FOREACH(m, &us->users, entries) {
|
||||||
if (m != TAILQ_FIRST(&us->users))
|
if (m != TAILQ_FIRST(&us->users))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ",
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
expand_aliases ? USERALIAS : UNSPEC);
|
expand_aliases ? USERALIAS : UNSPEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +282,7 @@ sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us,
|
|||||||
sudo_lbuf_append(lbuf, " : ");
|
sudo_lbuf_append(lbuf, " : ");
|
||||||
else
|
else
|
||||||
sudo_lbuf_append(lbuf, " ");
|
sudo_lbuf_append(lbuf, " ");
|
||||||
if (!sudoers_format_privilege(lbuf, priv, expand_aliases))
|
if (!sudoers_format_privilege(lbuf, parse_tree, priv, expand_aliases))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sudo_lbuf_append(lbuf, "\n");
|
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.
|
* Write a userspec_list to lbuf in sudoers format.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sudoers_format_userspecs(struct sudo_lbuf *lbuf, struct userspec_list *usl,
|
sudoers_format_userspecs(struct sudo_lbuf *lbuf,
|
||||||
const char *separator, bool expand_aliases, bool flush)
|
struct sudoers_parse_tree *parse_tree, const char *separator,
|
||||||
|
bool expand_aliases, bool flush)
|
||||||
{
|
{
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL)
|
debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
TAILQ_FOREACH(us, usl, entries) {
|
TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
|
||||||
if (separator != NULL && us != TAILQ_FIRST(usl))
|
if (separator != NULL && us != TAILQ_FIRST(&parse_tree->userspecs))
|
||||||
sudo_lbuf_append(lbuf, "%s", separator);
|
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;
|
break;
|
||||||
sudo_lbuf_print(lbuf);
|
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.
|
* entries with the same binding on a single line.
|
||||||
*/
|
*/
|
||||||
bool
|
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 defaults **next, bool expand_aliases)
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
@@ -369,7 +376,7 @@ sudoers_format_default_line(struct sudo_lbuf *lbuf, struct defaults *d,
|
|||||||
TAILQ_FOREACH(m, d->binding, entries) {
|
TAILQ_FOREACH(m, d->binding, entries) {
|
||||||
if (m != TAILQ_FIRST(d->binding))
|
if (m != TAILQ_FIRST(d->binding))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ", alias_type);
|
sudoers_format_member(lbuf, parse_tree, m, ", ", alias_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
sudo_lbuf_append(lbuf, " ");
|
sudo_lbuf_append(lbuf, " ");
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
#define YYPREFIX "sudoers"
|
#define YYPREFIX "sudoers"
|
||||||
#line 2 "gram.y"
|
#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>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -98,8 +98,11 @@ bool parse_error = false;
|
|||||||
int errorlineno = -1;
|
int errorlineno = -1;
|
||||||
char *errorfile = NULL;
|
char *errorfile = NULL;
|
||||||
|
|
||||||
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
|
struct sudoers_parse_tree parsed_policy = {
|
||||||
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
|
TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
|
||||||
|
TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
|
||||||
|
NULL /* aliases */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local protoypes
|
* Local protoypes
|
||||||
@@ -110,7 +113,7 @@ static bool add_userspec(struct member *, struct privilege *);
|
|||||||
static struct defaults *new_default(char *, char *, short);
|
static struct defaults *new_default(char *, char *, short);
|
||||||
static struct member *new_member(char *, int);
|
static struct member *new_member(char *, int);
|
||||||
static struct command_digest *new_digest(int, char *);
|
static struct command_digest *new_digest(int, char *);
|
||||||
#line 77 "gram.y"
|
#line 80 "gram.y"
|
||||||
#ifndef YYSTYPE_DEFINED
|
#ifndef YYSTYPE_DEFINED
|
||||||
#define YYSTYPE_DEFINED
|
#define YYSTYPE_DEFINED
|
||||||
typedef union {
|
typedef union {
|
||||||
@@ -127,7 +130,7 @@ typedef union {
|
|||||||
int tok;
|
int tok;
|
||||||
} YYSTYPE;
|
} YYSTYPE;
|
||||||
#endif /* YYSTYPE_DEFINED */
|
#endif /* YYSTYPE_DEFINED */
|
||||||
#line 130 "gram.c"
|
#line 133 "gram.c"
|
||||||
#define COMMAND 257
|
#define COMMAND 257
|
||||||
#define ALIAS 258
|
#define ALIAS 258
|
||||||
#define DEFVAR 259
|
#define DEFVAR 259
|
||||||
@@ -667,7 +670,7 @@ short *yysslim;
|
|||||||
YYSTYPE *yyvs;
|
YYSTYPE *yyvs;
|
||||||
unsigned int yystacksize;
|
unsigned int yystacksize;
|
||||||
int yyparse(void);
|
int yyparse(void);
|
||||||
#line 899 "gram.y"
|
#line 906 "gram.y"
|
||||||
void
|
void
|
||||||
sudoerserror(const char *s)
|
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) {
|
HLTQ_FOREACH_SAFE(d, defs, entries, next) {
|
||||||
d->type = type;
|
d->type = type;
|
||||||
d->binding = binding;
|
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->users, members, entries);
|
||||||
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
|
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
|
||||||
STAILQ_INIT(&u->comments);
|
STAILQ_INIT(&u->comments);
|
||||||
TAILQ_INSERT_TAIL(&userspecs, u, entries);
|
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
@@ -1007,6 +1010,41 @@ free_userspec(struct userspec *us)
|
|||||||
debug_return;
|
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
|
* Free up space used by data structures from a previous parser run and sets
|
||||||
* the current sudoers file to path.
|
* the current sudoers file to path.
|
||||||
@@ -1017,15 +1055,9 @@ init_parser(const char *path, bool quiet)
|
|||||||
bool ret = true;
|
bool ret = true;
|
||||||
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
|
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
free_userspecs(&userspecs);
|
free_parse_tree(&parsed_policy);
|
||||||
free_defaults(&defaults);
|
|
||||||
init_lexer();
|
init_lexer();
|
||||||
|
|
||||||
if (!init_aliases()) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcstr_delref(sudoers);
|
rcstr_delref(sudoers);
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
if ((sudoers = rcstr_dup(path)) == NULL) {
|
if ((sudoers = rcstr_dup(path)) == NULL) {
|
||||||
@@ -1063,7 +1095,7 @@ init_options(struct command_options *opts)
|
|||||||
opts->limitprivs = NULL;
|
opts->limitprivs = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#line 1014 "gram.c"
|
#line 1046 "gram.c"
|
||||||
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
|
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
|
||||||
#if defined(__cplusplus) || defined(__STDC__)
|
#if defined(__cplusplus) || defined(__STDC__)
|
||||||
static int yygrowstack(void)
|
static int yygrowstack(void)
|
||||||
@@ -1272,23 +1304,23 @@ yyreduce:
|
|||||||
switch (yyn)
|
switch (yyn)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
#line 175 "gram.y"
|
#line 178 "gram.y"
|
||||||
{ ; }
|
{ ; }
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
#line 183 "gram.y"
|
#line 186 "gram.y"
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
#line 186 "gram.y"
|
#line 189 "gram.y"
|
||||||
{
|
{
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
#line 189 "gram.y"
|
#line 192 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
|
if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
|
||||||
sudoerserror(N_("unable to allocate memory"));
|
sudoerserror(N_("unable to allocate memory"));
|
||||||
@@ -1297,73 +1329,73 @@ case 7:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
#line 195 "gram.y"
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
#line 198 "gram.y"
|
#line 198 "gram.y"
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 9:
|
||||||
#line 201 "gram.y"
|
#line 201 "gram.y"
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 10:
|
||||||
#line 204 "gram.y"
|
#line 204 "gram.y"
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 11:
|
||||||
#line 207 "gram.y"
|
#line 207 "gram.y"
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
#line 210 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
|
if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
#line 211 "gram.y"
|
#line 214 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
|
if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
#line 215 "gram.y"
|
#line 218 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
|
if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
#line 219 "gram.y"
|
#line 222 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
|
if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
#line 223 "gram.y"
|
#line 226 "gram.y"
|
||||||
{
|
{
|
||||||
if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
|
if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
#line 230 "gram.y"
|
#line 233 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
|
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
|
||||||
yyval.defaults = yyvsp[-2].defaults;
|
yyval.defaults = yyvsp[-2].defaults;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 19:
|
case 19:
|
||||||
#line 236 "gram.y"
|
#line 239 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.defaults = new_default(yyvsp[0].string, NULL, true);
|
yyval.defaults = new_default(yyvsp[0].string, NULL, true);
|
||||||
if (yyval.defaults == NULL) {
|
if (yyval.defaults == NULL) {
|
||||||
@@ -1373,7 +1405,7 @@ case 19:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 20:
|
||||||
#line 243 "gram.y"
|
#line 246 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.defaults = new_default(yyvsp[0].string, NULL, false);
|
yyval.defaults = new_default(yyvsp[0].string, NULL, false);
|
||||||
if (yyval.defaults == NULL) {
|
if (yyval.defaults == NULL) {
|
||||||
@@ -1383,7 +1415,7 @@ case 20:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 21:
|
case 21:
|
||||||
#line 250 "gram.y"
|
#line 253 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
|
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
|
||||||
if (yyval.defaults == NULL) {
|
if (yyval.defaults == NULL) {
|
||||||
@@ -1393,7 +1425,7 @@ case 21:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 22:
|
case 22:
|
||||||
#line 257 "gram.y"
|
#line 260 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
|
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
|
||||||
if (yyval.defaults == NULL) {
|
if (yyval.defaults == NULL) {
|
||||||
@@ -1403,7 +1435,7 @@ case 22:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 23:
|
case 23:
|
||||||
#line 264 "gram.y"
|
#line 267 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
|
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
|
||||||
if (yyval.defaults == NULL) {
|
if (yyval.defaults == NULL) {
|
||||||
@@ -1413,14 +1445,14 @@ case 23:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 25:
|
||||||
#line 274 "gram.y"
|
#line 277 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
|
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
|
||||||
yyval.privilege = yyvsp[-2].privilege;
|
yyval.privilege = yyvsp[-2].privilege;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 26:
|
case 26:
|
||||||
#line 280 "gram.y"
|
#line 283 "gram.y"
|
||||||
{
|
{
|
||||||
struct privilege *p = calloc(1, sizeof(*p));
|
struct privilege *p = calloc(1, sizeof(*p));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@@ -1435,21 +1467,21 @@ case 26:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27:
|
case 27:
|
||||||
#line 294 "gram.y"
|
#line 297 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = false;
|
yyval.member->negated = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 28:
|
case 28:
|
||||||
#line 298 "gram.y"
|
#line 301 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = true;
|
yyval.member->negated = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 29:
|
case 29:
|
||||||
#line 304 "gram.y"
|
#line 307 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1459,7 +1491,7 @@ case 29:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 30:
|
case 30:
|
||||||
#line 311 "gram.y"
|
#line 314 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(NULL, ALL);
|
yyval.member = new_member(NULL, ALL);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1469,7 +1501,7 @@ case 30:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 31:
|
case 31:
|
||||||
#line 318 "gram.y"
|
#line 321 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, NETGROUP);
|
yyval.member = new_member(yyvsp[0].string, NETGROUP);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1479,7 +1511,7 @@ case 31:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
#line 325 "gram.y"
|
#line 328 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
|
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1489,7 +1521,7 @@ case 32:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 33:
|
case 33:
|
||||||
#line 332 "gram.y"
|
#line 335 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, WORD);
|
yyval.member = new_member(yyvsp[0].string, WORD);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1499,7 +1531,7 @@ case 33:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 35:
|
case 35:
|
||||||
#line 342 "gram.y"
|
#line 345 "gram.y"
|
||||||
{
|
{
|
||||||
struct cmndspec *prev;
|
struct cmndspec *prev;
|
||||||
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
|
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
|
||||||
@@ -1553,7 +1585,7 @@ case 35:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 36:
|
case 36:
|
||||||
#line 395 "gram.y"
|
#line 398 "gram.y"
|
||||||
{
|
{
|
||||||
struct cmndspec *cs = calloc(1, sizeof(*cs));
|
struct cmndspec *cs = calloc(1, sizeof(*cs));
|
||||||
if (cs == NULL) {
|
if (cs == NULL) {
|
||||||
@@ -1605,7 +1637,7 @@ case 36:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
#line 446 "gram.y"
|
#line 449 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
|
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
|
||||||
if (yyval.digest == NULL) {
|
if (yyval.digest == NULL) {
|
||||||
@@ -1615,7 +1647,7 @@ case 37:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 38:
|
case 38:
|
||||||
#line 453 "gram.y"
|
#line 456 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
|
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
|
||||||
if (yyval.digest == NULL) {
|
if (yyval.digest == NULL) {
|
||||||
@@ -1625,7 +1657,7 @@ case 38:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 39:
|
||||||
#line 460 "gram.y"
|
#line 463 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
|
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
|
||||||
if (yyval.digest == NULL) {
|
if (yyval.digest == NULL) {
|
||||||
@@ -1635,7 +1667,7 @@ case 39:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 40:
|
case 40:
|
||||||
#line 467 "gram.y"
|
#line 470 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
|
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
|
||||||
if (yyval.digest == NULL) {
|
if (yyval.digest == NULL) {
|
||||||
@@ -1645,13 +1677,13 @@ case 40:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 41:
|
case 41:
|
||||||
#line 476 "gram.y"
|
#line 479 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 42:
|
case 42:
|
||||||
#line 479 "gram.y"
|
#line 482 "gram.y"
|
||||||
{
|
{
|
||||||
if (yyvsp[0].member->type != COMMAND) {
|
if (yyvsp[0].member->type != COMMAND) {
|
||||||
sudoerserror(N_("a digest requires a path name"));
|
sudoerserror(N_("a digest requires a path name"));
|
||||||
@@ -1663,75 +1695,75 @@ case 42:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 43:
|
case 43:
|
||||||
#line 490 "gram.y"
|
#line 493 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = false;
|
yyval.member->negated = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 44:
|
case 44:
|
||||||
#line 494 "gram.y"
|
#line 497 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = true;
|
yyval.member->negated = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 45:
|
case 45:
|
||||||
#line 500 "gram.y"
|
#line 503 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 46:
|
case 46:
|
||||||
#line 505 "gram.y"
|
#line 508 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 47:
|
case 47:
|
||||||
#line 509 "gram.y"
|
#line 512 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 48:
|
case 48:
|
||||||
#line 514 "gram.y"
|
#line 517 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 49:
|
case 49:
|
||||||
#line 519 "gram.y"
|
#line 522 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 50:
|
case 50:
|
||||||
#line 524 "gram.y"
|
#line 527 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 51:
|
case 51:
|
||||||
#line 528 "gram.y"
|
#line 531 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.string = yyvsp[0].string;
|
yyval.string = yyvsp[0].string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 52:
|
case 52:
|
||||||
#line 533 "gram.y"
|
#line 536 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = NULL;
|
yyval.runas = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 53:
|
case 53:
|
||||||
#line 536 "gram.y"
|
#line 539 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = yyvsp[-1].runas;
|
yyval.runas = yyvsp[-1].runas;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 54:
|
case 54:
|
||||||
#line 541 "gram.y"
|
#line 544 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
||||||
if (yyval.runas != NULL) {
|
if (yyval.runas != NULL) {
|
||||||
@@ -1749,7 +1781,7 @@ case 54:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 55:
|
case 55:
|
||||||
#line 556 "gram.y"
|
#line 559 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
||||||
if (yyval.runas == NULL) {
|
if (yyval.runas == NULL) {
|
||||||
@@ -1761,7 +1793,7 @@ case 55:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 56:
|
case 56:
|
||||||
#line 565 "gram.y"
|
#line 568 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
||||||
if (yyval.runas == NULL) {
|
if (yyval.runas == NULL) {
|
||||||
@@ -1773,7 +1805,7 @@ case 56:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 57:
|
case 57:
|
||||||
#line 574 "gram.y"
|
#line 577 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
||||||
if (yyval.runas == NULL) {
|
if (yyval.runas == NULL) {
|
||||||
@@ -1785,7 +1817,7 @@ case 57:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 58:
|
case 58:
|
||||||
#line 583 "gram.y"
|
#line 586 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
yyval.runas = calloc(1, sizeof(struct runascontainer));
|
||||||
if (yyval.runas != NULL) {
|
if (yyval.runas != NULL) {
|
||||||
@@ -1803,13 +1835,13 @@ case 58:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 59:
|
case 59:
|
||||||
#line 600 "gram.y"
|
#line 603 "gram.y"
|
||||||
{
|
{
|
||||||
init_options(&yyval.options);
|
init_options(&yyval.options);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 60:
|
case 60:
|
||||||
#line 603 "gram.y"
|
#line 606 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.options.notbefore = parse_gentime(yyvsp[0].string);
|
yyval.options.notbefore = parse_gentime(yyvsp[0].string);
|
||||||
free(yyvsp[0].string);
|
free(yyvsp[0].string);
|
||||||
@@ -1820,7 +1852,7 @@ case 60:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 61:
|
case 61:
|
||||||
#line 611 "gram.y"
|
#line 614 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.options.notafter = parse_gentime(yyvsp[0].string);
|
yyval.options.notafter = parse_gentime(yyvsp[0].string);
|
||||||
free(yyvsp[0].string);
|
free(yyvsp[0].string);
|
||||||
@@ -1831,7 +1863,7 @@ case 61:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 62:
|
case 62:
|
||||||
#line 619 "gram.y"
|
#line 622 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.options.timeout = parse_timeout(yyvsp[0].string);
|
yyval.options.timeout = parse_timeout(yyvsp[0].string);
|
||||||
free(yyvsp[0].string);
|
free(yyvsp[0].string);
|
||||||
@@ -1845,7 +1877,7 @@ case 62:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 63:
|
case 63:
|
||||||
#line 630 "gram.y"
|
#line 633 "gram.y"
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
free(yyval.options.role);
|
free(yyval.options.role);
|
||||||
@@ -1854,7 +1886,7 @@ case 63:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
#line 636 "gram.y"
|
#line 639 "gram.y"
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
free(yyval.options.type);
|
free(yyval.options.type);
|
||||||
@@ -1863,7 +1895,7 @@ case 64:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 65:
|
case 65:
|
||||||
#line 642 "gram.y"
|
#line 645 "gram.y"
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PRIV_SET
|
#ifdef HAVE_PRIV_SET
|
||||||
free(yyval.options.privs);
|
free(yyval.options.privs);
|
||||||
@@ -1872,7 +1904,7 @@ case 65:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 66:
|
case 66:
|
||||||
#line 648 "gram.y"
|
#line 651 "gram.y"
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PRIV_SET
|
#ifdef HAVE_PRIV_SET
|
||||||
free(yyval.options.limitprivs);
|
free(yyval.options.limitprivs);
|
||||||
@@ -1881,97 +1913,97 @@ case 66:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 67:
|
case 67:
|
||||||
#line 656 "gram.y"
|
#line 659 "gram.y"
|
||||||
{
|
{
|
||||||
TAGS_INIT(yyval.tag);
|
TAGS_INIT(yyval.tag);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 68:
|
case 68:
|
||||||
#line 659 "gram.y"
|
#line 662 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.nopasswd = true;
|
yyval.tag.nopasswd = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 69:
|
case 69:
|
||||||
#line 662 "gram.y"
|
#line 665 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.nopasswd = false;
|
yyval.tag.nopasswd = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 70:
|
case 70:
|
||||||
#line 665 "gram.y"
|
#line 668 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.noexec = true;
|
yyval.tag.noexec = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 71:
|
case 71:
|
||||||
#line 668 "gram.y"
|
#line 671 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.noexec = false;
|
yyval.tag.noexec = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 72:
|
case 72:
|
||||||
#line 671 "gram.y"
|
#line 674 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.setenv = true;
|
yyval.tag.setenv = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 73:
|
case 73:
|
||||||
#line 674 "gram.y"
|
#line 677 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.setenv = false;
|
yyval.tag.setenv = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 74:
|
case 74:
|
||||||
#line 677 "gram.y"
|
#line 680 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.log_input = true;
|
yyval.tag.log_input = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 75:
|
case 75:
|
||||||
#line 680 "gram.y"
|
#line 683 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.log_input = false;
|
yyval.tag.log_input = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 76:
|
case 76:
|
||||||
#line 683 "gram.y"
|
#line 686 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.log_output = true;
|
yyval.tag.log_output = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 77:
|
case 77:
|
||||||
#line 686 "gram.y"
|
#line 689 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.log_output = false;
|
yyval.tag.log_output = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 78:
|
case 78:
|
||||||
#line 689 "gram.y"
|
#line 692 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.follow = true;
|
yyval.tag.follow = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 79:
|
case 79:
|
||||||
#line 692 "gram.y"
|
#line 695 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.follow = false;
|
yyval.tag.follow = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 80:
|
case 80:
|
||||||
#line 695 "gram.y"
|
#line 698 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.send_mail = true;
|
yyval.tag.send_mail = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 81:
|
case 81:
|
||||||
#line 698 "gram.y"
|
#line 701 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.tag.send_mail = false;
|
yyval.tag.send_mail = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 82:
|
case 82:
|
||||||
#line 703 "gram.y"
|
#line 706 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(NULL, ALL);
|
yyval.member = new_member(NULL, ALL);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1981,7 +2013,7 @@ case 82:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 83:
|
case 83:
|
||||||
#line 710 "gram.y"
|
#line 713 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -1991,7 +2023,7 @@ case 83:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 84:
|
case 84:
|
||||||
#line 717 "gram.y"
|
#line 720 "gram.y"
|
||||||
{
|
{
|
||||||
struct sudo_command *c = calloc(1, sizeof(*c));
|
struct sudo_command *c = calloc(1, sizeof(*c));
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
@@ -2009,10 +2041,11 @@ case 84:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 87:
|
case 87:
|
||||||
#line 738 "gram.y"
|
#line 741 "gram.y"
|
||||||
{
|
{
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -2020,17 +2053,18 @@ case 87:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 89:
|
case 89:
|
||||||
#line 749 "gram.y"
|
#line 753 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
||||||
yyval.member = yyvsp[-2].member;
|
yyval.member = yyvsp[-2].member;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 92:
|
case 92:
|
||||||
#line 759 "gram.y"
|
#line 763 "gram.y"
|
||||||
{
|
{
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -2038,17 +2072,18 @@ case 92:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 94:
|
case 94:
|
||||||
#line 770 "gram.y"
|
#line 775 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
||||||
yyval.member = yyvsp[-2].member;
|
yyval.member = yyvsp[-2].member;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 97:
|
case 97:
|
||||||
#line 780 "gram.y"
|
#line 785 "gram.y"
|
||||||
{
|
{
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -2056,10 +2091,11 @@ case 97:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 100:
|
case 100:
|
||||||
#line 794 "gram.y"
|
#line 800 "gram.y"
|
||||||
{
|
{
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -2067,28 +2103,28 @@ case 100:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 102:
|
case 102:
|
||||||
#line 805 "gram.y"
|
#line 812 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
||||||
yyval.member = yyvsp[-2].member;
|
yyval.member = yyvsp[-2].member;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 103:
|
case 103:
|
||||||
#line 811 "gram.y"
|
#line 818 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = false;
|
yyval.member->negated = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 104:
|
case 104:
|
||||||
#line 815 "gram.y"
|
#line 822 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = true;
|
yyval.member->negated = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 105:
|
case 105:
|
||||||
#line 821 "gram.y"
|
#line 828 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2098,7 +2134,7 @@ case 105:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 106:
|
case 106:
|
||||||
#line 828 "gram.y"
|
#line 835 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(NULL, ALL);
|
yyval.member = new_member(NULL, ALL);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2108,7 +2144,7 @@ case 106:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 107:
|
case 107:
|
||||||
#line 835 "gram.y"
|
#line 842 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, NETGROUP);
|
yyval.member = new_member(yyvsp[0].string, NETGROUP);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2118,7 +2154,7 @@ case 107:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 108:
|
case 108:
|
||||||
#line 842 "gram.y"
|
#line 849 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, USERGROUP);
|
yyval.member = new_member(yyvsp[0].string, USERGROUP);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2128,7 +2164,7 @@ case 108:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 109:
|
case 109:
|
||||||
#line 849 "gram.y"
|
#line 856 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, WORD);
|
yyval.member = new_member(yyvsp[0].string, WORD);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2138,28 +2174,28 @@ case 109:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 111:
|
case 111:
|
||||||
#line 859 "gram.y"
|
#line 866 "gram.y"
|
||||||
{
|
{
|
||||||
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
|
||||||
yyval.member = yyvsp[-2].member;
|
yyval.member = yyvsp[-2].member;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 112:
|
case 112:
|
||||||
#line 865 "gram.y"
|
#line 872 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = false;
|
yyval.member->negated = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 113:
|
case 113:
|
||||||
#line 869 "gram.y"
|
#line 876 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = yyvsp[0].member;
|
yyval.member = yyvsp[0].member;
|
||||||
yyval.member->negated = true;
|
yyval.member->negated = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 114:
|
case 114:
|
||||||
#line 875 "gram.y"
|
#line 882 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
yyval.member = new_member(yyvsp[0].string, ALIAS);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2169,7 +2205,7 @@ case 114:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 115:
|
case 115:
|
||||||
#line 882 "gram.y"
|
#line 889 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(NULL, ALL);
|
yyval.member = new_member(NULL, ALL);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2179,7 +2215,7 @@ case 115:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 116:
|
case 116:
|
||||||
#line 889 "gram.y"
|
#line 896 "gram.y"
|
||||||
{
|
{
|
||||||
yyval.member = new_member(yyvsp[0].string, WORD);
|
yyval.member = new_member(yyvsp[0].string, WORD);
|
||||||
if (yyval.member == NULL) {
|
if (yyval.member == NULL) {
|
||||||
@@ -2188,7 +2224,7 @@ case 116:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#line 2139 "gram.c"
|
#line 2175 "gram.c"
|
||||||
}
|
}
|
||||||
yyssp -= yym;
|
yyssp -= yym;
|
||||||
yystate = *yyssp;
|
yystate = *yyssp;
|
||||||
|
@@ -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>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -60,8 +60,11 @@ bool parse_error = false;
|
|||||||
int errorlineno = -1;
|
int errorlineno = -1;
|
||||||
char *errorfile = NULL;
|
char *errorfile = NULL;
|
||||||
|
|
||||||
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
|
struct sudoers_parse_tree parsed_policy = {
|
||||||
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
|
TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
|
||||||
|
TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
|
||||||
|
NULL /* aliases */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local protoypes
|
* Local protoypes
|
||||||
@@ -737,7 +740,8 @@ hostaliases : hostalias
|
|||||||
|
|
||||||
hostalias : ALIAS '=' hostlist {
|
hostalias : ALIAS '=' hostlist {
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -758,7 +762,8 @@ cmndaliases : cmndalias
|
|||||||
|
|
||||||
cmndalias : ALIAS '=' cmndlist {
|
cmndalias : ALIAS '=' cmndlist {
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -779,7 +784,8 @@ runasaliases : runasalias
|
|||||||
|
|
||||||
runasalias : ALIAS '=' userlist {
|
runasalias : ALIAS '=' userlist {
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -793,7 +799,8 @@ useraliases : useralias
|
|||||||
|
|
||||||
useralias : ALIAS '=' userlist {
|
useralias : ALIAS '=' userlist {
|
||||||
const char *s;
|
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) {
|
if (s != NULL) {
|
||||||
sudoerserror(s);
|
sudoerserror(s);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
@@ -1027,7 +1034,7 @@ add_defaults(int type, struct member *bmem, struct defaults *defs)
|
|||||||
HLTQ_FOREACH_SAFE(d, defs, entries, next) {
|
HLTQ_FOREACH_SAFE(d, defs, entries, next) {
|
||||||
d->type = type;
|
d->type = type;
|
||||||
d->binding = binding;
|
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->users, members, entries);
|
||||||
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
|
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
|
||||||
STAILQ_INIT(&u->comments);
|
STAILQ_INIT(&u->comments);
|
||||||
TAILQ_INSERT_TAIL(&userspecs, u, entries);
|
TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
@@ -1235,6 +1242,41 @@ free_userspec(struct userspec *us)
|
|||||||
debug_return;
|
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
|
* Free up space used by data structures from a previous parser run and sets
|
||||||
* the current sudoers file to path.
|
* the current sudoers file to path.
|
||||||
@@ -1245,15 +1287,9 @@ init_parser(const char *path, bool quiet)
|
|||||||
bool ret = true;
|
bool ret = true;
|
||||||
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
|
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
free_userspecs(&userspecs);
|
free_parse_tree(&parsed_policy);
|
||||||
free_defaults(&defaults);
|
|
||||||
init_lexer();
|
init_lexer();
|
||||||
|
|
||||||
if (!init_aliases()) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcstr_delref(sudoers);
|
rcstr_delref(sudoers);
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
if ((sudoers = rcstr_dup(path)) == NULL) {
|
if ((sudoers = rcstr_dup(path)) == NULL) {
|
||||||
|
@@ -152,9 +152,7 @@ STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
|
|||||||
struct sudo_ldap_handle {
|
struct sudo_ldap_handle {
|
||||||
LDAP *ld;
|
LDAP *ld;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct userspec_list userspecs;
|
struct sudoers_parse_tree parse_tree;
|
||||||
struct defaults_list defaults;
|
|
||||||
bool cached_defaults;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LDAP_INITIALIZE
|
#ifdef HAVE_LDAP_INITIALIZE
|
||||||
@@ -1553,8 +1551,7 @@ sudo_ldap_close(struct sudo_nss *nss)
|
|||||||
/* Free the handle container. */
|
/* Free the handle container. */
|
||||||
if (handle->pw != NULL)
|
if (handle->pw != NULL)
|
||||||
sudo_pw_delref(handle->pw);
|
sudo_pw_delref(handle->pw);
|
||||||
free_userspecs(&handle->userspecs);
|
free_parse_tree(&handle->parse_tree);
|
||||||
free_defaults(&handle->defaults);
|
|
||||||
free(handle);
|
free(handle);
|
||||||
nss->handle = NULL;
|
nss->handle = NULL;
|
||||||
}
|
}
|
||||||
@@ -1660,40 +1657,39 @@ sudo_ldap_open(struct sudo_nss *nss)
|
|||||||
}
|
}
|
||||||
handle->ld = ld;
|
handle->ld = ld;
|
||||||
/* handle->pw = NULL; */
|
/* handle->pw = NULL; */
|
||||||
TAILQ_INIT(&handle->userspecs);
|
init_parse_tree(&handle->parse_tree);
|
||||||
TAILQ_INIT(&handle->defaults);
|
|
||||||
nss->handle = handle;
|
nss->handle = handle;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
|
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct defaults_list *
|
static int
|
||||||
sudo_ldap_getdefs(struct sudo_nss *nss)
|
sudo_ldap_getdefs(struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
struct sudo_ldap_handle *handle = nss->handle;
|
struct sudo_ldap_handle *handle = nss->handle;
|
||||||
struct defaults_list *ret = &handle->defaults;
|
|
||||||
struct timeval tv, *tvp = NULL;
|
struct timeval tv, *tvp = NULL;
|
||||||
struct ldap_config_str *base;
|
struct ldap_config_str *base;
|
||||||
LDAPMessage *entry, *result = NULL;
|
LDAPMessage *entry, *result = NULL;
|
||||||
char *filt = NULL;
|
char *filt = NULL;
|
||||||
int rc;
|
int rc, ret = -1;
|
||||||
|
static bool cached;
|
||||||
debug_decl(sudo_ldap_getdefs, SUDOERS_DEBUG_LDAP)
|
debug_decl(sudo_ldap_getdefs, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"%s: called with NULL handle", __func__);
|
"%s: called with NULL handle", __func__);
|
||||||
debug_return_ptr(NULL);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use cached result if present. */
|
/* Use cached result if present. */
|
||||||
if (handle->cached_defaults)
|
if (cached)
|
||||||
goto done;
|
debug_return_int(0);
|
||||||
|
|
||||||
filt = sudo_ldap_build_default_filter();
|
filt = sudo_ldap_build_default_filter();
|
||||||
if (filt == NULL) {
|
if (filt == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
debug_return_ptr(NULL);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
DPRINTF1("Looking for cn=defaults: %s", filt);
|
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);
|
filt, NULL, 0, NULL, NULL, tvp, 0, &result);
|
||||||
if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
|
if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
|
||||||
DPRINTF1("found:%s", ldap_get_dn(ld, entry));
|
DPRINTF1("found:%s", ldap_get_dn(ld, entry));
|
||||||
if (!sudo_ldap_parse_options(ld, entry, &handle->defaults)) {
|
if (!sudo_ldap_parse_options(ld, entry, &handle->parse_tree.defaults))
|
||||||
ret = NULL;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
DPRINTF1("no default options found in %s", base->val);
|
DPRINTF1("no default options found in %s", base->val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handle->cached_defaults = true;
|
cached = true;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ldap_msgfree(result);
|
ldap_msgfree(result);
|
||||||
free(filt);
|
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
|
* Perform LDAP query for user and host and convert to sudoers
|
||||||
* parse tree.
|
* parse tree.
|
||||||
*/
|
*/
|
||||||
static struct userspec_list *
|
static int
|
||||||
sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
|
sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
|
||||||
{
|
{
|
||||||
struct sudo_ldap_handle *handle = nss->handle;
|
struct sudo_ldap_handle *handle = nss->handle;
|
||||||
struct ldap_result *lres = NULL;
|
struct ldap_result *lres = NULL;
|
||||||
struct userspec_list *ret = &handle->userspecs;
|
int ret = -1;
|
||||||
debug_decl(sudo_ldap_query, SUDOERS_DEBUG_LDAP)
|
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) {
|
if (handle == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"%s: called with NULL handle", __func__);
|
"%s: called with NULL handle", __func__);
|
||||||
debug_return_ptr(NULL);
|
debug_return_ptr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use cached result if it matches pw. */
|
debug_return_ptr(&handle->parse_tree);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@@ -93,7 +93,8 @@ static bool digest_matches(int fd, const char *file, const struct command_digest
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
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;
|
struct alias *a;
|
||||||
int matched = UNSPEC;
|
int matched = UNSPEC;
|
||||||
@@ -114,9 +115,9 @@ user_matches(const struct passwd *pw, const struct member *m)
|
|||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = alias_get(m->name, USERALIAS)) != NULL) {
|
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
|
||||||
/* XXX */
|
/* XXX */
|
||||||
int rc = userlist_matches(pw, &a->members);
|
int rc = userlist_matches(parse_tree, pw, &a->members);
|
||||||
if (rc != UNSPEC)
|
if (rc != UNSPEC)
|
||||||
matched = m->negated ? !rc : rc;
|
matched = m->negated ? !rc : rc;
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
@@ -136,14 +137,15 @@ user_matches(const struct passwd *pw, const struct member *m)
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
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;
|
struct member *m;
|
||||||
int matched = UNSPEC;
|
int matched = UNSPEC;
|
||||||
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH)
|
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH)
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
debug_return_int(matched);
|
debug_return_int(matched);
|
||||||
@@ -155,9 +157,9 @@ userlist_matches(const struct passwd *pw, const struct member_list *list)
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
runaslist_matches(const struct member_list *user_list,
|
runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||||
const struct member_list *group_list, struct member **matching_user,
|
const struct member_list *user_list, const struct member_list *group_list,
|
||||||
struct member **matching_group)
|
struct member **matching_user, struct member **matching_group)
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
@@ -191,9 +193,10 @@ runaslist_matches(const struct member_list *user_list,
|
|||||||
user_matched = !m->negated;
|
user_matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
|
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||||
rc = runaslist_matches(&a->members, &empty,
|
if (a != NULL) {
|
||||||
matching_user, NULL);
|
rc = runaslist_matches(parse_tree, &a->members,
|
||||||
|
&empty, matching_user, NULL);
|
||||||
if (rc != UNSPEC)
|
if (rc != UNSPEC)
|
||||||
user_matched = m->negated ? !rc : rc;
|
user_matched = m->negated ? !rc : rc;
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
@@ -234,9 +237,10 @@ runaslist_matches(const struct member_list *user_list,
|
|||||||
group_matched = !m->negated;
|
group_matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
|
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||||
rc = runaslist_matches(&empty, &a->members,
|
if (a != NULL) {
|
||||||
NULL, matching_group);
|
rc = runaslist_matches(parse_tree, &empty,
|
||||||
|
&a->members, NULL, matching_group);
|
||||||
if (rc != UNSPEC)
|
if (rc != UNSPEC)
|
||||||
group_matched = m->negated ? !rc : rc;
|
group_matched = m->negated ? !rc : rc;
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
@@ -273,15 +277,16 @@ runaslist_matches(const struct member_list *user_list,
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
hostlist_matches_int(const struct passwd *pw, const char *lhost,
|
hostlist_matches_int(struct sudoers_parse_tree *parse_tree,
|
||||||
const char *shost, const struct member_list *list)
|
const struct passwd *pw, const char *lhost, const char *shost,
|
||||||
|
const struct member_list *list)
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
int matched = UNSPEC;
|
int matched = UNSPEC;
|
||||||
debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
|
debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
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)
|
if (matched != UNSPEC)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -293,9 +298,10 @@ hostlist_matches_int(const struct passwd *pw, const char *lhost,
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
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.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
host_matches(const struct passwd *pw, const char *lhost, const char *shost,
|
host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||||
const struct member *m)
|
const char *lhost, const char *shost, const struct member *m)
|
||||||
{
|
{
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
int matched = UNSPEC;
|
int matched = UNSPEC;
|
||||||
@@ -324,9 +330,11 @@ host_matches(const struct passwd *pw, const char *lhost, const char *shost,
|
|||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = alias_get(m->name, HOSTALIAS)) != NULL) {
|
a = alias_get(parse_tree, m->name, HOSTALIAS);
|
||||||
|
if (a != NULL) {
|
||||||
/* XXX */
|
/* 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)
|
if (rc != UNSPEC)
|
||||||
matched = m->negated ? !rc : rc;
|
matched = m->negated ? !rc : rc;
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
@@ -346,14 +354,15 @@ host_matches(const struct passwd *pw, const char *lhost, const char *shost,
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cmndlist_matches(const struct member_list *list)
|
cmndlist_matches(struct sudoers_parse_tree *parse_tree,
|
||||||
|
const struct member_list *list)
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
int matched = UNSPEC;
|
int matched = UNSPEC;
|
||||||
debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH)
|
debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH)
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||||
matched = cmnd_matches(m);
|
matched = cmnd_matches(parse_tree, m);
|
||||||
if (matched != UNSPEC)
|
if (matched != UNSPEC)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -365,7 +374,7 @@ cmndlist_matches(const struct member_list *list)
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cmnd_matches(const struct member *m)
|
cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
|
||||||
{
|
{
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
struct sudo_command *c;
|
struct sudo_command *c;
|
||||||
@@ -377,8 +386,9 @@ cmnd_matches(const struct member *m)
|
|||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = alias_get(m->name, CMNDALIAS)) != NULL) {
|
a = alias_get(parse_tree, m->name, CMNDALIAS);
|
||||||
rc = cmndlist_matches(&a->members);
|
if (a != NULL) {
|
||||||
|
rc = cmndlist_matches(parse_tree, &a->members);
|
||||||
if (rc != UNSPEC)
|
if (rc != UNSPEC)
|
||||||
matched = m->negated ? !rc : rc;
|
matched = m->negated ? !rc : rc;
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
|
@@ -65,19 +65,18 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
|
|||||||
CLR(validated, FLAG_NO_HOST);
|
CLR(validated, FLAG_NO_HOST);
|
||||||
match = DENY;
|
match = DENY;
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct userspec_list *usl = nss->query(nss, pw);
|
if (nss->query(nss, pw) == -1) {
|
||||||
if (usl == NULL) {
|
|
||||||
/* The query function should have printed an error message. */
|
/* The query function should have printed an error message. */
|
||||||
SET(validated, VALIDATE_ERROR);
|
SET(validated, VALIDATE_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(us, usl, entries) {
|
TAILQ_FOREACH(us, &nss->parse_tree->userspecs, entries) {
|
||||||
if (userlist_matches(pw, &us->users) != ALLOW)
|
if (userlist_matches(nss->parse_tree, pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
||||||
int priv_nopass = UNSPEC;
|
int priv_nopass = UNSPEC;
|
||||||
|
|
||||||
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
|
if (hostlist_matches(nss->parse_tree, pw, &priv->hostlist) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH(def, &priv->defaults, entries) {
|
TAILQ_FOREACH(def, &priv->defaults, entries) {
|
||||||
if (strcmp(def->var, "authenticate") == 0)
|
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. */
|
/* Only check the command when listing another user. */
|
||||||
if (user_uid == 0 || list_pw == NULL ||
|
if (user_uid == 0 || list_pw == NULL ||
|
||||||
user_uid == list_pw->pw_uid ||
|
user_uid == list_pw->pw_uid ||
|
||||||
cmnd_matches(cs->cmnd) == ALLOW)
|
cmnd_matches(nss->parse_tree, cs->cmnd) == ALLOW)
|
||||||
match = ALLOW;
|
match = ALLOW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +114,7 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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,
|
int *validated, struct cmndspec **matching_cs,
|
||||||
struct defaults_list **defs, time_t now)
|
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;
|
struct member *matching_user;
|
||||||
debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER)
|
debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
|
TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) {
|
||||||
if (userlist_matches(pw, &us->users) != ALLOW)
|
if (userlist_matches(nss->parse_tree, pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
CLR(*validated, FLAG_NO_USER);
|
CLR(*validated, FLAG_NO_USER);
|
||||||
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
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)
|
if (host_match == ALLOW)
|
||||||
CLR(*validated, FLAG_NO_HOST);
|
CLR(*validated, FLAG_NO_HOST);
|
||||||
else
|
else
|
||||||
@@ -146,10 +145,11 @@ sudoers_lookup_check(struct userspec_list *usl, struct passwd *pw,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
matching_user = NULL;
|
matching_user = NULL;
|
||||||
runas_match = runaslist_matches(cs->runasuserlist,
|
runas_match = runaslist_matches(nss->parse_tree,
|
||||||
cs->runasgrouplist, &matching_user, NULL);
|
cs->runasuserlist, cs->runasgrouplist, &matching_user,
|
||||||
|
NULL);
|
||||||
if (runas_match == ALLOW) {
|
if (runas_match == ALLOW) {
|
||||||
cmnd_match = cmnd_matches(cs->cmnd);
|
cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd);
|
||||||
if (cmnd_match != UNSPEC) {
|
if (cmnd_match != UNSPEC) {
|
||||||
/*
|
/*
|
||||||
* If user is running command as himself,
|
* 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)
|
int pwflag)
|
||||||
{
|
{
|
||||||
struct defaults_list *defs = NULL;
|
struct defaults_list *defs = NULL;
|
||||||
|
struct sudoers_parse_tree *parse_tree = NULL;
|
||||||
struct cmndspec *cs = NULL;
|
struct cmndspec *cs = NULL;
|
||||||
struct sudo_nss *nss;
|
struct sudo_nss *nss;
|
||||||
int m, match = UNSPEC;
|
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. */
|
/* Query each sudoers source and check the user. */
|
||||||
time(&now);
|
time(&now);
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct userspec_list *usl = nss->query(nss, pw);
|
if (nss->query(nss, pw) == -1) {
|
||||||
if (usl == NULL) {
|
|
||||||
/* The query function should have printed an error message. */
|
/* The query function should have printed an error message. */
|
||||||
SET(validated, VALIDATE_ERROR);
|
SET(validated, VALIDATE_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = sudoers_lookup_check(usl, pw, &validated, &cs, &defs, now);
|
m = sudoers_lookup_check(nss, pw, &validated, &cs, &defs, now);
|
||||||
if (m != UNSPEC)
|
if (m != UNSPEC) {
|
||||||
match = m;
|
match = m;
|
||||||
|
parse_tree = nss->parse_tree;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sudo_nss_can_continue(nss, m))
|
if (!sudo_nss_can_continue(nss, m))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (defs != NULL)
|
|
||||||
update_defaults(defs, SETDEF_GENERIC, false);
|
|
||||||
if (match != UNSPEC) {
|
if (match != UNSPEC) {
|
||||||
|
if (defs != NULL)
|
||||||
|
update_defaults(parse_tree, SETDEF_GENERIC, false);
|
||||||
if (!apply_cmndspec(cs))
|
if (!apply_cmndspec(cs))
|
||||||
SET(validated, VALIDATE_ERROR);
|
SET(validated, VALIDATE_ERROR);
|
||||||
else if (match == ALLOW)
|
else if (match == ALLOW)
|
||||||
@@ -322,8 +324,8 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_priv_short(struct passwd *pw, struct userspec *us,
|
display_priv_short(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
|
||||||
struct sudo_lbuf *lbuf)
|
struct userspec *us, struct sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
struct cmndspec *cs, *prev_cs;
|
struct cmndspec *cs, *prev_cs;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
@@ -332,7 +334,7 @@ display_priv_short(struct passwd *pw, struct userspec *us,
|
|||||||
debug_decl(display_priv_short, SUDOERS_DEBUG_PARSER)
|
debug_decl(display_priv_short, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
||||||
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
|
if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
prev_cs = NULL;
|
prev_cs = NULL;
|
||||||
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
|
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) {
|
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasuserlist))
|
if (m != TAILQ_FIRST(cs->runasuserlist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
|
RUNASALIAS);
|
||||||
}
|
}
|
||||||
} else if (cs->runasgrouplist == NULL) {
|
} else if (cs->runasgrouplist == NULL) {
|
||||||
sudo_lbuf_append(lbuf, "%s", def_runas_default);
|
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) {
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
|
RUNASALIAS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sudo_lbuf_append(lbuf, ") ");
|
sudo_lbuf_append(lbuf, ") ");
|
||||||
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
|
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
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;
|
prev_cs = cs;
|
||||||
nfound++;
|
nfound++;
|
||||||
}
|
}
|
||||||
@@ -409,8 +413,8 @@ new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_priv_long(struct passwd *pw, struct userspec *us,
|
display_priv_long(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
|
||||||
struct sudo_lbuf *lbuf)
|
struct userspec *us, struct sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
struct cmndspec *cs, *prev_cs;
|
struct cmndspec *cs, *prev_cs;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
@@ -418,7 +422,7 @@ display_priv_long(struct passwd *pw, struct userspec *us,
|
|||||||
debug_decl(display_priv_long, SUDOERS_DEBUG_PARSER)
|
debug_decl(display_priv_long, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
||||||
if (hostlist_matches(pw, &priv->hostlist) != ALLOW)
|
if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
prev_cs = NULL;
|
prev_cs = NULL;
|
||||||
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
|
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) {
|
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasuserlist))
|
if (m != TAILQ_FIRST(cs->runasuserlist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
|
RUNASALIAS);
|
||||||
}
|
}
|
||||||
} else if (cs->runasgrouplist == NULL) {
|
} else if (cs->runasgrouplist == NULL) {
|
||||||
sudo_lbuf_append(lbuf, "%s", def_runas_default);
|
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) {
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
|
||||||
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
if (m != TAILQ_FIRST(cs->runasgrouplist))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
sudo_lbuf_append(lbuf, ", ");
|
||||||
sudoers_format_member(lbuf, m, ", ", RUNASALIAS);
|
sudoers_format_member(lbuf, parse_tree, m, ", ",
|
||||||
|
RUNASALIAS);
|
||||||
}
|
}
|
||||||
sudo_lbuf_append(lbuf, "\n");
|
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, _(" Commands:\n"));
|
||||||
}
|
}
|
||||||
sudo_lbuf_append(lbuf, "\t");
|
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");
|
sudo_lbuf_append(lbuf, "\n");
|
||||||
prev_cs = cs;
|
prev_cs = cs;
|
||||||
nfound++;
|
nfound++;
|
||||||
@@ -522,21 +529,21 @@ display_priv_long(struct passwd *pw, struct userspec *us,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
int nfound = 0;
|
int nfound = 0;
|
||||||
debug_decl(sudo_display_userspecs, SUDOERS_DEBUG_PARSER)
|
debug_decl(sudo_display_userspecs, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
TAILQ_FOREACH(us, usl, entries) {
|
TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
|
||||||
if (userlist_matches(pw, &us->users) != ALLOW)
|
if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (long_list)
|
if (long_list)
|
||||||
nfound += display_priv_long(pw, us, lbuf);
|
nfound += display_priv_long(parse_tree, pw, us, lbuf);
|
||||||
else
|
else
|
||||||
nfound += display_priv_short(pw, us, lbuf);
|
nfound += display_priv_short(parse_tree, pw, us, lbuf);
|
||||||
}
|
}
|
||||||
if (sudo_lbuf_error(lbuf))
|
if (sudo_lbuf_error(lbuf))
|
||||||
debug_return_int(-1);
|
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.
|
* Display matching Defaults entries for the given user on this host.
|
||||||
*/
|
*/
|
||||||
static int
|
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 sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
@@ -560,14 +567,14 @@ display_defaults(struct defaults_list *defs, struct passwd *pw,
|
|||||||
else
|
else
|
||||||
prefix = ", ";
|
prefix = ", ";
|
||||||
|
|
||||||
TAILQ_FOREACH(d, defs, entries) {
|
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case DEFAULTS_HOST:
|
case DEFAULTS_HOST:
|
||||||
if (hostlist_matches(pw, d->binding) != ALLOW)
|
if (hostlist_matches(parse_tree, pw, d->binding) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_USER:
|
case DEFAULTS_USER:
|
||||||
if (userlist_matches(pw, d->binding) != ALLOW)
|
if (userlist_matches(parse_tree, pw, d->binding) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_RUNAS:
|
case DEFAULTS_RUNAS:
|
||||||
@@ -588,8 +595,8 @@ display_defaults(struct defaults_list *defs, struct passwd *pw,
|
|||||||
* Display Defaults entries of the given type.
|
* Display Defaults entries of the given type.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
|
display_bound_defaults_by_type(struct sudoers_parse_tree *parse_tree,
|
||||||
struct sudo_lbuf *lbuf)
|
int deftype, struct sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
struct member_list *binding = NULL;
|
struct member_list *binding = NULL;
|
||||||
@@ -618,7 +625,7 @@ display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
|
|||||||
default:
|
default:
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(d, defs, entries) {
|
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
|
||||||
if (d->type != deftype)
|
if (d->type != deftype)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -631,7 +638,7 @@ display_bound_defaults_by_type(struct defaults_list *defs, int deftype,
|
|||||||
TAILQ_FOREACH(m, binding, entries) {
|
TAILQ_FOREACH(m, binding, entries) {
|
||||||
if (m != TAILQ_FIRST(binding))
|
if (m != TAILQ_FIRST(binding))
|
||||||
sudo_lbuf_append(lbuf, ",");
|
sudo_lbuf_append(lbuf, ",");
|
||||||
sudoers_format_member(lbuf, m, ", ", atype);
|
sudoers_format_member(lbuf, parse_tree, m, ", ", atype);
|
||||||
sudo_lbuf_append(lbuf, " ");
|
sudo_lbuf_append(lbuf, " ");
|
||||||
}
|
}
|
||||||
} else
|
} 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
|
* Display Defaults entries that are per-runas or per-command
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
display_bound_defaults(struct defaults_list *defs, struct passwd *pw,
|
display_bound_defaults(struct sudoers_parse_tree *parse_tree,
|
||||||
struct sudo_lbuf *lbuf)
|
struct passwd *pw, struct sudo_lbuf *lbuf)
|
||||||
{
|
{
|
||||||
int nfound = 0;
|
int nfound = 0;
|
||||||
debug_decl(display_bound_defaults, SUDOERS_DEBUG_PARSER)
|
debug_decl(display_bound_defaults, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
/* XXX - should only print ones that match what the user can do. */
|
/* 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(parse_tree, DEFAULTS_RUNAS, lbuf);
|
||||||
nfound += display_bound_defaults_by_type(defs, DEFAULTS_CMND, lbuf);
|
nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_CMND, lbuf);
|
||||||
|
|
||||||
if (sudo_lbuf_error(lbuf))
|
if (sudo_lbuf_error(lbuf))
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
@@ -703,13 +710,10 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
|
|||||||
pw->pw_name, user_srunhost);
|
pw->pw_name, user_srunhost);
|
||||||
count = 0;
|
count = 0;
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct defaults_list *defs = nss->getdefs(nss);
|
n = display_defaults(nss->parse_tree, pw, &def_buf);
|
||||||
if (defs != NULL) {
|
if (n == -1)
|
||||||
n = display_defaults(defs, pw, &def_buf);
|
goto bad;
|
||||||
if (n == -1)
|
count += n;
|
||||||
goto bad;
|
|
||||||
count += n;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
sudo_lbuf_append(&def_buf, "\n\n");
|
sudo_lbuf_append(&def_buf, "\n\n");
|
||||||
@@ -724,13 +728,10 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
|
|||||||
pw->pw_name);
|
pw->pw_name);
|
||||||
count = 0;
|
count = 0;
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct defaults_list *defs = nss->getdefs(nss);
|
n = display_bound_defaults(nss->parse_tree, pw, &def_buf);
|
||||||
if (defs != NULL) {
|
if (n == -1)
|
||||||
n = display_bound_defaults(defs, pw, &def_buf);
|
goto bad;
|
||||||
if (n == -1)
|
count += n;
|
||||||
goto bad;
|
|
||||||
count += n;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
sudo_lbuf_append(&def_buf, "\n\n");
|
sudo_lbuf_append(&def_buf, "\n\n");
|
||||||
@@ -745,9 +746,8 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
|
|||||||
pw->pw_name, user_srunhost);
|
pw->pw_name, user_srunhost);
|
||||||
count = 0;
|
count = 0;
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct userspec_list *usl = nss->query(nss, pw);
|
if (nss->query(nss, pw) != -1) {
|
||||||
if (usl != NULL) {
|
n = sudo_display_userspecs(nss->parse_tree, pw, &priv_buf);
|
||||||
n = sudo_display_userspecs(usl, pw, &priv_buf);
|
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
goto bad;
|
goto bad;
|
||||||
count += n;
|
count += n;
|
||||||
@@ -778,7 +778,8 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
int host_match, runas_match, cmnd_match;
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
@@ -786,11 +787,11 @@ display_cmnd_check(struct userspec_list *usl, struct passwd *pw, time_t now)
|
|||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
debug_decl(display_cmnd_check, SUDOERS_DEBUG_PARSER)
|
debug_decl(display_cmnd_check, SUDOERS_DEBUG_PARSER)
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
|
TAILQ_FOREACH_REVERSE(us, &parse_tree->userspecs, userspec_list, entries) {
|
||||||
if (userlist_matches(pw, &us->users) != ALLOW)
|
if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
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)
|
if (host_match != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
|
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)
|
if (now > cs->notafter)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
runas_match = runaslist_matches(cs->runasuserlist,
|
runas_match = runaslist_matches(parse_tree, cs->runasuserlist,
|
||||||
cs->runasgrouplist, NULL, NULL);
|
cs->runasgrouplist, NULL, NULL);
|
||||||
if (runas_match == ALLOW) {
|
if (runas_match == ALLOW) {
|
||||||
cmnd_match = cmnd_matches(cs->cmnd);
|
cmnd_match = cmnd_matches(parse_tree, cs->cmnd);
|
||||||
if (cmnd_match != UNSPEC)
|
if (cmnd_match != UNSPEC)
|
||||||
debug_return_int(cmnd_match);
|
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. */
|
/* Iterate over each source, checking for the command. */
|
||||||
time(&now);
|
time(&now);
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct userspec_list *usl = nss->query(nss, pw);
|
if (nss->query(nss, pw) == -1) {
|
||||||
if (usl == NULL) {
|
|
||||||
/* The query function should have printed an error message. */
|
/* The query function should have printed an error message. */
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m = display_cmnd_check(usl, pw, now);
|
m = display_cmnd_check(nss->parse_tree, pw, now);
|
||||||
if (m != UNSPEC)
|
if (m != UNSPEC)
|
||||||
match = m;
|
match = m;
|
||||||
|
|
||||||
|
@@ -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>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* 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;
|
struct sudoers_parse_tree {
|
||||||
extern struct defaults_list defaults;
|
struct userspec_list userspecs;
|
||||||
|
struct defaults_list defaults;
|
||||||
|
struct rbtree *aliases;
|
||||||
|
};
|
||||||
|
|
||||||
/* alias.c */
|
/* alias.c */
|
||||||
bool no_aliases(void);
|
struct rbtree *alloc_aliases(void);
|
||||||
struct rbtree *replace_aliases(struct rbtree *new_aliases);
|
void free_aliases(struct rbtree *aliases);
|
||||||
const char *alias_add(char *name, int type, char *file, int lineno, struct member *members);
|
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);
|
const char *alias_type_to_string(int alias_type);
|
||||||
int alias_compare(const void *a1, const void *a2);
|
struct alias *alias_get(struct sudoers_parse_tree *parse_tree, const char *name, int type);
|
||||||
struct alias *alias_get(const char *name, int type);
|
struct alias *alias_remove(struct sudoers_parse_tree *parse_tree, char *name, int type);
|
||||||
struct alias *alias_remove(char *name, int type);
|
bool alias_find_used(struct sudoers_parse_tree *parse_tree, struct rbtree *used_aliases);
|
||||||
bool alias_find_used(struct rbtree *used_aliases);
|
void alias_apply(struct sudoers_parse_tree *parse_tree, int (*func)(void *, void *), void *cookie);
|
||||||
void alias_apply(int (*func)(void *, void *), void *cookie);
|
|
||||||
void alias_free(void *a);
|
void alias_free(void *a);
|
||||||
void alias_put(struct alias *a);
|
void alias_put(struct alias *a);
|
||||||
bool init_aliases(void);
|
|
||||||
|
|
||||||
/* gram.c */
|
/* gram.c */
|
||||||
|
extern struct sudoers_parse_tree parsed_policy;
|
||||||
bool init_parser(const char *path, bool quiet);
|
bool init_parser(const char *path, bool quiet);
|
||||||
void free_member(struct member *m);
|
void free_member(struct member *m);
|
||||||
void free_members(struct member_list *members);
|
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_userspecs(struct userspec_list *usl);
|
||||||
void free_default(struct defaults *def, struct member_list **binding);
|
void free_default(struct defaults *def, struct member_list **binding);
|
||||||
void free_defaults(struct defaults_list *defs);
|
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 */
|
/* match_addr.c */
|
||||||
bool addr_matches(char *n);
|
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 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 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);
|
bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
|
||||||
int cmnd_matches(const struct member *m);
|
int cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m);
|
||||||
int cmndlist_matches(const struct member_list *list);
|
int cmndlist_matches(struct sudoers_parse_tree *parse_tree, const struct member_list *list);
|
||||||
int host_matches(const struct passwd *pw, const char *host, const char *shost, const struct member *m);
|
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(const struct passwd *pw, const struct member_list *list);
|
int hostlist_matches(struct sudoers_parse_tree *parse_tree, 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 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(const struct passwd *pw, const struct member *m);
|
int user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member *m);
|
||||||
int userlist_matches(const struct passwd *pw, const struct member_list *list);
|
int userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
|
||||||
const char *sudo_getdomainname(void);
|
const char *sudo_getdomainname(void);
|
||||||
|
|
||||||
/* toke.c */
|
/* toke.c */
|
||||||
@@ -322,12 +328,12 @@ int display_cmnd(struct sudo_nss_list *snl, struct passwd *pw);
|
|||||||
|
|
||||||
/* fmtsudoers.c */
|
/* fmtsudoers.c */
|
||||||
struct sudo_lbuf;
|
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(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_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 member *m, const char *separator, int alias_type);
|
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 privilege *priv, bool expand_aliases);
|
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 userspec *us, 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 userspec_list *usl, const char *separator, bool expand_aliases, bool flush);
|
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 */
|
#endif /* SUDOERS_PARSE_H */
|
||||||
|
@@ -83,9 +83,7 @@ struct sudo_sss_handle {
|
|||||||
char *ipa_shost;
|
char *ipa_shost;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
void *ssslib;
|
void *ssslib;
|
||||||
struct userspec_list userspecs;
|
struct sudoers_parse_tree parse_tree;
|
||||||
struct defaults_list defaults;
|
|
||||||
bool cached_defaults;
|
|
||||||
sss_sudo_send_recv_t fn_send_recv;
|
sss_sudo_send_recv_t fn_send_recv;
|
||||||
sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
|
sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
|
||||||
sss_sudo_free_result_t fn_free_result;
|
sss_sudo_free_result_t fn_free_result;
|
||||||
@@ -237,7 +235,7 @@ val_array_iter(void **vp)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
sss_to_sudoers(struct sudo_sss_handle *handle,
|
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 userspec *us;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
@@ -250,7 +248,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle,
|
|||||||
TAILQ_INIT(&us->users);
|
TAILQ_INIT(&us->users);
|
||||||
TAILQ_INIT(&us->privileges);
|
TAILQ_INIT(&us->privileges);
|
||||||
STAILQ_INIT(&us->comments);
|
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. */
|
/* We only include rules where the user matches. */
|
||||||
if ((m = calloc(1, sizeof(*m))) == NULL)
|
if ((m = calloc(1, sizeof(*m))) == NULL)
|
||||||
@@ -387,7 +385,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle,
|
|||||||
|
|
||||||
oom:
|
oom:
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
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);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,8 +515,7 @@ sudo_sss_close(struct sudo_nss *nss)
|
|||||||
free(handle->ipa_host);
|
free(handle->ipa_host);
|
||||||
if (handle->ipa_host != handle->ipa_shost)
|
if (handle->ipa_host != handle->ipa_shost)
|
||||||
free(handle->ipa_shost);
|
free(handle->ipa_shost);
|
||||||
free_userspecs(&handle->userspecs);
|
free_parse_tree(&handle->parse_tree);
|
||||||
free_defaults(&handle->defaults);
|
|
||||||
free(handle);
|
free(handle);
|
||||||
nss->handle = NULL;
|
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"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
debug_return_int(ENOMEM);
|
debug_return_int(ENOMEM);
|
||||||
}
|
}
|
||||||
|
init_parse_tree(&handle->parse_tree);
|
||||||
TAILQ_INIT(&handle->userspecs);
|
|
||||||
TAILQ_INIT(&handle->defaults);
|
|
||||||
|
|
||||||
/* Load symbols */
|
/* Load symbols */
|
||||||
handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
|
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.
|
* 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)
|
sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
|
||||||
{
|
{
|
||||||
struct sudo_sss_handle *handle = nss->handle;
|
struct sudo_sss_handle *handle = nss->handle;
|
||||||
struct sss_sudo_result *sss_result = NULL;
|
struct sss_sudo_result *sss_result = NULL;
|
||||||
struct userspec_list *ret = &handle->userspecs;
|
int ret = 0;
|
||||||
debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
|
debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
|
||||||
|
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"%s: called with NULL handle", __func__);
|
"%s: called with NULL handle", __func__);
|
||||||
debug_return_ptr(NULL);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use cached result if it matches pw. */
|
/* 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 old userspecs, if any. */
|
||||||
free_userspecs(&handle->userspecs);
|
free_userspecs(&handle->parse_tree.userspecs);
|
||||||
|
|
||||||
/* Fetch list of sudoRole entries that match user and host. */
|
/* Fetch list of sudoRole entries that match user and host. */
|
||||||
sss_result = sudo_sss_result_get(nss, pw);
|
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",
|
"searching SSSD/LDAP for sudoers entries for user %s, host %s",
|
||||||
pw->pw_name, user_runhost);
|
pw->pw_name, user_runhost);
|
||||||
|
|
||||||
if (sss_result == NULL)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Stash a ref to the passwd struct in the handle. */
|
/* Stash a ref to the passwd struct in the handle. */
|
||||||
sudo_pw_addref(pw);
|
sudo_pw_addref(pw);
|
||||||
handle->pw = pw;
|
handle->pw = pw;
|
||||||
|
|
||||||
/* Convert to sudoers parse tree. */
|
/* Convert to sudoers parse tree if the user was found. */
|
||||||
if (!sss_to_sudoers(handle, sss_result, &handle->userspecs)) {
|
if (sss_result != NULL) {
|
||||||
ret = NULL;
|
if (!sss_to_sudoers(handle, sss_result)) {
|
||||||
goto done;
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
handle->fn_free_result(sss_result);
|
handle->fn_free_result(sss_result);
|
||||||
if (ret == NULL) {
|
if (ret == -1) {
|
||||||
free_userspecs(&handle->userspecs);
|
free_userspecs(&handle->parse_tree.userspecs);
|
||||||
sudo_pw_delref(handle->pw);
|
if (handle->pw != NULL) {
|
||||||
handle->pw = NULL;
|
sudo_pw_delref(handle->pw);
|
||||||
|
handle->pw = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
|
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
|
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)
|
sudo_sss_getdefs(struct sudo_nss *nss)
|
||||||
{
|
{
|
||||||
struct sudo_sss_handle *handle = nss->handle;
|
struct sudo_sss_handle *handle = nss->handle;
|
||||||
struct sss_sudo_result *sss_result = NULL;
|
struct sss_sudo_result *sss_result = NULL;
|
||||||
|
static bool cached;
|
||||||
uint32_t sss_error;
|
uint32_t sss_error;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -704,12 +713,12 @@ sudo_sss_getdefs(struct sudo_nss *nss)
|
|||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"%s: called with NULL handle", __func__);
|
"%s: called with NULL handle", __func__);
|
||||||
debug_return_ptr(NULL);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use cached result if present. */
|
/* Use cached result if present. */
|
||||||
if (handle->cached_defaults)
|
if (cached)
|
||||||
debug_return_ptr(&handle->defaults);
|
debug_return_int(0);
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
|
sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
|
||||||
|
|
||||||
@@ -725,7 +734,7 @@ sudo_sss_getdefs(struct sudo_nss *nss)
|
|||||||
default:
|
default:
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_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) {
|
switch (sss_error) {
|
||||||
@@ -735,7 +744,8 @@ sudo_sss_getdefs(struct sudo_nss *nss)
|
|||||||
struct sss_sudo_rule *sss_rule = sss_result->rules + i;
|
struct sss_sudo_rule *sss_rule = sss_result->rules + i;
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG,
|
sudo_debug_printf(SUDO_DEBUG_DIAG,
|
||||||
"Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
|
"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;
|
goto bad;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -747,13 +757,13 @@ sudo_sss_getdefs(struct sudo_nss *nss)
|
|||||||
sudo_debug_printf(SUDO_DEBUG_ERROR, "sss_error=%u\n", sss_error);
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "sss_error=%u\n", sss_error);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
handle->cached_defaults = true;
|
|
||||||
handle->fn_free_result(sss_result);
|
handle->fn_free_result(sss_result);
|
||||||
debug_return_ptr(&handle->defaults);
|
cached = true;
|
||||||
|
debug_return_int(0);
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
handle->fn_free_result(sss_result);
|
handle->fn_free_result(sss_result);
|
||||||
debug_return_ptr(NULL);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sudo_nss implementation */
|
/* sudo_nss implementation */
|
||||||
|
@@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -21,14 +22,16 @@ struct passwd;
|
|||||||
struct userspec_list;
|
struct userspec_list;
|
||||||
struct defaults_list;
|
struct defaults_list;
|
||||||
|
|
||||||
|
/* XXX - parse_tree, ret_if_found and ret_if_notfound should be private */
|
||||||
struct sudo_nss {
|
struct sudo_nss {
|
||||||
TAILQ_ENTRY(sudo_nss) entries;
|
TAILQ_ENTRY(sudo_nss) entries;
|
||||||
int (*open)(struct sudo_nss *nss);
|
int (*open)(struct sudo_nss *nss);
|
||||||
int (*close)(struct sudo_nss *nss);
|
int (*close)(struct sudo_nss *nss);
|
||||||
int (*parse)(struct sudo_nss *nss);
|
struct sudoers_parse_tree *(*parse)(struct sudo_nss *nss);
|
||||||
struct userspec_list *(*query)(struct sudo_nss *nss, struct passwd *pw);
|
int (*query)(struct sudo_nss *nss, struct passwd *pw);
|
||||||
struct defaults_list *(*getdefs)(struct sudo_nss *nss);
|
int (*getdefs)(struct sudo_nss *nss);
|
||||||
void *handle;
|
void *handle;
|
||||||
|
struct sudoers_parse_tree *parse_tree;
|
||||||
bool ret_if_found;
|
bool ret_if_found;
|
||||||
bool ret_if_notfound;
|
bool ret_if_notfound;
|
||||||
};
|
};
|
||||||
|
@@ -192,17 +192,17 @@ sudoers_policy_init(void *info, char * const envp[])
|
|||||||
sudo_warn_set_locale_func(sudoers_warn_setlocale);
|
sudo_warn_set_locale_func(sudoers_warn_setlocale);
|
||||||
init_parser(sudoers_file, false);
|
init_parser(sudoers_file, false);
|
||||||
TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
|
TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
|
||||||
if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
|
if (nss->open(nss) == -1 || (nss->parse_tree = nss->parse(nss)) == NULL) {
|
||||||
struct defaults_list *defs = nss->getdefs(nss);
|
|
||||||
sources++;
|
|
||||||
if (defs == NULL || !update_defaults(defs,
|
|
||||||
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);
|
TAILQ_REMOVE(snl, nss, entries);
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sources++;
|
||||||
|
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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (sources == 0) {
|
if (sources == 0) {
|
||||||
sudo_warnx(U_("no valid sudoers sources found, quitting"));
|
sudo_warnx(U_("no valid sudoers sources found, quitting"));
|
||||||
@@ -243,12 +243,12 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
/* Is root even allowed to run sudo? */
|
/* Is root even allowed to run sudo? */
|
||||||
if (user_uid == 0 && !def_root_sudo) {
|
if (user_uid == 0 && !def_root_sudo) {
|
||||||
/* Not an audit event. */
|
/* Not an audit event. */
|
||||||
sudo_warnx(U_("sudoers specifies that root is not allowed to sudo"));
|
sudo_warnx(U_("sudoers specifies that root is not allowed to sudo"));
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set_perms(PERM_INITIAL))
|
if (!set_perms(PERM_INITIAL))
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
/* Environment variables specified on the command line. */
|
/* Environment variables specified on the command line. */
|
||||||
if (env_add != NULL && env_add[0] != NULL)
|
if (env_add != NULL && env_add[0] != NULL)
|
||||||
@@ -854,8 +854,7 @@ set_cmnd(void)
|
|||||||
user_base = user_cmnd;
|
user_base = user_cmnd;
|
||||||
|
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
struct defaults_list *defs = nss->getdefs(nss);
|
if (!update_defaults(nss->parse_tree, SETDEF_CMND, false)) {
|
||||||
if (defs == NULL || !update_defaults(defs, SETDEF_CMND, false)) {
|
|
||||||
log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
|
log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
|
||||||
N_("problem with defaults entries"));
|
N_("problem with defaults entries"));
|
||||||
}
|
}
|
||||||
|
@@ -285,7 +285,7 @@ main(int argc, char *argv[])
|
|||||||
(void) fputs("Parses OK", stdout);
|
(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);
|
(void) fputs(" (problem with defaults entries)", stdout);
|
||||||
puts(".");
|
puts(".");
|
||||||
|
|
||||||
@@ -301,22 +301,23 @@ main(int argc, char *argv[])
|
|||||||
/* This loop must match the one in sudo_file_lookup() */
|
/* This loop must match the one in sudo_file_lookup() */
|
||||||
printf("\nEntries for user %s:\n", user_name);
|
printf("\nEntries for user %s:\n", user_name);
|
||||||
match = UNSPEC;
|
match = UNSPEC;
|
||||||
TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
|
TAILQ_FOREACH_REVERSE(us, &parsed_policy.userspecs, userspec_list, entries) {
|
||||||
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
|
if (userlist_matches(&parsed_policy, sudo_user.pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
||||||
sudo_lbuf_append(&lbuf, "\n");
|
sudo_lbuf_append(&lbuf, "\n");
|
||||||
sudoers_format_privilege(&lbuf, priv, false);
|
sudoers_format_privilege(&lbuf, &parsed_policy, priv, false);
|
||||||
sudo_lbuf_print(&lbuf);
|
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) {
|
if (host_match == ALLOW) {
|
||||||
puts("\thost matched");
|
puts("\thost matched");
|
||||||
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
|
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
|
||||||
runas_match = runaslist_matches(cs->runasuserlist,
|
runas_match = runaslist_matches(&parsed_policy,
|
||||||
cs->runasgrouplist, NULL, NULL);
|
cs->runasuserlist, cs->runasgrouplist, NULL, NULL);
|
||||||
if (runas_match == ALLOW) {
|
if (runas_match == ALLOW) {
|
||||||
puts("\trunas matched");
|
puts("\trunas matched");
|
||||||
cmnd_match = cmnd_matches(cs->cmnd);
|
cmnd_match = cmnd_matches(&parsed_policy, cs->cmnd);
|
||||||
if (cmnd_match != UNSPEC)
|
if (cmnd_match != UNSPEC)
|
||||||
match = cmnd_match;
|
match = cmnd_match;
|
||||||
printf("\tcmnd %s\n", match == ALLOW ? "allowed" :
|
printf("\tcmnd %s\n", match == ALLOW ? "allowed" :
|
||||||
@@ -483,8 +484,8 @@ print_defaults(struct sudo_lbuf *lbuf)
|
|||||||
struct defaults *def, *next;
|
struct defaults *def, *next;
|
||||||
debug_decl(print_defaults, SUDOERS_DEBUG_UTIL)
|
debug_decl(print_defaults, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(def, &defaults, entries, next)
|
TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next)
|
||||||
sudoers_format_default_line(lbuf, def, &next, false);
|
sudoers_format_default_line(lbuf, &parsed_policy, def, &next, false);
|
||||||
|
|
||||||
debug_return_bool(!sudo_lbuf_error(lbuf));
|
debug_return_bool(!sudo_lbuf_error(lbuf));
|
||||||
}
|
}
|
||||||
@@ -502,7 +503,7 @@ print_alias(void *v1, void *v2)
|
|||||||
TAILQ_FOREACH(m, &a->members, entries) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m != TAILQ_FIRST(&a->members))
|
if (m != TAILQ_FIRST(&a->members))
|
||||||
sudo_lbuf_append(lbuf, ", ");
|
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");
|
sudo_lbuf_append(lbuf, "\n");
|
||||||
|
|
||||||
@@ -514,7 +515,7 @@ print_aliases(struct sudo_lbuf *lbuf)
|
|||||||
{
|
{
|
||||||
debug_decl(print_aliases, SUDOERS_DEBUG_UTIL)
|
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));
|
debug_return_bool(!sudo_lbuf_error(lbuf));
|
||||||
}
|
}
|
||||||
@@ -541,7 +542,7 @@ dump_sudoers(struct sudo_lbuf *lbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Print User_Specs */
|
/* Print User_Specs */
|
||||||
if (!sudoers_format_userspecs(lbuf, &userspecs, NULL, false, true))
|
if (!sudoers_format_userspecs(lbuf, &parsed_policy, NULL, false, true))
|
||||||
goto done;
|
goto done;
|
||||||
if (lbuf->len > 1) {
|
if (lbuf->len > 1) {
|
||||||
sudo_lbuf_print(lbuf);
|
sudo_lbuf_print(lbuf);
|
||||||
|
@@ -246,8 +246,8 @@ main(int argc, char *argv[])
|
|||||||
init_parser(sudoers_file, quiet);
|
init_parser(sudoers_file, quiet);
|
||||||
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||||
(void) sudoersparse();
|
(void) sudoersparse();
|
||||||
(void) update_defaults(&defaults, SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER,
|
(void) update_defaults(&parsed_policy,
|
||||||
quiet);
|
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, quiet);
|
||||||
sudoers_setlocale(oldlocale, NULL);
|
sudoers_setlocale(oldlocale, NULL);
|
||||||
|
|
||||||
editor = get_editor(&editor_argc, &editor_argv);
|
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)
|
debug_decl(check_defaults_and_aliases, SUDOERS_DEBUG_UTIL)
|
||||||
|
|
||||||
if (!check_defaults(quiet)) {
|
if (!check_defaults(&parsed_policy, quiet)) {
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
rcstr_delref(errorfile);
|
rcstr_delref(errorfile);
|
||||||
errorfile = NULL;
|
errorfile = NULL;
|
||||||
errorlineno = -1;
|
errorlineno = -1;
|
||||||
/* XXX - should edit all files with errors */
|
/* XXX - should edit all files with errors */
|
||||||
TAILQ_FOREACH(d, &defaults, entries) {
|
TAILQ_FOREACH(d, &parsed_policy.defaults, entries) {
|
||||||
if (d->error) {
|
if (d->error) {
|
||||||
/* Defaults parse error, set errorfile/errorlineno. */
|
/* Defaults parse error, set errorfile/errorlineno. */
|
||||||
errorfile = rcstr_addref(d->file);
|
errorfile = rcstr_addref(d->file);
|
||||||
@@ -602,7 +602,7 @@ reparse_sudoers(char *editor, int editor_argc, char **editor_argv,
|
|||||||
}
|
}
|
||||||
fclose(sudoersin);
|
fclose(sudoersin);
|
||||||
if (!parse_error) {
|
if (!parse_error) {
|
||||||
(void) update_defaults(&defaults,
|
(void) update_defaults(&parsed_policy,
|
||||||
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
|
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
|
||||||
check_defaults_and_aliases(strict, quiet);
|
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"));
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
}
|
}
|
||||||
if (!parse_error) {
|
if (!parse_error) {
|
||||||
(void) update_defaults(&defaults,
|
(void) update_defaults(&parsed_policy,
|
||||||
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
|
SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
|
||||||
check_defaults_and_aliases(strict, quiet);
|
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;
|
int errors = 0;
|
||||||
debug_decl(check_alias, SUDOERS_DEBUG_ALIAS)
|
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 */
|
/* check alias contents */
|
||||||
TAILQ_FOREACH(m, &a->members, entries) {
|
TAILQ_FOREACH(m, &a->members, entries) {
|
||||||
if (m->type != ALIAS)
|
if (m->type != ALIAS)
|
||||||
@@ -1071,14 +1071,14 @@ check_aliases(bool strict, bool quiet)
|
|||||||
int errors = 0;
|
int errors = 0;
|
||||||
debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS)
|
debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS)
|
||||||
|
|
||||||
used_aliases = rbcreate(alias_compare);
|
used_aliases = alloc_aliases();
|
||||||
if (used_aliases == NULL) {
|
if (used_aliases == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward check. */
|
/* Forward check. */
|
||||||
TAILQ_FOREACH(us, &userspecs, entries) {
|
TAILQ_FOREACH(us, &parsed_policy.userspecs, entries) {
|
||||||
TAILQ_FOREACH(m, &us->users, entries) {
|
TAILQ_FOREACH(m, &us->users, entries) {
|
||||||
if (m->type == ALIAS) {
|
if (m->type == ALIAS) {
|
||||||
errors += check_alias(m->name, USERALIAS,
|
errors += check_alias(m->name, USERALIAS,
|
||||||
@@ -1118,13 +1118,13 @@ check_aliases(bool strict, bool quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reverse check (destructive) */
|
/* Reverse check (destructive) */
|
||||||
if (!alias_find_used(used_aliases))
|
if (!alias_find_used(&parsed_policy, used_aliases))
|
||||||
errors++;
|
errors++;
|
||||||
rbdestroy(used_aliases, alias_free);
|
free_aliases(used_aliases);
|
||||||
|
|
||||||
/* If all aliases were referenced we will have an empty tree. */
|
/* If all aliases were referenced we will have an empty tree. */
|
||||||
if (!no_aliases() && !quiet)
|
if (!no_aliases(&parsed_policy) && !quiet)
|
||||||
alias_apply(print_unused, NULL);
|
alias_apply(&parsed_policy, print_unused, NULL);
|
||||||
|
|
||||||
debug_return_int(strict ? errors : 0);
|
debug_return_int(strict ? errors : 0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user