auth/sudo_auth.c
HDRS = compat.h def_data.h defaults.h error.h ins_2001.h ins_classic.h \
- ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h logging.h parse.h \
- sudo.h gram.h version.h auth/sudo_auth.h emul/fnmatch.h emul/utime.h \
- redblack.h
+ ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h list.h \
+ logging.h parse.h sudo.h gram.h version.h auth/sudo_auth.h \
+ emul/fnmatch.h emul/utime.h redblack.h
AUTH_OBJS = sudo_auth.o @AUTH_OBJS@
# Note: gram.o must come first here
-COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o match.o toke.o \
- redblack.o zero_bytes.o
+COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o list.o match.o \
+ toke.o redblack.o zero_bytes.o
SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ check.o env.o \
getspwuid.o gettime.o goodpath.o fileops.o find_path.o \
@DEV@ perl $(srcdir)/mkdefaults -o def_data $(srcdir)/def_data.in
# Dependencies (not counting auth functions)
-alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/redblack.h
+alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/redblack.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c
alloc.o: $(srcdir)/alloc.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/glob.c
goodpath.o: $(srcdir)/goodpath.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/goodpath.c
-gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h
+gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/gram.c
interfaces.o: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/interfaces.c
-ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h
- $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c
lbuf.o: $(srcdir)/lbuf.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/lbuf.c
+ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c
+list.o: $(srcdir)/list.c $(SUDODEP)
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/list.c
logging.o: $(srcdir)/logging.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/logging.c
-match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/interfaces.h $(devdir)/gram.h
+match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/match.c
memrchr.o: $(srcdir)/memrchr.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/memrchr.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mkstemp.c
mon_solaris.o: $(srcdir)/mon_solaris.c $(SUDODEP) $(srcdir)/mon_solaris.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mon_solaris.c
-parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h
+parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse.c
pwutil.o: $(srcdir)/pwutil.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_edit.c
sudo_noexec.o: $(srcdir)/sudo_noexec.c $(srcdir)/compat.h config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c
-testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/interfaces.h $(devdir)/gram.h
+testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c
tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c
-toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(devdir)/gram.h
+toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke.c
tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tsgetgrpw.c
a = emalloc(sizeof(*a));
a->name = name;
a->type = type;
- LIST2HEAD(a->members, members);
+ list2head(&a->members, members);
if (rbinsert(aliases, a)) {
efree(a);
snprintf(errbuf, sizeof(errbuf), "Alias `%s' already defined", name);
{
struct defaults *def;
- LH_FOREACH_FWD(&defaults, def) {
+ lh_foreach_fwd(&defaults, def) {
if (skip_cmnd == (def->type == DEFAULTS_CMND))
continue;
switch (def->type) {
defaults_list : defaults_entry
| defaults_list ',' defaults_entry {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
privileges : privilege
| privileges ':' privilege {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
/* propagate tags and runas lists */
tags.nopasswd = tags.noexec = tags.setenv = UNSPEC;
for (cs = $3; cs != NULL; cs = cs->next) {
- if (LH_EMPTY(&cs->runaslist) &&
- !LH_EMPTY(&cs->prev->runaslist)) {
+ if (lh_empty(&cs->runaslist) &&
+ !lh_empty(&cs->prev->runaslist)) {
memcpy(&cs->runaslist, &cs->prev->runaslist,
sizeof(cs->runaslist));
}
cs->tags.setenv = tags.setenv;
memcpy(&tags, &cs->tags, sizeof(tags));
}
- LIST2HEAD(p->hostlist, $1);
- LIST2HEAD(p->cmndlist, $3);
+ list2head(&p->hostlist, $1);
+ list2head(&p->cmndlist, $3);
p->prev = p;
p->next = NULL;
$$ = p;
cmndspeclist : cmndspec
| cmndspeclist ',' cmndspec {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
cmndspec : runasspec cmndtag opcmnd {
struct cmndspec *cs = emalloc(sizeof(*cs));
- LIST2HEAD(cs->runaslist, $1);
+ list2head(&cs->runaslist, $1);
cs->tags = $2;
cs->cmnd = $3;
cs->prev = cs;
runaslist : oprunasuser
| runaslist ',' oprunasuser {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
hostlist : ophost
| hostlist ',' ophost {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
cmndlist : opcmnd
| cmndlist ',' opcmnd {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
userlist : opuser
| userlist ',' opuser {
- LIST_APPEND($1, $3);
+ list_append($1, $3);
$$ = $1;
}
;
d = emalloc(sizeof(struct defaults));
d->var = var;
d->val = val;
- LH_INIT(&d->binding);
+ lh_init(&d->binding);
d->type = 0;
d->op = op;
d->prev = d;
*/
for (d = defs; d != NULL; d = d->next) {
d->type = type;
- LIST2HEAD(d->binding, binding);
+ list2head(&d->binding, binding);
}
- HEAD_APPEND(defaults, defs);
+ lh_append(&defaults, defs);
}
/*
struct userspec *u;
u = emalloc(sizeof(*u));
- LIST2HEAD(u->users, members);
- LIST2HEAD(u->privileges, privs);
+ list2head(&u->users, members);
+ list2head(&u->privileges, privs);
u->prev = u;
u->next = NULL;
- HEAD_APPEND(userspecs, u);
+ lh_append(&userspecs, u);
}
/*
struct privilege *priv;
struct cmndspec *cs;
- while ((us = LH_LAST(&userspecs)) != NULL) {
- LH_POP(&userspecs);
- while ((m = LH_LAST(&us->users)) != NULL) {
- LH_POP(&us->users);
+ while ((us = lh_pop(&userspecs)) != NULL) {
+ while ((m = lh_pop(&us->users)) != NULL) {
efree(m->name);
efree(m);
}
- while ((priv = LH_LAST(&us->privileges)) != NULL) {
- LH_POP(&us->privileges);
- while ((m = LH_LAST(&priv->hostlist)) != NULL) {
- LH_POP(&priv->hostlist);
+ while ((priv = lh_pop(&us->privileges)) != NULL) {
+ while ((m = lh_pop(&priv->hostlist)) != NULL) {
efree(m->name);
efree(m);
}
- while ((cs = LH_LAST(&priv->cmndlist)) != NULL) {
- LH_POP(&priv->cmndlist);
- while ((m = LH_LAST(&cs->runaslist)) != NULL) {
- LH_POP(&cs->runaslist);
+ while ((cs = lh_pop(&priv->cmndlist)) != NULL) {
+ while ((m = lh_pop(&cs->runaslist)) != NULL) {
efree(m->name);
efree(m);
}
efree(priv);
}
}
- LH_INIT(&userspecs);
+ lh_init(&userspecs);
lastbinding = NULL;
- while ((d = LH_LAST(&defaults)) != NULL) {
- LH_POP(&defaults);
- if (LH_FIRST(&d->binding) != lastbinding) {
- lastbinding = LH_FIRST(&d->binding);
- while ((m = LH_LAST(&d->binding)) != NULL) {
- LH_POP(&d->binding);
+ while ((d = lh_pop(&defaults)) != NULL) {
+ if (lh_pop(&d->binding) != lastbinding) {
+ while ((m = lh_pop(&d->binding)) != NULL) {
efree(m->name);
efree(m);
}
efree(d->val);
efree(d);
}
- LH_INIT(&defaults);
+ lh_init(&defaults);
init_aliases();
--- /dev/null
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+
+#include "sudo.h"
+#include "list.h"
+
+#ifndef lint
+__unused static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+struct list_proto {
+ struct list_proto *prev;
+ struct list_proto *next;
+};
+
+struct list_head_proto {
+ struct list_proto *first;
+ struct list_proto *last;
+};
+
+/*
+ * Pop the last element off the end of vh.
+ * Returns the popped element.
+ */
+VOID *
+lh_pop(vh)
+ VOID *vh;
+{
+ struct list_head_proto *h = (struct list_head_proto *)vh;
+ VOID *last = NULL;
+
+ if (!lh_empty(h)) {
+ last = (VOID *)h->last;
+ if (h->first == h->last) {
+ h->first = NULL;
+ h->last = NULL;
+ } else {
+ h->last = h->last->prev;
+ h->last->next = NULL;
+ }
+ }
+ return (last);
+}
+
+/*
+ * Convert from a semi-circle queue to normal doubly-linked list
+ * with a head node.
+ */
+void
+list2head(vh, vl)
+ VOID *vh;
+ VOID *vl;
+{
+ struct list_head_proto *h = (struct list_head_proto *)vh;
+ struct list_proto *l = (struct list_proto *)vl;
+
+ if (l != NULL) {
+ h->first = l;
+ h->last = l->prev; /* l->prev points to the last member of l */
+ l->prev = NULL; /* zero last ptr now that we have a head */
+ } else {
+ h->first = NULL;
+ h->last = NULL;
+ }
+}
+
+/*
+ * Append one queue (or single entry) to another using the
+ * circular properties of the prev pointer to simplify the logic.
+ */
+void
+list_append(vl1, vl2)
+ VOID *vl1;
+ VOID *vl2;
+{
+ struct list_proto *l1 = (struct list_proto *)vl1;
+ struct list_proto *l2 = (struct list_proto *)vl2;
+ VOID *tail = l2->prev;
+
+ l1->prev->next = l2;
+ l2->prev = l1->prev;
+ l1->prev = tail;
+}
+
+/*
+ * Append the list of entries to the head node and convert
+ * e from a semi-circle queue to normal doubly-linked list.
+ */
+void
+lh_append(vh, vl)
+ VOID *vh;
+ VOID *vl;
+{
+ struct list_head_proto *h = (struct list_head_proto *)vh;
+ struct list_proto *l = (struct list_proto *)vl;
+ VOID *tail = l->prev;
+
+ if (h->first == NULL)
+ h->first = l;
+ else
+ h->last->next = l;
+ l->prev = h->last;
+ h->last = tail;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Sudo$
+ */
+
+#ifndef _SUDO_LIST_H
+#define _SUDO_LIST_H
+
+/*
+ * Convenience macro for declaring a list head.
+ */
+#ifdef __STDC__
+#define LH_DECLARE(n) \
+struct n##_list { \
+ struct n *first; \
+ struct n *last; \
+};
+#else
+#define LH_DECLARE(n) \
+struct n/**/_list { \
+ struct n *first; \
+ struct n *last; \
+};
+#endif
+
+/*
+ * Foreach loops: forward and reverse
+ */
+#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)
+
+/*
+ * Init a list head.
+ */
+#undef lh_init
+#define lh_init(h) do { \
+ (h)->first = NULL; \
+ (h)->last = NULL; \
+} while (0)
+
+/*
+ * Simple macros to avoid exposing first/last and prev/next.
+ */
+#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)
+
+/*
+ * Prototypes for list.c
+ */
+VOID *lh_pop __P((VOID *));
+void lh_append __P((VOID *, VOID *));
+void list_append __P((VOID *, VOID *));
+void list2head __P((VOID *, VOID *));
+
+#endif /* _SUDO_LIST_H */
struct alias *a;
int rval, matched = UNSPEC;
- LH_FOREACH_REV(list, m) {
+ lh_foreach_rev(list, m) {
switch (m->type) {
case ALL:
matched = !m->negated;
if (list == NULL)
return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
- LH_FOREACH_REV(list, m) {
+ lh_foreach_rev(list, m) {
switch (m->type) {
case ALL:
matched = !m->negated;
struct alias *a;
int rval, matched = UNSPEC;
- LH_FOREACH_REV(list, m) {
+ lh_foreach_rev(list, m) {
switch (m->type) {
case ALL:
matched = !m->negated;
struct member *m;
int rval, matched = UNSPEC;
- LH_FOREACH_REV(list, m) {
+ lh_foreach_rev(list, m) {
rval = cmnd_matches(m);
if (rval != UNSPEC) {
matched = m->negated ? !rval : rval;
CLR(validated, FLAG_NO_USER);
CLR(validated, FLAG_NO_HOST);
match = DENY;
- LH_FOREACH_REV(&userspecs, us) {
+ lh_foreach_rev(&userspecs, us) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
- LH_FOREACH_REV(&us->privileges, priv) {
+ lh_foreach_rev(&us->privileges, priv) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
- LH_FOREACH_REV(&priv->cmndlist, cs) {
+ lh_foreach_rev(&priv->cmndlist, cs) {
/* Only check the command when listing another user. */
if (user_uid == 0 || list_pw == NULL ||
user_uid == list_pw->pw_uid ||
set_perms(PERM_RUNAS);
match = UNSPEC;
- LH_FOREACH_REV(&userspecs, us) {
+ lh_foreach_rev(&userspecs, us) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
CLR(validated, FLAG_NO_USER);
- LH_FOREACH_REV(&us->privileges, priv) {
+ lh_foreach_rev(&us->privileges, priv) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match == ALLOW)
CLR(validated, FLAG_NO_HOST);
else
continue;
runas = NULL;
- LH_FOREACH_REV(&priv->cmndlist, cs) {
- if (!LH_EMPTY(&cs->runaslist))
+ lh_foreach_rev(&priv->cmndlist, cs) {
+ if (!lh_empty(&cs->runaslist))
runas = &cs->runaslist;
runas_match = runaslist_matches(runas);
if (runas_match == ALLOW) {
printf("User %s may run the following commands on this host:\n",
pw->pw_name);
- LH_FOREACH_FWD(&userspecs, us) {
+ lh_foreach_fwd(&userspecs, us) {
/* XXX - why only check the first privilege here? */
if (userlist_matches(pw, &us->users) != ALLOW ||
hostlist_matches(&us->privileges.first->hostlist) != ALLOW)
continue;
- LH_FOREACH_FWD(&us->privileges, priv) {
+ lh_foreach_fwd(&us->privileges, priv) {
tags.noexec = def_noexec;
tags.setenv = def_setenv;
tags.nopasswd = !def_authenticate;
lbuf_append(&lbuf, " ", NULL);
- LH_FOREACH_FWD(&priv->cmndlist, cs) {
- if (cs != LH_FIRST(&priv->cmndlist))
+ lh_foreach_fwd(&priv->cmndlist, cs) {
+ if (cs != lh_first(&priv->cmndlist))
lbuf_append(&lbuf, ", ", NULL);
lbuf_append(&lbuf, "(", NULL);
- if (!LH_EMPTY(&cs->runaslist)) {
- LH_FOREACH_FWD(&cs->runaslist, m) {
- if (m != LH_FIRST(&cs->runaslist))
+ if (!lh_empty(&cs->runaslist)) {
+ lh_foreach_fwd(&cs->runaslist, m) {
+ if (m != lh_first(&cs->runaslist))
lbuf_append(&lbuf, ", ", NULL);
print_member(&lbuf, m->name, m->type, m->negated,
RUNASALIAS);
lbuf_init(&lbuf, NULL, 4, 0);
- LH_FOREACH_FWD(&defaults, d) {
+ lh_foreach_fwd(&defaults, d) {
switch (d->type) {
case DEFAULTS_HOST:
if (hostlist_matches(&d->binding) != ALLOW)
}
lbuf_init(&lbuf, NULL, 4, 0);
printf("Per-%s Defaults entries:\n", dname);
- LH_FOREACH_FWD(&defaults, d) {
+ lh_foreach_fwd(&defaults, d) {
if (d->type != dtype)
continue;
- if (binding != LH_FIRST(&d->binding)) {
- binding = LH_FIRST(&d->binding);
+ if (binding != lh_first(&d->binding)) {
+ binding = lh_first(&d->binding);
lbuf_append(&lbuf, " Defaults", dsep, NULL);
for (m = binding; m != NULL; m = m->next) {
if (m != binding)
#endif
if (rval != 0 && !def_ignore_local_sudoers) {
match = NULL;
- LH_FOREACH_REV(&userspecs, us) {
+ lh_foreach_rev(&userspecs, us) {
if (userlist_matches(pw, &us->users) != ALLOW)
continue;
- LH_FOREACH_REV(&us->privileges, priv) {
+ lh_foreach_rev(&us->privileges, priv) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match != ALLOW)
continue;
runas = NULL;
- LH_FOREACH_REV(&priv->cmndlist, cs) {
- if (!LH_EMPTY(&cs->runaslist) != NULL)
+ lh_foreach_rev(&priv->cmndlist, cs) {
+ if (!lh_empty(&cs->runaslist) != NULL)
runas = &cs->runaslist;
runas_match = runaslist_matches(runas);
if (runas_match == ALLOW) {
break;
case ALIAS:
if ((a = find_alias(name, alias_type)) != NULL) {
- LH_FOREACH_FWD(&a->members, m) {
- if (m != LH_FIRST(&a->members))
+ lh_foreach_fwd(&a->members, m) {
+ if (m != lh_first(&a->members))
lbuf_append(lbuf, ", ", NULL);
print_member(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, alias_type);
#ifndef _SUDO_PARSE_H
#define _SUDO_PARSE_H
+#include "list.h"
+
#undef ALLOW
#define ALLOW 1
#undef DENY
* to trivally append sub-lists. In addition, the prev pointer is always
* valid (even if it points to itself). Unlike a circle queue, the next
* pointer of the last entry is NULL and does not point back to the head.
+ *
+ * Note that each list struct must contain a "prev" and "next" pointer as
+ * the first two members of the struct (in that order).
*/
/*
* 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;
-};
+LH_DECLARE(defaults)
+LH_DECLARE(userspec)
+LH_DECLARE(member)
+LH_DECLARE(privilege)
+LH_DECLARE(cmndspec)
/*
* Structure describing a user specification and list thereof.
*/
struct userspec {
+ struct userspec *prev, *next;
struct member_list users; /* list of users */
struct privilege_list privileges; /* list of privileges */
- struct userspec *prev, *next;
};
/*
* Structure describing a privilege specification.
*/
struct privilege {
+ struct privilege *prev, *next;
struct member_list hostlist; /* list of hosts */
struct cmndspec_list cmndlist; /* list of Cmnd_Specs */
- struct privilege *prev, *next;
};
/*
* Structure describing a linked list of Cmnd_Specs.
*/
struct cmndspec {
+ struct cmndspec *prev, *next;
struct member_list runaslist; /* list of runas users */
struct member *cmnd; /* command to allow/deny */
struct cmndtag tags; /* tag specificaion */
- struct cmndspec *prev, *next;
};
/*
* Generic structure to hold users, hosts, commands.
*/
struct member {
+ struct member *prev, *next;
char *name; /* member name */
short type; /* type (see gram.h) */
short negated; /* negated via '!'? */
- struct member *prev, *next;
};
/*
* Structure describing a Defaults entry and a list thereof.
*/
struct defaults {
+ struct defaults *prev, *next;
char *var; /* variable name */
char *val; /* variable value */
struct member_list binding; /* user/host/runas binding */
int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
int op; /* TRUE, FALSE, '+', '-' */
- struct defaults *prev, *next;
};
-/*
- * Append one queue (or single entry) to another using the
- * circular properties of the prev pointer to simplify the logic.
- */
-#undef LIST_APPEND
-#define LIST_APPEND(h, e) do { \
- void *_tail = (e)->prev; \
- (h)->prev->next = (e); \
- (e)->prev = (h)->prev; \
- (h)->prev = _tail; \
-} 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.
*/
/* This loop must match the one in sudoers_lookup() */
printf("\nEntries for user %s:\n", user_name);
matched = UNSPEC;
- LH_FOREACH_REV(&userspecs, us) {
+ lh_foreach_rev(&userspecs, us) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
- LH_FOREACH_REV(&us->privileges, priv) {
+ lh_foreach_rev(&us->privileges, priv) {
putchar('\n');
print_privilege(priv); /* XXX */
putchar('\n');
if (hostlist_matches(&priv->hostlist) == ALLOW) {
puts("\thost matched");
runas = NULL;
- LH_FOREACH_REV(&priv->cmndlist, cs) {
- if (!LH_EMPTY(&cs->runaslist))
+ lh_foreach_rev(&priv->cmndlist, cs) {
+ if (!lh_empty(&cs->runaslist))
runas = &cs->runaslist;
if (runaslist_matches(runas) == ALLOW) {
puts("\trunas matched");
struct defaults *d;
struct member *m;
- LH_FOREACH_FWD(&defaults, d) {
+ lh_foreach_fwd(&defaults, d) {
(void) fputs("Defaults", stdout);
switch (d->type) {
case DEFAULTS_HOST:
putchar('!');
break;
}
- LH_FOREACH_FWD(&d->binding, m) {
- if (m != LH_FIRST(&d->binding))
+ lh_foreach_fwd(&d->binding, m) {
+ if (m != lh_first(&d->binding))
putchar(',');
print_member(m);
}
(void) printf("Runas_Alias\t%s = ", a->name);
break;
}
- LH_FOREACH_FWD(&a->members, m) {
- if (m != LH_FIRST(&a->members))
+ lh_foreach_fwd(&a->members, m) {
+ if (m != lh_first(&a->members))
fputs(", ", stdout);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
for (p = priv; p != NULL; p = p->next) {
if (p != priv)
fputs(" : ", stdout);
- LH_FOREACH_FWD(&p->hostlist, m) {
- if (m != LH_FIRST(&p->hostlist))
+ lh_foreach_fwd(&p->hostlist, m) {
+ if (m != lh_first(&p->hostlist))
fputs(", ", stdout);
print_member(m);
}
fputs(" = ", stdout);
tags.nopasswd = tags.noexec = UNSPEC;
- LH_FOREACH_FWD(&p->cmndlist, cs) {
- if (cs != LH_FIRST(&p->cmndlist))
+ lh_foreach_fwd(&p->cmndlist, cs) {
+ if (cs != lh_first(&p->cmndlist))
fputs(", ", stdout);
- if (!LH_EMPTY(&cs->runaslist)) {
+ if (!lh_empty(&cs->runaslist)) {
fputs("(", stdout);
- LH_FOREACH_FWD(&cs->runaslist, m) {
- if (m != LH_FIRST(&cs->runaslist))
+ lh_foreach_fwd(&cs->runaslist, m) {
+ if (m != lh_first(&cs->runaslist))
fputs(", ", stdout);
print_member(m);
}
struct member *m;
struct userspec *us;
- LH_FOREACH_FWD(&userspecs, us) {
- LH_FOREACH_FWD(&us->users, m) {
- if (m != LH_FIRST(&us->users))
+ lh_foreach_fwd(&userspecs, us) {
+ lh_foreach_fwd(&us->users, m) {
+ if (m != lh_first(&us->users))
fputs(", ", stdout);
print_member(m);
}
setup_signals();
/* Edit the sudoers file(s) */
- LH_FOREACH_FWD(&sudoerslist, sp) {
- if (sp != LH_FIRST(&sudoerslist)) {
+ lh_foreach_fwd(&sudoerslist, sp) {
+ if (sp != lh_first(&sudoerslist)) {
printf("press return to edit %s: ", sp->path);
while ((ch = getchar()) != EOF && ch != '\n')
continue;
reparse_sudoers(editor, args, strict, quiet);
/* Install the sudoers temp files. */
- LH_FOREACH_FWD(&sudoerslist, sp) {
+ lh_foreach_fwd(&sudoerslist, sp) {
if (!sp->modified)
(void) unlink(sp->tpath);
else
* Parse the edited sudoers files and do sanity checking
*/
do {
- sp = LH_FIRST(&sudoerslist);
- last = LH_LAST(&sudoerslist);
+ sp = lh_first(&sudoerslist);
+ last = lh_last(&sudoerslist);
fp = fopen(sp->tpath, "r+");
if (fp == NULL)
errorx(1, "can't re-open temporary file (%s), %s unchanged.",
}
if (parse_error) {
/* Edit file with the parse error */
- LH_FOREACH_FWD(&sudoerslist, sp) {
+ lh_foreach_fwd(&sudoerslist, sp) {
if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) {
edit_sudoers(sp, editor, args, errorlineno);
break;
FILE *fp;
/* Check for existing entry */
- LH_FOREACH_FWD(&sudoerslist, entry) {
+ lh_foreach_fwd(&sudoerslist, entry) {
if (strcmp(path, entry->path) == 0)
break;
}
int error = 0;
/* Forward check. */
- LH_FOREACH_FWD(&userspecs, us) {
- LH_FOREACH_FWD(&us->users, m) {
+ lh_foreach_fwd(&userspecs, us) {
+ lh_foreach_fwd(&us->users, m) {
if (m->type == USERALIAS) {
if (find_alias(m->name, m->type) == NULL) {
fprintf(stderr,
}
}
}
- LH_FOREACH_FWD(&us->privileges, priv) {
- LH_FOREACH_FWD(&priv->hostlist, m) {
+ lh_foreach_fwd(&us->privileges, priv) {
+ lh_foreach_fwd(&priv->hostlist, m) {
if (m->type == HOSTALIAS) {
if (find_alias(m->name, m->type) == NULL) {
fprintf(stderr,
}
}
}
- LH_FOREACH_FWD(&priv->cmndlist, cs) {
- LH_FOREACH_FWD(&cs->runaslist, m) {
+ lh_foreach_fwd(&priv->cmndlist, cs) {
+ lh_foreach_fwd(&cs->runaslist, m) {
if (m->type == RUNASALIAS) {
if (find_alias(m->name, m->type) == NULL) {
fprintf(stderr,
}
/* Reverse check (destructive) */
- LH_FOREACH_FWD(&userspecs, us) {
- LH_FOREACH_FWD(&us->users, m) {
+ lh_foreach_fwd(&userspecs, us) {
+ lh_foreach_fwd(&us->users, m) {
if (m->type == USERALIAS)
(void) alias_remove(m->name, m->type);
}
- LH_FOREACH_FWD(&us->privileges, priv) {
- LH_FOREACH_FWD(&priv->hostlist, m) {
+ lh_foreach_fwd(&us->privileges, priv) {
+ lh_foreach_fwd(&priv->hostlist, m) {
if (m->type == HOSTALIAS)
(void) alias_remove(m->name, m->type);
}
- LH_FOREACH_FWD(&priv->cmndlist, cs) {
- LH_FOREACH_FWD(&cs->runaslist, m) {
+ lh_foreach_fwd(&priv->cmndlist, cs) {
+ lh_foreach_fwd(&cs->runaslist, m) {
if (m->type == RUNASALIAS)
(void) alias_remove(m->name, m->type);
}
{
struct sudoersfile *sp;
- LH_FOREACH_FWD(&sudoerslist, sp) {
+ lh_foreach_fwd(&sudoerslist, sp) {
if (sp->tpath != NULL)
(void) unlink(sp->tpath);
}