Use a list head struct when storing the semi-circular lists and
convert to tail queues in the process. This will allow us to reverse foreach loops more easily and it makes it clearer which functions expect a list as opposed to a single member. Add macros for manipulating lists. Some of these should become functions. When freeing up a list, just pop off the last item in the queue instead of going from head to tail. This is simpler since we don't have to stash a pointer to the next member, we always just use the last one in the queue until the queue is empty. Rename match functions that take a list to have list in the name. Break cmnd_matches() into cmnd_matches() and cmndlist_matches.
This commit is contained in:
4
alias.c
4
alias.c
@@ -114,7 +114,7 @@ alias_add(name, type, members)
|
|||||||
a = emalloc(sizeof(*a));
|
a = emalloc(sizeof(*a));
|
||||||
a->name = name;
|
a->name = name;
|
||||||
a->type = type;
|
a->type = type;
|
||||||
a->first_member = members;
|
LIST2HEAD(a->members, members);
|
||||||
if (rbinsert(aliases, a)) {
|
if (rbinsert(aliases, a)) {
|
||||||
efree(a);
|
efree(a);
|
||||||
snprintf(errbuf, sizeof(errbuf), "Alias `%s' already defined", name);
|
snprintf(errbuf, sizeof(errbuf), "Alias `%s' already defined", name);
|
||||||
@@ -154,7 +154,7 @@ alias_free(v)
|
|||||||
struct member *m;
|
struct member *m;
|
||||||
VOID *next;
|
VOID *next;
|
||||||
|
|
||||||
for (m = a->first_member; m != NULL; m = next) {
|
for (m = a->members.first; m != NULL; m = next) {
|
||||||
next = m->next;
|
next = m->next;
|
||||||
efree(m->name);
|
efree(m->name);
|
||||||
efree(m);
|
efree(m);
|
||||||
|
12
defaults.c
12
defaults.c
@@ -92,8 +92,6 @@ static struct strmap priorities[] = {
|
|||||||
{ NULL, -1 }
|
{ NULL, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct defaults *defaults;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local prototypes.
|
* Local prototypes.
|
||||||
*/
|
*/
|
||||||
@@ -503,7 +501,7 @@ update_defaults(skip_cmnd)
|
|||||||
{
|
{
|
||||||
struct defaults *def;
|
struct defaults *def;
|
||||||
|
|
||||||
for (def = defaults; def != NULL; def = def->next) {
|
LH_FOREACH_FWD(defaults, def) {
|
||||||
if (skip_cmnd == (def->type == DEFAULTS_CMND))
|
if (skip_cmnd == (def->type == DEFAULTS_CMND))
|
||||||
continue;
|
continue;
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
@@ -511,22 +509,22 @@ update_defaults(skip_cmnd)
|
|||||||
if (!set_default(def->var, def->val, def->op))
|
if (!set_default(def->var, def->val, def->op))
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
case DEFAULTS_USER:
|
case DEFAULTS_USER:
|
||||||
if (user_matches(sudo_user.pw, def->binding) &&
|
if (userlist_matches(sudo_user.pw, &def->binding) &&
|
||||||
!set_default(def->var, def->val, def->op))
|
!set_default(def->var, def->val, def->op))
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_RUNAS:
|
case DEFAULTS_RUNAS:
|
||||||
if (runas_matches(def->binding) &&
|
if (runaslist_matches(&def->binding) &&
|
||||||
!set_default(def->var, def->val, def->op))
|
!set_default(def->var, def->val, def->op))
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_HOST:
|
case DEFAULTS_HOST:
|
||||||
if (host_matches(def->binding) &&
|
if (hostlist_matches(&def->binding) &&
|
||||||
!set_default(def->var, def->val, def->op))
|
!set_default(def->var, def->val, def->op))
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_CMND:
|
case DEFAULTS_CMND:
|
||||||
if (cmnd_matches(def->binding) &&
|
if (cmndlist_matches(&def->binding) &&
|
||||||
!set_default(def->var, def->val, def->op))
|
!set_default(def->var, def->val, def->op))
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
68
gram.y
68
gram.y
@@ -67,8 +67,8 @@ int verbose = FALSE;
|
|||||||
int errorlineno = -1;
|
int errorlineno = -1;
|
||||||
char *errorfile = NULL;
|
char *errorfile = NULL;
|
||||||
|
|
||||||
struct defaults *defaults;
|
struct defaults_list defaults;
|
||||||
struct userspec *userspecs;
|
struct userspec_list userspecs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local protoypes
|
* Local protoypes
|
||||||
@@ -242,8 +242,8 @@ privilege : hostlist '=' cmndspeclist {
|
|||||||
struct cmndtag tags;
|
struct cmndtag tags;
|
||||||
struct privilege *p = emalloc(sizeof(*p));
|
struct privilege *p = emalloc(sizeof(*p));
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
p->hostlist = $1;
|
LIST2HEAD(p->hostlist, $1);
|
||||||
p->cmndlist = $3;
|
LIST2HEAD(p->cmndlist, $3);
|
||||||
tags.nopasswd = tags.noexec = tags.setenv = UNSPEC;
|
tags.nopasswd = tags.noexec = tags.setenv = UNSPEC;
|
||||||
/* propagate tags */
|
/* propagate tags */
|
||||||
for (cs = $3; cs != NULL; cs = cs->next) {
|
for (cs = $3; cs != NULL; cs = cs->next) {
|
||||||
@@ -297,7 +297,7 @@ cmndspeclist : cmndspec
|
|||||||
|
|
||||||
cmndspec : runasspec cmndtag opcmnd {
|
cmndspec : runasspec cmndtag opcmnd {
|
||||||
struct cmndspec *cs = emalloc(sizeof(*cs));
|
struct cmndspec *cs = emalloc(sizeof(*cs));
|
||||||
cs->runaslist = $1;
|
LIST2HEAD(cs->runaslist, $1);
|
||||||
cs->tags = $2;
|
cs->tags = $2;
|
||||||
cs->cmnd = $3;
|
cs->cmnd = $3;
|
||||||
cs->prev = cs;
|
cs->prev = cs;
|
||||||
@@ -514,12 +514,9 @@ add_defaults(type, binding, defs)
|
|||||||
*/
|
*/
|
||||||
for (d = defs; d != NULL; d = d->next) {
|
for (d = defs; d != NULL; d = d->next) {
|
||||||
d->type = type;
|
d->type = type;
|
||||||
d->binding = binding;
|
LIST2HEAD(d->binding, binding);
|
||||||
}
|
}
|
||||||
if (defaults == NULL)
|
HEAD_APPEND(defaults, defs);
|
||||||
defaults = defs;
|
|
||||||
else
|
|
||||||
LIST_APPEND(defaults, defs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -534,14 +531,11 @@ add_userspec(members, privs)
|
|||||||
struct userspec *u;
|
struct userspec *u;
|
||||||
|
|
||||||
u = emalloc(sizeof(*u));
|
u = emalloc(sizeof(*u));
|
||||||
u->user = members;
|
LIST2HEAD(u->users, members);
|
||||||
u->privileges = privs;
|
LIST2HEAD(u->privileges, privs);
|
||||||
u->prev = u;
|
u->prev = u;
|
||||||
u->next = NULL;
|
u->next = NULL;
|
||||||
if (userspecs == NULL)
|
HEAD_APPEND(userspecs, u);
|
||||||
userspecs = u;
|
|
||||||
else
|
|
||||||
LIST_APPEND(userspecs, u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -558,55 +552,53 @@ init_parser(path, quiet)
|
|||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
VOID *next;
|
|
||||||
|
|
||||||
for (us = userspecs; us != NULL; us = next) {
|
while ((us = LH_LAST(userspecs)) != NULL) {
|
||||||
for (m = us->user; m != NULL; m = next) {
|
LH_POP(userspecs);
|
||||||
next = m->next;
|
while ((m = LH_LAST(us->users)) != NULL) {
|
||||||
|
LH_POP(us->users);
|
||||||
efree(m->name);
|
efree(m->name);
|
||||||
efree(m);
|
efree(m);
|
||||||
}
|
}
|
||||||
for (priv = us->privileges; priv != NULL; priv = next) {
|
while ((priv = LH_LAST(us->privileges)) != NULL) {
|
||||||
for (m = priv->hostlist; m != NULL; m = next) {
|
LH_POP(us->privileges);
|
||||||
next = m->next;
|
while ((m = LH_LAST(priv->hostlist)) != NULL) {
|
||||||
|
LH_POP(priv->hostlist);
|
||||||
efree(m->name);
|
efree(m->name);
|
||||||
efree(m);
|
efree(m);
|
||||||
}
|
}
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = next) {
|
while ((cs = LH_LAST(priv->cmndlist)) != NULL) {
|
||||||
for (m = cs->runaslist; m != NULL; m = next) {
|
LH_POP(priv->cmndlist);
|
||||||
next = m->next;
|
while ((m = LH_LAST(cs->runaslist)) != NULL) {
|
||||||
|
LH_POP(cs->runaslist);
|
||||||
efree(m->name);
|
efree(m->name);
|
||||||
efree(m);
|
efree(m);
|
||||||
}
|
}
|
||||||
efree(cs->cmnd->name);
|
efree(cs->cmnd->name);
|
||||||
efree(cs->cmnd);
|
efree(cs->cmnd);
|
||||||
next = cs->next;
|
|
||||||
efree(cs);
|
efree(cs);
|
||||||
}
|
}
|
||||||
next = priv->next;
|
|
||||||
efree(priv);
|
efree(priv);
|
||||||
}
|
}
|
||||||
next = us->next;
|
|
||||||
efree(us);
|
|
||||||
}
|
}
|
||||||
userspecs = NULL;
|
LH_INIT(userspecs);
|
||||||
|
|
||||||
lastbinding = NULL;
|
lastbinding = NULL;
|
||||||
for (d = defaults; d != NULL; d = next) {
|
while ((d = LH_LAST(defaults)) != NULL) {
|
||||||
if (d->binding != lastbinding) {
|
LH_POP(defaults);
|
||||||
for (m = d->binding; m != NULL; m = next) {
|
if (LH_FIRST(d->binding) != lastbinding) {
|
||||||
next = m->next;
|
lastbinding = LH_FIRST(d->binding);
|
||||||
|
while ((m = LH_LAST(d->binding)) != NULL) {
|
||||||
|
LH_POP(d->binding);
|
||||||
efree(m->name);
|
efree(m->name);
|
||||||
efree(m);
|
efree(m);
|
||||||
}
|
}
|
||||||
lastbinding = d->binding;
|
|
||||||
}
|
}
|
||||||
next = d->next;
|
|
||||||
efree(d->var);
|
efree(d->var);
|
||||||
efree(d->val);
|
efree(d->val);
|
||||||
efree(d);
|
efree(d);
|
||||||
}
|
}
|
||||||
defaults = NULL;
|
LH_INIT(defaults);
|
||||||
|
|
||||||
init_aliases();
|
init_aliases();
|
||||||
|
|
||||||
|
84
match.c
84
match.c
@@ -103,15 +103,15 @@ static int has_meta __P((char *));
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
user_matches(pw, list)
|
userlist_matches(pw, list)
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct member *list;
|
struct member_list *list;
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
int rval, matched = UNSPEC;
|
int rval, matched = UNSPEC;
|
||||||
|
|
||||||
for (m = list; m != NULL; m = m->next) {
|
for (m = list->first; m != NULL; m = m->next) {
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case ALL:
|
case ALL:
|
||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
@@ -126,7 +126,7 @@ user_matches(pw, list)
|
|||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = find_alias(m->name, USERALIAS)) != NULL) {
|
if ((a = find_alias(m->name, USERALIAS)) != NULL) {
|
||||||
rval = user_matches(pw, a->first_member);
|
rval = userlist_matches(pw, &a->members);
|
||||||
if (rval != UNSPEC)
|
if (rval != UNSPEC)
|
||||||
matched = m->negated ? !rval : rval;
|
matched = m->negated ? !rval : rval;
|
||||||
break;
|
break;
|
||||||
@@ -147,8 +147,8 @@ user_matches(pw, list)
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
runas_matches(list)
|
runaslist_matches(list)
|
||||||
struct member *list;
|
struct member_list *list;
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
@@ -157,7 +157,7 @@ runas_matches(list)
|
|||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
|
return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
|
||||||
|
|
||||||
for (m = list; m != NULL; m = m->next) {
|
for (m = list->first; m != NULL; m = m->next) {
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case ALL:
|
case ALL:
|
||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
@@ -172,7 +172,7 @@ runas_matches(list)
|
|||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
|
if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
|
||||||
rval = runas_matches(a->first_member);
|
rval = runaslist_matches(&a->members);
|
||||||
if (rval != UNSPEC)
|
if (rval != UNSPEC)
|
||||||
matched = m->negated ? !rval : rval;
|
matched = m->negated ? !rval : rval;
|
||||||
break;
|
break;
|
||||||
@@ -192,14 +192,14 @@ runas_matches(list)
|
|||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
host_matches(list)
|
hostlist_matches(list)
|
||||||
struct member *list;
|
struct member_list *list;
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
int rval, matched = UNSPEC;
|
int rval, matched = UNSPEC;
|
||||||
|
|
||||||
for (m = list; m != NULL; m = m->next) {
|
for (m = list->first; m != NULL; m = m->next) {
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case ALL:
|
case ALL:
|
||||||
matched = !m->negated;
|
matched = !m->negated;
|
||||||
@@ -214,7 +214,7 @@ host_matches(list)
|
|||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = find_alias(m->name, HOSTALIAS)) != NULL) {
|
if ((a = find_alias(m->name, HOSTALIAS)) != NULL) {
|
||||||
rval = host_matches(a->first_member);
|
rval = hostlist_matches(&a->members);
|
||||||
if (rval != UNSPEC)
|
if (rval != UNSPEC)
|
||||||
matched = m->negated ? !rval : rval;
|
matched = m->negated ? !rval : rval;
|
||||||
break;
|
break;
|
||||||
@@ -229,37 +229,53 @@ host_matches(list)
|
|||||||
return(matched);
|
return(matched);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check cmnd and args.
|
||||||
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cmnd_matches(m)
|
||||||
|
struct member *m;
|
||||||
|
{
|
||||||
|
struct alias *a;
|
||||||
|
struct sudo_command *c;
|
||||||
|
int rval, matched = UNSPEC;
|
||||||
|
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
matched = !m->negated;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
if ((a = find_alias(m->name, CMNDALIAS)) != NULL) {
|
||||||
|
rval = cmndlist_matches(&a->members);
|
||||||
|
if (rval != UNSPEC)
|
||||||
|
matched = m->negated ? !rval : rval;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMMAND:
|
||||||
|
c = (struct sudo_command *)m->name;
|
||||||
|
if (command_matches(c->cmnd, c->args))
|
||||||
|
matched = !m->negated;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(matched);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for cmnd and args in a list of members.
|
* Check for cmnd and args in a list of members.
|
||||||
* Returns ALLOW, DENY or UNSPEC.
|
* Returns ALLOW, DENY or UNSPEC.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cmnd_matches(list)
|
cmndlist_matches(list)
|
||||||
struct member *list;
|
struct member_list *list;
|
||||||
{
|
{
|
||||||
struct sudo_command *c;
|
|
||||||
struct member *m;
|
struct member *m;
|
||||||
struct alias *a;
|
|
||||||
int rval, matched = UNSPEC;
|
int rval, matched = UNSPEC;
|
||||||
|
|
||||||
for (m = list; m != NULL; m = m->next) {
|
for (m = list->first; m != NULL; m = m->next) {
|
||||||
switch (m->type) {
|
rval = cmnd_matches(m);
|
||||||
case ALL:
|
if (rval != UNSPEC)
|
||||||
matched = !m->negated;
|
matched = m->negated ? !rval : rval;
|
||||||
break;
|
|
||||||
case ALIAS:
|
|
||||||
if ((a = find_alias(m->name, CMNDALIAS)) != NULL) {
|
|
||||||
rval = cmnd_matches(a->first_member);
|
|
||||||
if (rval != UNSPEC)
|
|
||||||
matched = m->negated ? !rval : rval;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COMMAND:
|
|
||||||
c = (struct sudo_command *)m->name;
|
|
||||||
if (command_matches(c->cmnd, c->args))
|
|
||||||
matched = !m->negated;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return(matched);
|
return(matched);
|
||||||
}
|
}
|
||||||
|
97
parse.c
97
parse.c
@@ -55,12 +55,6 @@ __unused static const char rcsid[] = "$Sudo$";
|
|||||||
/* Characters that must be quoted in sudoers */
|
/* Characters that must be quoted in sudoers */
|
||||||
#define SUDOERS_QUOTED "*?[]!:\\,=#\""
|
#define SUDOERS_QUOTED "*?[]!:\\,=#\""
|
||||||
|
|
||||||
/*
|
|
||||||
* Parsed sudoers info.
|
|
||||||
*/
|
|
||||||
extern struct userspec *userspecs;
|
|
||||||
extern struct defaults *defaults;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local prototypes.
|
* Local prototypes.
|
||||||
*/
|
*/
|
||||||
@@ -93,7 +87,7 @@ sudoers_lookup(pwflag)
|
|||||||
int validated, match, host_match, runas_match, cmnd_match;
|
int validated, match, host_match, runas_match, cmnd_match;
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
struct cmndtag *tags = NULL;
|
struct cmndtag *tags = NULL;
|
||||||
struct member *runas;
|
struct member_list *runas;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
|
|
||||||
@@ -116,13 +110,15 @@ sudoers_lookup(pwflag)
|
|||||||
CLR(validated, FLAG_NO_USER);
|
CLR(validated, FLAG_NO_USER);
|
||||||
CLR(validated, FLAG_NO_HOST);
|
CLR(validated, FLAG_NO_HOST);
|
||||||
match = DENY;
|
match = DENY;
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
/* XXX - it should be faster to start from the bottom and
|
||||||
if (user_matches(sudo_user.pw, us->user) != ALLOW)
|
work our way up and then just stop at the first match. */
|
||||||
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
|
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
if (host_matches(priv->hostlist) != ALLOW)
|
if (hostlist_matches(&priv->hostlist) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
/* 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 ||
|
||||||
@@ -149,22 +145,24 @@ sudoers_lookup(pwflag)
|
|||||||
/* Need to be runas user while stat'ing things. */
|
/* Need to be runas user while stat'ing things. */
|
||||||
set_perms(PERM_RUNAS);
|
set_perms(PERM_RUNAS);
|
||||||
|
|
||||||
|
/* XXX - it should be faster to start from the bottom and
|
||||||
|
work our way up and then just stop at the first match. */
|
||||||
match = UNSPEC;
|
match = UNSPEC;
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
if (user_matches(sudo_user.pw, us->user) != ALLOW)
|
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
CLR(validated, FLAG_NO_USER);
|
CLR(validated, FLAG_NO_USER);
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
host_match = host_matches(priv->hostlist);
|
host_match = hostlist_matches(&priv->hostlist);
|
||||||
if (host_match == UNSPEC)
|
if (host_match == UNSPEC)
|
||||||
continue;
|
continue;
|
||||||
if (host_match == ALLOW)
|
if (host_match == ALLOW)
|
||||||
CLR(validated, FLAG_NO_HOST);
|
CLR(validated, FLAG_NO_HOST);
|
||||||
runas = NULL;
|
runas = NULL;
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
if (cs->runaslist != NULL)
|
if (!LH_EMPTY(cs->runaslist))
|
||||||
runas = cs->runaslist;
|
runas = &cs->runaslist;
|
||||||
runas_match = runas_matches(runas);
|
runas_match = runaslist_matches(runas);
|
||||||
if (runas_match != UNSPEC) {
|
if (runas_match != UNSPEC) {
|
||||||
cmnd_match = cmnd_matches(cs->cmnd);
|
cmnd_match = cmnd_matches(cs->cmnd);
|
||||||
if (cmnd_match != UNSPEC)
|
if (cmnd_match != UNSPEC)
|
||||||
@@ -229,23 +227,24 @@ display_privs(v, pw)
|
|||||||
printf("User %s may run the following commands on this host:\n",
|
printf("User %s may run the following commands on this host:\n",
|
||||||
pw->pw_name);
|
pw->pw_name);
|
||||||
|
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
if (user_matches(pw, us->user) != ALLOW ||
|
/* XXX - why only check the first privilege here? */
|
||||||
host_matches(us->privileges->hostlist) != ALLOW)
|
if (userlist_matches(pw, &us->users) != ALLOW ||
|
||||||
|
hostlist_matches(&us->privileges.first->hostlist) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
tags.noexec = def_noexec;
|
tags.noexec = def_noexec;
|
||||||
tags.setenv = def_setenv;
|
tags.setenv = def_setenv;
|
||||||
tags.nopasswd = !def_authenticate;
|
tags.nopasswd = !def_authenticate;
|
||||||
lbuf_append(&lbuf, " ", NULL);
|
lbuf_append(&lbuf, " ", NULL);
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
if (cs != priv->cmndlist)
|
if (cs != LH_FIRST(priv->cmndlist))
|
||||||
lbuf_append(&lbuf, ", ", NULL);
|
lbuf_append(&lbuf, ", ", NULL);
|
||||||
lbuf_append(&lbuf, "(", NULL);
|
lbuf_append(&lbuf, "(", NULL);
|
||||||
if (cs->runaslist != NULL) {
|
if (!LH_EMPTY(cs->runaslist)) {
|
||||||
for (m = cs->runaslist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(cs->runaslist, m) {
|
||||||
if (m != cs->runaslist)
|
if (m != LH_FIRST(cs->runaslist))
|
||||||
lbuf_append(&lbuf, ", ", NULL);
|
lbuf_append(&lbuf, ", ", NULL);
|
||||||
print_member(&lbuf, m->name, m->type, m->negated,
|
print_member(&lbuf, m->name, m->type, m->negated,
|
||||||
RUNASALIAS);
|
RUNASALIAS);
|
||||||
@@ -293,19 +292,19 @@ display_defaults(pw)
|
|||||||
{
|
{
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
struct lbuf lbuf;
|
struct lbuf lbuf;
|
||||||
char *prefix;
|
char *prefix = NULL;
|
||||||
int per_runas = 0, per_cmnd = 0;
|
int per_runas = 0, per_cmnd = 0;
|
||||||
|
|
||||||
lbuf_init(&lbuf, NULL, 4, 0);
|
lbuf_init(&lbuf, NULL, 4, 0);
|
||||||
|
|
||||||
for (d = defaults, prefix = NULL; d != NULL; d = d->next) {
|
LH_FOREACH_FWD(defaults, d) {
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case DEFAULTS_HOST:
|
case DEFAULTS_HOST:
|
||||||
if (host_matches(d->binding) != ALLOW)
|
if (hostlist_matches(&d->binding) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_USER:
|
case DEFAULTS_USER:
|
||||||
if (user_matches(pw, d->binding) != ALLOW)
|
if (userlist_matches(pw, &d->binding) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case DEFAULTS_RUNAS:
|
case DEFAULTS_RUNAS:
|
||||||
@@ -355,7 +354,7 @@ display_bound_defaults(dtype)
|
|||||||
{
|
{
|
||||||
struct lbuf lbuf;
|
struct lbuf lbuf;
|
||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
struct member *m, *binding;
|
struct member *m, *binding = NULL;
|
||||||
char *dname, *dsep;
|
char *dname, *dsep;
|
||||||
int atype;
|
int atype;
|
||||||
|
|
||||||
@@ -385,12 +384,12 @@ display_bound_defaults(dtype)
|
|||||||
}
|
}
|
||||||
lbuf_init(&lbuf, NULL, 4, 0);
|
lbuf_init(&lbuf, NULL, 4, 0);
|
||||||
printf("Per-%s Defaults entries:\n", dname);
|
printf("Per-%s Defaults entries:\n", dname);
|
||||||
for (d = defaults, binding = NULL; d != NULL; d = d->next) {
|
LH_FOREACH_FWD(defaults, d) {
|
||||||
if (d->type != dtype)
|
if (d->type != dtype)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (d->binding != binding) {
|
if (binding != LH_FIRST(d->binding)) {
|
||||||
binding = d->binding;
|
binding = LH_FIRST(d->binding);
|
||||||
lbuf_append(&lbuf, " Defaults", dsep, NULL);
|
lbuf_append(&lbuf, " Defaults", dsep, NULL);
|
||||||
for (m = binding; m != NULL; m = m->next) {
|
for (m = binding; m != NULL; m = m->next) {
|
||||||
if (m != binding)
|
if (m != binding)
|
||||||
@@ -421,7 +420,8 @@ display_cmnd(v, pw)
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
{
|
{
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
struct member *match, *runas;
|
struct member *match;
|
||||||
|
struct member_list *runas;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
int rval = 1;
|
int rval = 1;
|
||||||
@@ -432,19 +432,20 @@ display_cmnd(v, pw)
|
|||||||
rval = sudo_ldap_display_cmnd(v, pw);
|
rval = sudo_ldap_display_cmnd(v, pw);
|
||||||
#endif
|
#endif
|
||||||
if (rval != 0 && !def_ignore_local_sudoers) {
|
if (rval != 0 && !def_ignore_local_sudoers) {
|
||||||
for (match = NULL, us = userspecs; us != NULL; us = us->next) {
|
match = NULL;
|
||||||
if (user_matches(pw, us->user) != ALLOW)
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
|
if (userlist_matches(pw, &us->users) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
host_match = host_matches(priv->hostlist);
|
host_match = hostlist_matches(&priv->hostlist);
|
||||||
if (host_match == UNSPEC)
|
if (host_match == UNSPEC)
|
||||||
continue;
|
continue;
|
||||||
runas = NULL;
|
runas = NULL;
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
if (cs->runaslist != NULL)
|
if (!LH_EMPTY(cs->runaslist) != NULL)
|
||||||
runas = cs->runaslist;
|
runas = &cs->runaslist;
|
||||||
runas_match = runas_matches(runas);
|
runas_match = runaslist_matches(runas);
|
||||||
if (runas_match != UNSPEC) {
|
if (runas_match != UNSPEC) {
|
||||||
cmnd_match = cmnd_matches(cs->cmnd);
|
cmnd_match = cmnd_matches(cs->cmnd);
|
||||||
if (cmnd_match != UNSPEC)
|
if (cmnd_match != UNSPEC)
|
||||||
@@ -492,8 +493,8 @@ print_member(lbuf, name, type, negated, alias_type)
|
|||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
if ((a = find_alias(name, alias_type)) != NULL) {
|
if ((a = find_alias(name, alias_type)) != NULL) {
|
||||||
for (m = a->first_member; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(a->members, m) {
|
||||||
if (m != a->first_member)
|
if (m != LH_FIRST(a->members))
|
||||||
lbuf_append(lbuf, ", ", NULL);
|
lbuf_append(lbuf, ", ", NULL);
|
||||||
print_member(lbuf, m->name, m->type,
|
print_member(lbuf, m->name, m->type,
|
||||||
negated ? !m->negated : m->negated, alias_type);
|
negated ? !m->negated : m->negated, alias_type);
|
||||||
|
134
parse.h
134
parse.h
@@ -60,12 +60,40 @@ struct cmndtag {
|
|||||||
* pointer of the last entry is NULL and does not point back to the head.
|
* pointer of the last entry is NULL and does not point back to the head.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue list head structure.
|
||||||
|
*/
|
||||||
|
struct defaults_list {
|
||||||
|
struct defaults *first;
|
||||||
|
struct defaults *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct userspec_list {
|
||||||
|
struct userspec *first;
|
||||||
|
struct userspec *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct member_list {
|
||||||
|
struct member *first;
|
||||||
|
struct member *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct privilege_list {
|
||||||
|
struct privilege *first;
|
||||||
|
struct privilege *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmndspec_list {
|
||||||
|
struct cmndspec *first;
|
||||||
|
struct cmndspec *last;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure describing a user specification and list thereof.
|
* Structure describing a user specification and list thereof.
|
||||||
*/
|
*/
|
||||||
struct userspec {
|
struct userspec {
|
||||||
struct member *user; /* list of users */
|
struct member_list users; /* list of users */
|
||||||
struct privilege *privileges; /* list of privileges */
|
struct privilege_list privileges; /* list of privileges */
|
||||||
struct userspec *prev, *next;
|
struct userspec *prev, *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,8 +101,8 @@ struct userspec {
|
|||||||
* Structure describing a privilege specification.
|
* Structure describing a privilege specification.
|
||||||
*/
|
*/
|
||||||
struct privilege {
|
struct privilege {
|
||||||
struct member *hostlist; /* list of hosts */
|
struct member_list hostlist; /* list of hosts */
|
||||||
struct cmndspec *cmndlist; /* list of Cmnd_Specs */
|
struct cmndspec_list cmndlist; /* list of Cmnd_Specs */
|
||||||
struct privilege *prev, *next;
|
struct privilege *prev, *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,7 +110,7 @@ struct privilege {
|
|||||||
* Structure describing a linked list of Cmnd_Specs.
|
* Structure describing a linked list of Cmnd_Specs.
|
||||||
*/
|
*/
|
||||||
struct cmndspec {
|
struct cmndspec {
|
||||||
struct member *runaslist; /* list of runas users */
|
struct member_list runaslist; /* list of runas users */
|
||||||
struct member *cmnd; /* command to allow/deny */
|
struct member *cmnd; /* command to allow/deny */
|
||||||
struct cmndtag tags; /* tag specificaion */
|
struct cmndtag tags; /* tag specificaion */
|
||||||
struct cmndspec *prev, *next;
|
struct cmndspec *prev, *next;
|
||||||
@@ -105,7 +133,7 @@ struct member {
|
|||||||
struct alias {
|
struct alias {
|
||||||
char *name; /* alias name */
|
char *name; /* alias name */
|
||||||
int type; /* {USER,HOST,RUNAS,CMND}ALIAS */
|
int type; /* {USER,HOST,RUNAS,CMND}ALIAS */
|
||||||
struct member *first_member; /* list of alias members */
|
struct member_list members; /* list of alias members */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -114,7 +142,7 @@ struct alias {
|
|||||||
struct defaults {
|
struct defaults {
|
||||||
char *var; /* variable name */
|
char *var; /* variable name */
|
||||||
char *val; /* variable value */
|
char *val; /* variable value */
|
||||||
struct member *binding; /* user/host/runas binding */
|
struct member_list binding; /* user/host/runas binding */
|
||||||
int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
|
int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
|
||||||
int op; /* TRUE, FALSE, '+', '-' */
|
int op; /* TRUE, FALSE, '+', '-' */
|
||||||
struct defaults *prev, *next;
|
struct defaults *prev, *next;
|
||||||
@@ -123,6 +151,7 @@ struct defaults {
|
|||||||
/*
|
/*
|
||||||
* Allocate space for a defaults entry and populate it.
|
* Allocate space for a defaults entry and populate it.
|
||||||
*/
|
*/
|
||||||
|
#undef NEW_DEFAULT
|
||||||
#define NEW_DEFAULT(r, v1, v2, o) do { \
|
#define NEW_DEFAULT(r, v1, v2, o) do { \
|
||||||
(r) = emalloc(sizeof(struct defaults)); \
|
(r) = emalloc(sizeof(struct defaults)); \
|
||||||
(r)->var = (v1); \
|
(r)->var = (v1); \
|
||||||
@@ -135,6 +164,7 @@ struct defaults {
|
|||||||
/*
|
/*
|
||||||
* Allocate space for a member and populate it.
|
* Allocate space for a member and populate it.
|
||||||
*/
|
*/
|
||||||
|
#undef NEW_MEMBER
|
||||||
#define NEW_MEMBER(r, n, t) do { \
|
#define NEW_MEMBER(r, n, t) do { \
|
||||||
(r) = emalloc(sizeof(struct member)); \
|
(r) = emalloc(sizeof(struct member)); \
|
||||||
(r)->name = (n); \
|
(r)->name = (n); \
|
||||||
@@ -147,6 +177,7 @@ struct defaults {
|
|||||||
* Append one queue (or single entry) to another using the
|
* Append one queue (or single entry) to another using the
|
||||||
* circular properties of the prev pointer to simplify the logic.
|
* circular properties of the prev pointer to simplify the logic.
|
||||||
*/
|
*/
|
||||||
|
#undef LIST_APPEND
|
||||||
#define LIST_APPEND(h, e) do { \
|
#define LIST_APPEND(h, e) do { \
|
||||||
void *_tail = (e)->prev; \
|
void *_tail = (e)->prev; \
|
||||||
(h)->prev->next = (e); \
|
(h)->prev->next = (e); \
|
||||||
@@ -154,6 +185,88 @@ struct defaults {
|
|||||||
(h)->prev = _tail; \
|
(h)->prev = _tail; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append the list of entries to the head node and convert
|
||||||
|
* e from a semi-circle queue to normal doubly-linked list.
|
||||||
|
*/
|
||||||
|
#undef HEAD_APPEND
|
||||||
|
#define HEAD_APPEND(h, e) do { \
|
||||||
|
void *_tail = (e)->prev; \
|
||||||
|
if ((h).first == NULL) \
|
||||||
|
(h).first = (e); \
|
||||||
|
else \
|
||||||
|
(h).last->next = (e); \
|
||||||
|
(e)->prev = (h).last; \
|
||||||
|
(h).last = _tail; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert from a semi-circle queue to normal doubly-linked list
|
||||||
|
* with a head node.
|
||||||
|
*/
|
||||||
|
#undef LIST2HEAD
|
||||||
|
#define LIST2HEAD(h, e) do { \
|
||||||
|
if ((e) != NULL) { \
|
||||||
|
(h).first = (e); \
|
||||||
|
(h).last = (e)->prev; \
|
||||||
|
(e)->prev = NULL; \
|
||||||
|
} else { \
|
||||||
|
(h).first = NULL; \
|
||||||
|
(h).last = NULL; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#undef LH_FOREACH_FWD
|
||||||
|
#define LH_FOREACH_FWD(h, v) \
|
||||||
|
for ((v) = (h).first; (v) != NULL; (v) = (v)->next)
|
||||||
|
|
||||||
|
#undef LH_FOREACH_REV
|
||||||
|
#define LH_FOREACH_REV(h, v) \
|
||||||
|
for ((v) = (h).last; (v) != NULL; (v) = (v)->prev)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pop the last element off the end of h.
|
||||||
|
* XXX - really should return the popped element.
|
||||||
|
*/
|
||||||
|
#undef LH_POP
|
||||||
|
#define LH_POP(h) do { \
|
||||||
|
if (!LH_EMPTY(h)) { \
|
||||||
|
if ((h).first == (h).last) \
|
||||||
|
(h).first = (h).last = NULL; \
|
||||||
|
else { \
|
||||||
|
(h).last = (h).last->prev; \
|
||||||
|
(h).last->next = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#undef LH_INIT
|
||||||
|
#define LH_INIT(h) do { \
|
||||||
|
(h).first = NULL; \
|
||||||
|
(h).last = NULL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#undef LH_EMPTY
|
||||||
|
#define LH_EMPTY(h) ((h).first == NULL)
|
||||||
|
|
||||||
|
#undef LH_FIRST
|
||||||
|
#define LH_FIRST(h) ((h).first)
|
||||||
|
|
||||||
|
#undef LH_LAST
|
||||||
|
#define LH_LAST(h) ((h).last)
|
||||||
|
|
||||||
|
#undef LIST_NEXT
|
||||||
|
#define LIST_NEXT(e) ((e)->next)
|
||||||
|
|
||||||
|
#undef LIST_PREV
|
||||||
|
#define LIST_PREV(e) ((e)->prev)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parsed sudoers info.
|
||||||
|
*/
|
||||||
|
extern struct userspec_list userspecs;
|
||||||
|
extern struct defaults_list defaults;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
@@ -161,13 +274,14 @@ char *alias_add __P((char *, int, struct member *));
|
|||||||
int addr_matches __P((char *));
|
int addr_matches __P((char *));
|
||||||
int alias_remove __P((char *, int));
|
int alias_remove __P((char *, int));
|
||||||
int cmnd_matches __P((struct member *));
|
int cmnd_matches __P((struct member *));
|
||||||
|
int cmndlist_matches __P((struct member_list *));
|
||||||
int command_matches __P((char *, char *));
|
int command_matches __P((char *, char *));
|
||||||
int host_matches __P((struct member *));
|
int hostlist_matches __P((struct member_list *));
|
||||||
int hostname_matches __P((char *, char *, char *));
|
int hostname_matches __P((char *, char *, char *));
|
||||||
int netgr_matches __P((char *, char *, char *, char *));
|
int netgr_matches __P((char *, char *, char *, char *));
|
||||||
int no_aliases __P((void));
|
int no_aliases __P((void));
|
||||||
int runas_matches __P((struct member *));
|
int runaslist_matches __P((struct member_list *));
|
||||||
int user_matches __P((struct passwd *, struct member *));
|
int userlist_matches __P((struct passwd *, struct member_list *));
|
||||||
int usergr_matches __P((char *, char *, struct passwd *));
|
int usergr_matches __P((char *, char *, struct passwd *));
|
||||||
int userpw_matches __P((char *, char *, struct passwd *));
|
int userpw_matches __P((char *, char *, struct passwd *));
|
||||||
struct alias *find_alias __P((char *, int));
|
struct alias *find_alias __P((char *, int));
|
||||||
|
@@ -99,9 +99,6 @@ struct passwd *(*my_getpwuid) __P((uid_t)) = getpwuid;
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
extern struct defaults *defaults;
|
|
||||||
extern struct userspec *userspecs;
|
|
||||||
|
|
||||||
int print_alias __P((VOID *, VOID *));
|
int print_alias __P((VOID *, VOID *));
|
||||||
void dump_sudoers __P((void));
|
void dump_sudoers __P((void));
|
||||||
void print_defaults __P((void));
|
void print_defaults __P((void));
|
||||||
@@ -128,7 +125,7 @@ main(argc, argv)
|
|||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
struct cmndspec *cs;
|
struct cmndspec *cs;
|
||||||
struct member *runas;
|
struct member_list *runas;
|
||||||
struct privilege *priv;
|
struct privilege *priv;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
char *p, *grfile, *pwfile, *uflag, hbuf[MAXHOSTNAMELEN];
|
char *p, *grfile, *pwfile, *uflag, hbuf[MAXHOSTNAMELEN];
|
||||||
@@ -272,20 +269,20 @@ main(argc, argv)
|
|||||||
/* This loop must match the one in sudoers_lookup() */
|
/* This loop must match the one in sudoers_lookup() */
|
||||||
printf("\nEntries for user %s:\n", user_name);
|
printf("\nEntries for user %s:\n", user_name);
|
||||||
matched = UNSPEC;
|
matched = UNSPEC;
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
if (user_matches(sudo_user.pw, us->user) != TRUE)
|
if (userlist_matches(sudo_user.pw, &us->users) != TRUE)
|
||||||
continue;
|
continue;
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
print_privilege(priv);
|
print_privilege(priv); /* XXX */
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
if (host_matches(priv->hostlist) == TRUE) {
|
if (hostlist_matches(&priv->hostlist) == TRUE) {
|
||||||
puts("\thost matched");
|
puts("\thost matched");
|
||||||
runas = NULL;
|
runas = NULL;
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
if (cs->runaslist != NULL)
|
if (!LH_EMPTY(cs->runaslist))
|
||||||
runas = cs->runaslist;
|
runas = &cs->runaslist;
|
||||||
if (runas_matches(runas) == TRUE) {
|
if (runaslist_matches(runas) == TRUE) {
|
||||||
puts("\trunas matched");
|
puts("\trunas matched");
|
||||||
rval = cmnd_matches(cs->cmnd);
|
rval = cmnd_matches(cs->cmnd);
|
||||||
if (rval != UNSPEC)
|
if (rval != UNSPEC)
|
||||||
@@ -391,7 +388,7 @@ print_defaults()
|
|||||||
struct defaults *d;
|
struct defaults *d;
|
||||||
struct member *m;
|
struct member *m;
|
||||||
|
|
||||||
for (d = defaults; d != NULL; d = d->next) {
|
LH_FOREACH_FWD(defaults, d) {
|
||||||
(void) fputs("Defaults", stdout);
|
(void) fputs("Defaults", stdout);
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case DEFAULTS_HOST:
|
case DEFAULTS_HOST:
|
||||||
@@ -407,8 +404,8 @@ print_defaults()
|
|||||||
putchar('!');
|
putchar('!');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (m = d->binding; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(d->binding, m) {
|
||||||
if (m != d->binding)
|
if (m != LH_FIRST(d->binding))
|
||||||
putchar(',');
|
putchar(',');
|
||||||
print_member(m);
|
print_member(m);
|
||||||
}
|
}
|
||||||
@@ -442,8 +439,8 @@ print_alias(v1, v2)
|
|||||||
(void) printf("Runas_Alias\t%s = ", a->name);
|
(void) printf("Runas_Alias\t%s = ", a->name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (m = a->first_member; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(a->members, m) {
|
||||||
if (m != a->first_member)
|
if (m != LH_FIRST(a->members))
|
||||||
fputs(", ", stdout);
|
fputs(", ", stdout);
|
||||||
if (m->type == COMMAND) {
|
if (m->type == COMMAND) {
|
||||||
c = (struct sudo_command *) m->name;
|
c = (struct sudo_command *) m->name;
|
||||||
@@ -468,20 +465,20 @@ print_privilege(priv)
|
|||||||
for (p = priv; p != NULL; p = p->next) {
|
for (p = priv; p != NULL; p = p->next) {
|
||||||
if (p != priv)
|
if (p != priv)
|
||||||
fputs(" : ", stdout);
|
fputs(" : ", stdout);
|
||||||
for (m = p->hostlist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(p->hostlist, m) {
|
||||||
if (m != p->hostlist)
|
if (m != LH_FIRST(p->hostlist))
|
||||||
fputs(", ", stdout);
|
fputs(", ", stdout);
|
||||||
print_member(m);
|
print_member(m);
|
||||||
}
|
}
|
||||||
fputs(" = ", stdout);
|
fputs(" = ", stdout);
|
||||||
tags.nopasswd = tags.noexec = UNSPEC;
|
tags.nopasswd = tags.noexec = UNSPEC;
|
||||||
for (cs = p->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(p->cmndlist, cs) {
|
||||||
if (cs != p->cmndlist)
|
if (cs != LH_FIRST(p->cmndlist))
|
||||||
fputs(", ", stdout);
|
fputs(", ", stdout);
|
||||||
if (cs->runaslist) {
|
if (!LH_EMPTY(cs->runaslist)) {
|
||||||
fputs("(", stdout);
|
fputs("(", stdout);
|
||||||
for (m = cs->runaslist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(cs->runaslist, m) {
|
||||||
if (m != cs->runaslist)
|
if (m != LH_FIRST(cs->runaslist))
|
||||||
fputs(", ", stdout);
|
fputs(", ", stdout);
|
||||||
print_member(m);
|
print_member(m);
|
||||||
}
|
}
|
||||||
@@ -503,14 +500,14 @@ print_userspecs()
|
|||||||
struct member *m;
|
struct member *m;
|
||||||
struct userspec *us;
|
struct userspec *us;
|
||||||
|
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
for (m = us->user; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(us->users, m) {
|
||||||
if (m != us->user)
|
if (m != LH_FIRST(us->users))
|
||||||
fputs(", ", stdout);
|
fputs(", ", stdout);
|
||||||
print_member(m);
|
print_member(m);
|
||||||
}
|
}
|
||||||
putchar('\t');
|
putchar('\t');
|
||||||
print_privilege(us->privileges);
|
print_privilege(us->privileges.first); /* XXX */
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
visudo.c
44
visudo.c
@@ -128,9 +128,6 @@ extern int errorlineno, parse_error;
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
extern struct defaults *defaults;
|
|
||||||
extern struct userspec *userspecs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals
|
* Globals
|
||||||
*/
|
*/
|
||||||
@@ -215,8 +212,8 @@ main(argc, argv)
|
|||||||
setup_signals();
|
setup_signals();
|
||||||
|
|
||||||
/* Edit the sudoers file(s) */
|
/* Edit the sudoers file(s) */
|
||||||
for (sp = sudoerslist.first; sp != NULL; sp = sp->next) {
|
LH_FOREACH_FWD(sudoerslist, sp) {
|
||||||
if (sp != sudoerslist.first) {
|
if (sp != LH_FIRST(sudoerslist)) {
|
||||||
printf("press return to edit %s: ", sp->path);
|
printf("press return to edit %s: ", sp->path);
|
||||||
while ((ch = getchar()) != EOF && ch != '\n')
|
while ((ch = getchar()) != EOF && ch != '\n')
|
||||||
continue;
|
continue;
|
||||||
@@ -228,7 +225,7 @@ main(argc, argv)
|
|||||||
reparse_sudoers(editor, args, strict, quiet);
|
reparse_sudoers(editor, args, strict, quiet);
|
||||||
|
|
||||||
/* Install the sudoers temp files. */
|
/* Install the sudoers temp files. */
|
||||||
for (sp = sudoerslist.first; sp != NULL; sp = sp->next) {
|
LH_FOREACH_FWD(sudoerslist, sp) {
|
||||||
if (!sp->modified)
|
if (!sp->modified)
|
||||||
(void) unlink(sp->tpath);
|
(void) unlink(sp->tpath);
|
||||||
else
|
else
|
||||||
@@ -403,8 +400,8 @@ reparse_sudoers(editor, args, strict, quiet)
|
|||||||
* Parse the edited sudoers files and do sanity checking
|
* Parse the edited sudoers files and do sanity checking
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
sp = sudoerslist.first;
|
sp = LH_FIRST(sudoerslist);
|
||||||
last = sudoerslist.last;
|
last = LH_LAST(sudoerslist);
|
||||||
fp = fopen(sp->tpath, "r+");
|
fp = fopen(sp->tpath, "r+");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
errorx(1, "can't re-open temporary file (%s), %s unchanged.",
|
errorx(1, "can't re-open temporary file (%s), %s unchanged.",
|
||||||
@@ -440,7 +437,7 @@ reparse_sudoers(editor, args, strict, quiet)
|
|||||||
}
|
}
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
/* Edit file with the parse error */
|
/* Edit file with the parse error */
|
||||||
for (sp = sudoerslist.first; sp != NULL; sp = sp->next) {
|
LH_FOREACH_FWD(sudoerslist, sp) {
|
||||||
if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) {
|
if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) {
|
||||||
edit_sudoers(sp, editor, args, errorlineno);
|
edit_sudoers(sp, editor, args, errorlineno);
|
||||||
break;
|
break;
|
||||||
@@ -711,7 +708,7 @@ open_sudoers(path, keepopen)
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
/* Check for existing entry */
|
/* Check for existing entry */
|
||||||
for (entry = sudoerslist.first; entry != NULL; entry = entry->next) {
|
LH_FOREACH_FWD(sudoerslist, entry) {
|
||||||
if (strcmp(path, entry->path) == 0)
|
if (strcmp(path, entry->path) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -731,6 +728,7 @@ open_sudoers(path, keepopen)
|
|||||||
errorx(1, "%s busy, try again later", entry->path);
|
errorx(1, "%s busy, try again later", entry->path);
|
||||||
if ((fp = fdopen(entry->fd, "r")) == NULL)
|
if ((fp = fdopen(entry->fd, "r")) == NULL)
|
||||||
error(1, "%s", entry->path);
|
error(1, "%s", entry->path);
|
||||||
|
/* XXX - macro here? */
|
||||||
if (sudoerslist.last == NULL)
|
if (sudoerslist.last == NULL)
|
||||||
sudoerslist.first = sudoerslist.last = entry;
|
sudoerslist.first = sudoerslist.last = entry;
|
||||||
else {
|
else {
|
||||||
@@ -888,8 +886,8 @@ check_aliases(strict)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/* Forward check. */
|
/* Forward check. */
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
for (m = us->user; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(us->users, m) {
|
||||||
if (m->type == USERALIAS) {
|
if (m->type == USERALIAS) {
|
||||||
if (find_alias(m->name, m->type) == NULL) {
|
if (find_alias(m->name, m->type) == NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -899,8 +897,8 @@ check_aliases(strict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
for (m = priv->hostlist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(priv->hostlist, m) {
|
||||||
if (m->type == HOSTALIAS) {
|
if (m->type == HOSTALIAS) {
|
||||||
if (find_alias(m->name, m->type) == NULL) {
|
if (find_alias(m->name, m->type) == NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -910,8 +908,8 @@ check_aliases(strict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
for (m = cs->runaslist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(cs->runaslist, m) {
|
||||||
if (m->type == RUNASALIAS) {
|
if (m->type == RUNASALIAS) {
|
||||||
if (find_alias(m->name, m->type) == NULL) {
|
if (find_alias(m->name, m->type) == NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -934,18 +932,18 @@ check_aliases(strict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reverse check (destructive) */
|
/* Reverse check (destructive) */
|
||||||
for (us = userspecs; us != NULL; us = us->next) {
|
LH_FOREACH_FWD(userspecs, us) {
|
||||||
for (m = us->user; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(us->users, m) {
|
||||||
if (m->type == USERALIAS)
|
if (m->type == USERALIAS)
|
||||||
(void) alias_remove(m->name, m->type);
|
(void) alias_remove(m->name, m->type);
|
||||||
}
|
}
|
||||||
for (priv = us->privileges; priv != NULL; priv = priv->next) {
|
LH_FOREACH_FWD(us->privileges, priv) {
|
||||||
for (m = priv->hostlist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(priv->hostlist, m) {
|
||||||
if (m->type == HOSTALIAS)
|
if (m->type == HOSTALIAS)
|
||||||
(void) alias_remove(m->name, m->type);
|
(void) alias_remove(m->name, m->type);
|
||||||
}
|
}
|
||||||
for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
|
LH_FOREACH_FWD(priv->cmndlist, cs) {
|
||||||
for (m = cs->runaslist; m != NULL; m = m->next) {
|
LH_FOREACH_FWD(cs->runaslist, m) {
|
||||||
if (m->type == RUNASALIAS)
|
if (m->type == RUNASALIAS)
|
||||||
(void) alias_remove(m->name, m->type);
|
(void) alias_remove(m->name, m->type);
|
||||||
}
|
}
|
||||||
@@ -985,7 +983,7 @@ cleanup(gotsignal)
|
|||||||
{
|
{
|
||||||
struct sudoersfile *sp;
|
struct sudoersfile *sp;
|
||||||
|
|
||||||
for (sp = sudoerslist.first; sp != NULL; sp = sp->next) {
|
LH_FOREACH_FWD(sudoerslist, sp) {
|
||||||
if (sp->tpath != NULL)
|
if (sp->tpath != NULL)
|
||||||
(void) unlink(sp->tpath);
|
(void) unlink(sp->tpath);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user