Add "headless" tail queues and use them in place of the semi-circular

lists in sudoers.  Once the headless tail queue is built up it is
converted to a normal TAILQ.  This removes the last consumer of
list.c and list.h so those can now be removed.
This commit is contained in:
Todd C. Miller
2013-10-22 09:08:38 -06:00
parent f85106ea67
commit b38d253e98
17 changed files with 841 additions and 725 deletions

View File

@@ -20,7 +20,6 @@ common/fileops.c
common/fmt_string.c
common/gidlist.c
common/lbuf.c
common/list.c
common/regress/sudo_conf/conf_test.c
common/regress/sudo_conf/test1.in
common/regress/sudo_conf/test1.out.ok
@@ -47,6 +46,7 @@ common/regress/sudo_parseln/test5.in
common/regress/sudo_parseln/test5.out.ok
common/regress/sudo_parseln/test6.in
common/regress/sudo_parseln/test6.out.ok
common/regress/tailq/hltq_test.c
common/secure_path.c
common/setgroups.c
common/sudo_conf.c
@@ -145,7 +145,6 @@ include/fatal.h
include/fileops.h
include/gettext.h
include/lbuf.h
include/list.h
include/missing.h
include/queue.h
include/secure_path.h

View File

@@ -55,7 +55,7 @@ SSP_CFLAGS = @SSP_CFLAGS@
SSP_LDFLAGS = @SSP_LDFLAGS@
# Regression tests
TEST_PROGS = conf_test parseln_test
TEST_PROGS = conf_test parseln_test hltq_test
TEST_LIBS = @LIBS@ @LIBINTL@ ../compat/libreplace.la
TEST_LDFLAGS = @LDFLAGS@
@@ -67,7 +67,7 @@ DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\"
SHELL = @SHELL@
LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \
fmt_string.lo gidlist.lo lbuf.lo list.lo secure_path.lo \
fmt_string.lo gidlist.lo lbuf.lo secure_path.lo \
setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo term.lo \
ttysize.lo @COMMON_OBJS@
@@ -75,6 +75,8 @@ PARSELN_TEST_OBJS = parseln_test.lo
CONF_TEST_OBJS = conf_test.lo
HLTQ_TEST_OBJS = hltq_test.lo
all: libcommon.la
Makefile: $(srcdir)/Makefile.in
@@ -94,6 +96,9 @@ conf_test: $(CONF_TEST_OBJS) libcommon.la
parseln_test: $(PARSELN_TEST_OBJS) libcommon.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
hltq_test: $(HLTQ_TEST_OBJS) libcommon.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
pre-install:
install:
@@ -113,6 +118,12 @@ uninstall:
check: $(TEST_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
passed=0; failed=0; total=0; \
total=1; \
if ./hltq_test; then \
passed=`expr $$passed + 1`; \
else \
failed=`expr $$failed + 1`; \
fi; \
for dir in sudo_conf sudo_parseln; do \
mkdir -p regress/$$dir; \
for t in $(srcdir)/regress/$$dir/*.in; do \
@@ -203,13 +214,14 @@ gidlist.lo: $(srcdir)/gidlist.c $(top_builddir)/config.h $(incdir)/gettext.h \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
$(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/gidlist.c
hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
$(incdir)/fatal.h $(incdir)/queue.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/tailq/hltq_test.c
lbuf.lo: $(srcdir)/lbuf.c $(top_builddir)/config.h $(incdir)/missing.h \
$(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/lbuf.h \
$(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/lbuf.c
list.lo: $(srcdir)/list.c $(top_builddir)/config.h $(incdir)/missing.h \
$(incdir)/list.h $(incdir)/fatal.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/list.c
parseln_test.lo: $(srcdir)/regress/sudo_parseln/parseln_test.c \
$(top_builddir)/config.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/missing.h $(incdir)/fileops.h

View File

@@ -1,158 +0,0 @@
/*
* Copyright (c) 2007-2008, 2010-2012 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 "missing.h"
#include "list.h"
#ifdef DEBUG
# include "fatal.h"
#endif
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 *
tq_pop(void *vh)
{
struct list_head_proto *h = (struct list_head_proto *)vh;
void *last = NULL;
if (!tq_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
list2tq(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) {
#ifdef DEBUG
if (l->prev == NULL) {
warningx_nodebug("list2tq called with non-semicircular list");
abort();
}
#endif
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(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
* from a semi-circle queue to normal doubly-linked list.
*/
void
tq_append(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;
}
/*
* Remove element from the tail_queue
*/
void
tq_remove(void *vh, void *vl)
{
struct list_head_proto *h = (struct list_head_proto *)vh;
struct list_proto *l = (struct list_proto *)vl;
if (h->first == l && h->last == l) {
/* Single element in the list. */
h->first = NULL;
h->last = NULL;
} else {
/* At least two elements in the list. */
if (h->first == l) {
h->first = l->next;
h->first->prev = h->first;
} else if (h->last == l) {
h->last = l->prev;
h->last->next = NULL;
} else {
l->prev->next = l->next;
l->next->prev = l->prev;
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2013 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.
*/
#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 */
#ifdef HAVE_STRING_H
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
# include <memory.h>
# endif
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif
#include "missing.h"
#include "fatal.h"
#include "queue.h"
__dso_public int main(int argc, char *argv[]);
/*
* Note: HLTQ_ENTRY is intentionally in the middle of the struct
* to catch bad assumptions in the PREV/NEXT macros.
*/
struct test_data {
int a;
HLTQ_ENTRY(test_data) entries;
char b;
};
TAILQ_HEAD(test_data_list, test_data);
/*
* Simple tests for headless tail queue macros.
*/
int
main(int argc, char *argv[])
{
struct test_data d1, d2, d3;
struct test_data *hltq;
struct test_data_list tq;
int errors = 0;
/*
* Initialize three data elements and concatenate them in order.
*/
HLTQ_INIT(&d1, entries);
d1.a = 1;
d1.b = 'a';
if (HLTQ_FIRST(&d1) != &d1) {
warningx_nodebug("FAIL: HLTQ_FIRST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_FIRST(&d1), &d1);
errors++;
}
if (HLTQ_LAST(&d1, test_data, entries) != &d1) {
warningx_nodebug("FAIL: HLTQ_LAST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_LAST(&d1, test_data, entries), &d1);
errors++;
}
if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
warningx_nodebug("FAIL: HLTQ_PREV(1 entry) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
errors++;
}
HLTQ_INIT(&d2, entries);
d2.a = 2;
d2.b = 'b';
HLTQ_INIT(&d3, entries);
d3.a = 3;
d3.b = 'c';
HLTQ_CONCAT(&d1, &d2, entries);
HLTQ_CONCAT(&d1, &d3, entries);
hltq = &d1;
/*
* Verify that HLTQ_FIRST, HLTQ_LAST, HLTQ_NEXT, HLTQ_PREV
* work as expected.
*/
if (HLTQ_FIRST(hltq) != &d1) {
warningx_nodebug("FAIL: HLTQ_FIRST(3 entries) doesn't return first element: got %p, expected %p", HLTQ_FIRST(hltq), &d1);
errors++;
}
if (HLTQ_LAST(hltq, test_data, entries) != &d3) {
warningx_nodebug("FAIL: HLTQ_LAST(3 entries) doesn't return third element: got %p, expected %p", HLTQ_LAST(hltq, test_data, entries), &d3);
errors++;
}
if (HLTQ_NEXT(&d1, entries) != &d2) {
warningx_nodebug("FAIL: HLTQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", HLTQ_NEXT(&d1, entries), &d2);
errors++;
}
if (HLTQ_NEXT(&d2, entries) != &d3) {
warningx_nodebug("FAIL: HLTQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", HLTQ_NEXT(&d2, entries), &d3);
errors++;
}
if (HLTQ_NEXT(&d3, entries) != NULL) {
warningx_nodebug("FAIL: HLTQ_NEXT(&d3) doesn't return NULL: got %p", HLTQ_NEXT(&d3, entries));
errors++;
}
if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
warningx_nodebug("FAIL: HLTQ_PREV(&d1) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
errors++;
}
if (HLTQ_PREV(&d2, test_data, entries) != &d1) {
warningx_nodebug("FAIL: HLTQ_PREV(&d2) doesn't return &d1: got %p, expected %p", HLTQ_PREV(&d2, test_data, entries), &d1);
errors++;
}
if (HLTQ_PREV(&d3, test_data, entries) != &d2) {
warningx_nodebug("FAIL: HLTQ_PREV(&d3) doesn't return &d2: got %p, expected %p", HLTQ_PREV(&d3, test_data, entries), &d2);
errors++;
}
/* Test conversion to TAILQ. */
HLTQ_TO_TAILQ(&tq, hltq, entries);
if (TAILQ_FIRST(&tq) != &d1) {
warningx_nodebug("FAIL: TAILQ_FIRST(&tq) doesn't return first element: got %p, expected %p", TAILQ_FIRST(&tq), &d1);
errors++;
}
if (TAILQ_LAST(&tq, test_data_list) != &d3) {
warningx_nodebug("FAIL: TAILQ_LAST(&tq) doesn't return third element: got %p, expected %p", TAILQ_LAST(&tq, test_data_list), &d3);
errors++;
}
if (TAILQ_NEXT(&d1, entries) != &d2) {
warningx_nodebug("FAIL: TAILQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", TAILQ_NEXT(&d1, entries), &d2);
errors++;
}
if (TAILQ_NEXT(&d2, entries) != &d3) {
warningx_nodebug("FAIL: TAILQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", TAILQ_NEXT(&d2, entries), &d3);
errors++;
}
if (TAILQ_NEXT(&d3, entries) != NULL) {
warningx_nodebug("FAIL: TAILQ_NEXT(&d3) doesn't return NULL: got %p", TAILQ_NEXT(&d3, entries));
errors++;
}
if (TAILQ_PREV(&d1, test_data_list, entries) != NULL) {
warningx_nodebug("FAIL: TAILQ_PREV(&d1) doesn't return NULL: got %p", TAILQ_PREV(&d1, test_data_list, entries));
errors++;
}
if (TAILQ_PREV(&d2, test_data_list, entries) != &d1) {
warningx_nodebug("FAIL: TAILQ_PREV(&d2) doesn't return &d1: got %p, expected %p", TAILQ_PREV(&d2, test_data_list, entries), &d1);
errors++;
}
if (TAILQ_PREV(&d3, test_data_list, entries) != &d2) {
warningx_nodebug("FAIL: TAILQ_PREV(&d3) doesn't return &d2: got %p, expected %p", TAILQ_PREV(&d3, test_data_list, entries), &d2);
errors++;
}
exit(errors);
}
/* STUB */
void
warning_set_locale(void)
{
return;
}
/* STUB */
void
warning_restore_locale(void)
{
return;
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 2007, 2010 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.
*/
#ifndef _SUDO_LIST_H
#define _SUDO_LIST_H
/*
* Convenience macro for declaring a list head.
*/
#define TQ_DECLARE(n) \
struct n##_list { \
struct n *first; \
struct n *last; \
};
/*
* Foreach loops: forward and reverse
*/
#undef tq_foreach_fwd
#define tq_foreach_fwd(h, v) \
for ((v) = (h)->first; (v) != NULL; (v) = (v)->next)
#undef tq_foreach_rev
#define tq_foreach_rev(h, v) \
for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev)
/*
* Init a list head.
*/
#undef tq_init
#define tq_init(h) do { \
(h)->first = NULL; \
(h)->last = NULL; \
} while (0)
/*
* Simple macros to avoid exposing first/last and prev/next.
*/
#undef tq_empty
#define tq_empty(h) ((h)->first == NULL)
#undef tq_first
#define tq_first(h) ((h)->first)
#undef tq_last
#define tq_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 *tq_pop(void *);
void tq_append(void *, void *);
void tq_remove(void *, void *);
void list_append(void *, void *);
void list2tq(void *, void *);
#endif /* _SUDO_LIST_H */

View File

@@ -72,6 +72,13 @@
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A headless tail queue lacks a head structure, The first element acts
* as a de facto list head. It uses the same entry struct as a regular
* tail queue for easy conversion from headless to headful.
* It is capable of concatenating queues as well as individual elements.
* Traversing in reverse is more expensive due to lack of a list head.
* Note: elements must be initialized before use.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
@@ -712,4 +719,88 @@ struct { \
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
/*
* Headless Tail queue definitions.
*/
#undef HLTQ_ENTRY
#define HLTQ_ENTRY(type) TAILQ_ENTRY(type)
#undef HLTQ_INIT
#define HLTQ_INIT(entry, field) do { \
(entry)->field.tqe_next = NULL; \
(entry)->field.tqe_prev = &(entry)->field.tqe_next; \
} while (0)
#undef HLTQ_INITIALIZER
#define HLTQ_INITIALIZER(entry, field) \
{ NULL, &(entry)->field.tqe_next }
#undef HLTQ_FIRST
#define HLTQ_FIRST(elm) (elm)
#undef HLTQ_END
#define HLTQ_END(elm) NULL
#undef HLTQ_NEXT
#define HLTQ_NEXT(elm, field) ((elm)->field.tqe_next)
#undef HLTQ_LAST
#define HLTQ_LAST(elm, type, field) \
((elm)->field.tqe_next == NULL ? (elm) : \
__containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
#undef HLTQ_PREV
#define HLTQ_PREV(elm, type, field) \
(*(elm)->field.tqe_prev == NULL ? NULL : \
__containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
#undef HLTQ_FOREACH
#define HLTQ_FOREACH(var, head, field) \
for ((var) = HLTQ_FIRST(head); \
(var) != HLTQ_END(head); \
(var) = HLTQ_NEXT(var, field))
#undef HLTQ_FOREACH_SAFE
#define HLTQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = HLTQ_FIRST(head); \
(var) != HLTQ_END(head) && \
((tvar) = HLTQ_NEXT(var, field), 1); \
(var) = (tvar))
#undef HLTQ_FOREACH_REVERSE
#define HLTQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = HLTQ_LAST(head, headname); \
(var) != HLTQ_END(head); \
(var) = HLTQ_PREV(var, headname, field))
#undef HLTQ_FOREACH_REVERSE_SAFE
#define HLTQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = HLTQ_LAST(head, headname); \
(var) != HLTQ_END(head) && \
((tvar) = HLTQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/* Concatenate queue2 to the end of queue1. */
#undef HLTQ_CONCAT
#define HLTQ_CONCAT(queue1, queue2, field) do { \
(queue2)->field.tqe_prev = (queue1)->field.tqe_prev; \
*(queue1)->field.tqe_prev = (queue2); \
(queue1)->field.tqe_prev = &(queue2)->field.tqe_next; \
} while (0)
/* Convert a headless tailq to a headful one. */
#define HLTQ_TO_TAILQ(head, hl, field) do { \
(head)->tqh_first = (hl); \
(head)->tqh_last = (hl)->field.tqe_prev; \
(hl)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
/* Concatenate a headless tail queue to the end of a regular tail queue. */
#define TAILQ_CONCAT_HLTQ(head, hl, field) do { \
void *last = (hl)->field.tqe_prev; \
(hl)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (hl); \
(head)->tqh_last = last; \
} while (0)
#endif /* !_SUDO_QUEUE_H_ */

View File

@@ -450,8 +450,7 @@ alias.lo: $(srcdir)/alias.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \
$(devdir)/gram.h
$(srcdir)/parse.h $(srcdir)/redblack.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/alias.c
audit.lo: $(srcdir)/audit.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
@@ -491,7 +490,7 @@ check_addr.o: $(srcdir)/regress/parser/check_addr.c $(top_builddir)/config.h \
$(incdir)/fileops.h $(srcdir)/defaults.h $(devdir)/def_data.h \
$(srcdir)/logging.h $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_debug.h $(incdir)/gettext.h $(srcdir)/parse.h \
$(incdir)/list.h $(srcdir)/interfaces.h
$(srcdir)/interfaces.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_addr.c
check_base64.o: $(srcdir)/regress/parser/check_base64.c \
$(top_builddir)/config.h $(incdir)/missing.h
@@ -501,8 +500,8 @@ check_digest.o: $(srcdir)/regress/parser/check_digest.c \
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_digest.c
check_fill.o: $(srcdir)/regress/parser/check_fill.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \
$(incdir)/list.h $(srcdir)/parse.h $(incdir)/list.h \
$(srcdir)/toke.h $(incdir)/sudo_plugin.h $(devdir)/gram.h
$(incdir)/queue.h $(srcdir)/parse.h $(srcdir)/toke.h \
$(incdir)/sudo_plugin.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_fill.c
check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(top_builddir)/config.h $(srcdir)/sudoers.h \
@@ -534,8 +533,8 @@ defaults.lo: $(srcdir)/defaults.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \
$(devdir)/gram.h $(devdir)/def_data.c
$(incdir)/gettext.h $(srcdir)/parse.h $(devdir)/gram.h \
$(devdir)/def_data.c
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/defaults.c
env.lo: $(srcdir)/env.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \
@@ -585,7 +584,7 @@ gram.lo: $(devdir)/gram.c $(top_builddir)/config.h $(top_builddir)/config.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \
$(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/toke.h
$(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/gram.c
group_plugin.lo: $(srcdir)/group_plugin.c $(top_builddir)/config.h \
$(top_srcdir)/compat/dlfcn.h $(srcdir)/sudoers.h \
@@ -643,7 +642,7 @@ ldap.lo: $(srcdir)/ldap.c $(top_builddir)/config.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h
$(srcdir)/parse.h $(incdir)/lbuf.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ldap.c
linux_audit.lo: $(srcdir)/linux_audit.c $(top_builddir)/config.h \
$(incdir)/missing.h $(incdir)/fatal.h $(incdir)/alloc.h \
@@ -678,8 +677,8 @@ match.lo: $(srcdir)/match.c $(top_builddir)/config.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \
$(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \
$(srcdir)/sha2.h $(devdir)/gram.h
$(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/sha2.h \
$(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/match.c
match_addr.lo: $(srcdir)/match_addr.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
@@ -708,7 +707,7 @@ parse.lo: $(srcdir)/parse.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h $(devdir)/gram.h
$(srcdir)/parse.h $(incdir)/lbuf.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/parse.c
passwd.lo: $(authdir)/passwd.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
$(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \
@@ -805,8 +804,7 @@ sssd.lo: $(srcdir)/sssd.c $(top_builddir)/config.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h \
$(incdir)/sudo_debug.h
$(srcdir)/parse.h $(incdir)/lbuf.h $(incdir)/sudo_debug.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sssd.c
sudo_auth.lo: $(authdir)/sudo_auth.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
@@ -853,8 +851,8 @@ testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/interfaces.h $(srcdir)/parse.h \
$(incdir)/list.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
$(incdir)/secure_path.h $(devdir)/gram.h
$(incdir)/sudo_conf.h $(incdir)/queue.h $(incdir)/secure_path.h \
$(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/testsudoers.c
timestamp.lo: $(srcdir)/timestamp.c $(top_builddir)/config.h \
$(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \
@@ -872,8 +870,8 @@ toke.lo: $(devdir)/toke.c $(top_builddir)/config.h $(top_builddir)/config.h \
$(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \
$(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \
$(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \
$(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \
$(srcdir)/toke.h $(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \
$(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h \
$(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \
$(incdir)/secure_path.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/toke.c
toke_util.lo: $(srcdir)/toke_util.c $(top_builddir)/config.h \
@@ -883,7 +881,7 @@ toke_util.lo: $(srcdir)/toke_util.c $(top_builddir)/config.h \
$(incdir)/fileops.h $(srcdir)/defaults.h $(devdir)/def_data.h \
$(srcdir)/logging.h $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_debug.h $(incdir)/gettext.h $(srcdir)/parse.h \
$(incdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h
$(srcdir)/toke.h $(devdir)/gram.h
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/toke_util.c
toke_util.o: toke_util.lo
tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(top_builddir)/config.h \
@@ -902,7 +900,7 @@ visudo.o: $(srcdir)/visudo.c $(top_builddir)/config.h \
$(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \
$(incdir)/gettext.h $(srcdir)/sudoers_version.h \
$(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h
$(srcdir)/parse.h $(srcdir)/redblack.h $(incdir)/gettext.h \
$(srcdir)/sudoers_version.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
$(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c

View File

@@ -131,7 +131,7 @@ alias_add(char *name, int type, struct member *members)
a->name = name;
a->type = type;
/* a->used = false; */
list2tq(&a->members, members);
HLTQ_TO_TAILQ(&a->members, members, entries);
if (rbinsert(aliases, a)) {
snprintf(errbuf, sizeof(errbuf), N_("Alias `%s' already defined"), name);
alias_free(a);
@@ -176,8 +176,7 @@ alias_free(void *v)
debug_decl(alias_free, SUDO_DEBUG_ALIAS)
efree(a->name);
for (m = a->members.first; m != NULL; m = next) {
next = m->next;
TAILQ_FOREACH_SAFE(m, &a->members, entries, next) {
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);

View File

@@ -502,7 +502,7 @@ update_defaults(int what)
bool rc = true;
debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
tq_foreach_fwd(&defaults, def) {
TAILQ_FOREACH(def, &defaults, entries) {
switch (def->type) {
case DEFAULTS:
if (ISSET(what, SETDEF_GENERIC) &&
@@ -513,7 +513,7 @@ update_defaults(int what)
#if 1
if (ISSET(what, SETDEF_USER)) {
int m;
m = userlist_matches(sudo_user.pw, &def->binding);
m = userlist_matches(sudo_user.pw, def->binding);
if (m == ALLOW) {
if (!set_default(def->var, def->val, def->op))
rc = false;
@@ -521,26 +521,26 @@ update_defaults(int what)
}
#else
if (ISSET(what, SETDEF_USER) &&
userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
userlist_matches(sudo_user.pw, def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
#endif
break;
case DEFAULTS_RUNAS:
if (ISSET(what, SETDEF_RUNAS) &&
runaslist_matches(&def->binding, NULL, NULL, NULL) == ALLOW &&
runaslist_matches(def->binding, NULL, NULL, NULL) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
case DEFAULTS_HOST:
if (ISSET(what, SETDEF_HOST) &&
hostlist_matches(&def->binding) == ALLOW &&
hostlist_matches(def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
case DEFAULTS_CMND:
if (ISSET(what, SETDEF_CMND) &&
cmndlist_matches(&def->binding) == ALLOW &&
cmndlist_matches(def->binding) == ALLOW &&
!set_default(def->var, def->val, def->op))
rc = false;
break;
@@ -561,7 +561,7 @@ check_defaults(int what, bool quiet)
bool rc = true;
debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS)
tq_foreach_fwd(&defaults, def) {
TAILQ_FOREACH(def, &defaults, entries) {
switch (def->type) {
case DEFAULTS:
if (!ISSET(what, SETDEF_GENERIC))

View File

@@ -117,8 +117,8 @@ bool parse_error = false;
int errorlineno = -1;
char *errorfile = NULL;
struct defaults_list defaults;
struct userspec_list userspecs;
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
/*
* Local protoypes
@@ -699,7 +699,7 @@ short *yyss;
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
#line 681 "gram.y"
#line 688 "gram.y"
void
sudoerserror(const char *s)
{
@@ -741,11 +741,10 @@ new_default(char *var, char *val, int op)
d = ecalloc(1, sizeof(struct defaults));
d->var = var;
d->val = val;
tq_init(&d->binding);
/* d->type = 0; */
d->op = op;
d->prev = d;
/* d->next = NULL; */
/* d->binding = NULL */
HLTQ_INIT(d, entries);
debug_return_ptr(d);
}
@@ -759,8 +758,7 @@ new_member(char *name, int type)
m = ecalloc(1, sizeof(struct member));
m->name = name;
m->type = type;
m->prev = m;
/* m->next = NULL; */
HLTQ_INIT(m, entries);
debug_return_ptr(m);
}
@@ -787,30 +785,34 @@ static void
add_defaults(int type, struct member *bmem, struct defaults *defs)
{
struct defaults *d;
struct member_list binding;
struct member_list *binding;
debug_decl(add_defaults, SUDO_DEBUG_PARSER)
/*
* We can only call list2tq once on bmem as it will zero
* out the prev pointer when it consumes bmem.
* We use a single binding for each entry in defs.
*/
list2tq(&binding, bmem);
binding = emalloc(sizeof(*binding));
if (bmem != NULL)
HLTQ_TO_TAILQ(binding, bmem, entries);
else
TAILQ_INIT(binding);
/*
* Set type and binding (who it applies to) for new entries.
* Then add to the global defaults list.
*/
for (d = defs; d != NULL; d = d->next) {
HLTQ_FOREACH(d, defs, entries) {
d->type = type;
d->binding = binding;
}
tq_append(&defaults, defs);
TAILQ_CONCAT_HLTQ(&defaults, defs, entries);
debug_return;
}
/*
* Allocate a new struct userspec, populate it, and insert it at the
* and of the userspecs list.
* end of the userspecs list.
*/
static void
add_userspec(struct member *members, struct privilege *privs)
@@ -819,11 +821,9 @@ add_userspec(struct member *members, struct privilege *privs)
debug_decl(add_userspec, SUDO_DEBUG_PARSER)
u = ecalloc(1, sizeof(*u));
list2tq(&u->users, members);
list2tq(&u->privileges, privs);
u->prev = u;
/* u->next = NULL; */
tq_append(&userspecs, u);
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
debug_return;
}
@@ -835,21 +835,24 @@ add_userspec(struct member *members, struct privilege *privs)
void
init_parser(const char *path, bool quiet)
{
struct member_list *binding;
struct member *m;
struct defaults *d;
struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
struct sudo_command *c;
debug_decl(init_parser, SUDO_DEBUG_PARSER)
while ((us = tq_pop(&userspecs)) != NULL) {
while ((m = tq_pop(&us->users)) != NULL) {
while ((us = TAILQ_FIRST(&userspecs)) != NULL) {
TAILQ_REMOVE(&userspecs, us, entries);
while ((m = TAILQ_FIRST(&us->users)) != NULL) {
TAILQ_REMOVE(&us->users, m, entries);
efree(m->name);
efree(m);
}
while ((priv = tq_pop(&us->privileges)) != NULL) {
struct member *runasuser = NULL, *runasgroup = NULL;
while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
#ifdef HAVE_SELINUX
char *role = NULL, *type = NULL;
#endif /* HAVE_SELINUX */
@@ -857,11 +860,14 @@ init_parser(const char *path, bool quiet)
char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */
while ((m = tq_pop(&priv->hostlist)) != NULL) {
TAILQ_REMOVE(&us->privileges, priv, entries);
while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) {
TAILQ_REMOVE(&priv->hostlist, m, entries);
efree(m->name);
efree(m);
}
while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) {
TAILQ_REMOVE(&priv->cmndlist, cs, entries);
#ifdef HAVE_SELINUX
/* Only free the first instance of a role/type. */
if (cs->role != role) {
@@ -884,19 +890,24 @@ init_parser(const char *path, bool quiet)
efree(cs->limitprivs);
}
#endif /* HAVE_PRIV_SET */
if (tq_last(&cs->runasuserlist) != runasuser) {
runasuser = tq_last(&cs->runasuserlist);
while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
/* Only free the first instance of runas user/group lists. */
if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
runasuserlist = cs->runasuserlist;
while ((m = TAILQ_FIRST(runasuserlist)) != NULL) {
TAILQ_REMOVE(runasuserlist, m, entries);
efree(m->name);
efree(m);
}
efree(runasuserlist);
}
if (tq_last(&cs->runasgrouplist) != runasgroup) {
runasgroup = tq_last(&cs->runasgrouplist);
while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
runasgrouplist = cs->runasgrouplist;
while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) {
TAILQ_REMOVE(runasgrouplist, m, entries);
efree(m->name);
efree(m);
}
efree(runasgrouplist);
}
if (cs->cmnd->type == COMMAND) {
c = (struct sudo_command *) cs->cmnd->name;
@@ -911,13 +922,15 @@ init_parser(const char *path, bool quiet)
}
efree(us);
}
tq_init(&userspecs);
TAILQ_INIT(&userspecs);
binding = NULL;
while ((d = tq_pop(&defaults)) != NULL) {
if (tq_last(&d->binding) != binding) {
binding = tq_last(&d->binding);
while ((m = tq_pop(&d->binding)) != NULL) {
while ((d = TAILQ_FIRST(&defaults)) != NULL) {
TAILQ_REMOVE(&defaults, d, entries);
if (d->binding != binding) {
binding = d->binding;
while ((m = TAILQ_FIRST(d->binding)) != NULL) {
TAILQ_REMOVE(d->binding, m, entries);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);
@@ -926,12 +939,13 @@ init_parser(const char *path, bool quiet)
efree(m->name);
efree(m);
}
efree(d->binding);
}
efree(d->var);
efree(d->val);
efree(d);
}
tq_init(&defaults);
TAILQ_INIT(&defaults);
init_aliases();
@@ -947,7 +961,7 @@ init_parser(const char *path, bool quiet)
debug_return;
}
#line 898 "gram.c"
#line 912 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void)
@@ -1228,7 +1242,7 @@ break;
case 18:
#line 232 "gram.y"
{
list_append(yyvsp[-2].defaults, yyvsp[0].defaults);
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
yyval.defaults = yyvsp[-2].defaults;
}
break;
@@ -1265,7 +1279,7 @@ break;
case 25:
#line 256 "gram.y"
{
list_append(yyvsp[-2].privilege, yyvsp[0].privilege);
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
yyval.privilege = yyvsp[-2].privilege;
}
break;
@@ -1273,108 +1287,116 @@ case 26:
#line 262 "gram.y"
{
struct privilege *p = ecalloc(1, sizeof(*p));
list2tq(&p->hostlist, yyvsp[-2].member);
list2tq(&p->cmndlist, yyvsp[0].cmndspec);
p->prev = p;
/* p->next = NULL; */
HLTQ_TO_TAILQ(&p->hostlist, yyvsp[-2].member, entries);
HLTQ_TO_TAILQ(&p->cmndlist, yyvsp[0].cmndspec, entries);
HLTQ_INIT(p, entries);
yyval.privilege = p;
}
break;
case 27:
#line 272 "gram.y"
#line 271 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 28:
#line 276 "gram.y"
#line 275 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 29:
#line 282 "gram.y"
#line 281 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 30:
#line 285 "gram.y"
#line 284 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 31:
#line 288 "gram.y"
#line 287 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
case 32:
#line 291 "gram.y"
#line 290 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
}
break;
case 33:
#line 294 "gram.y"
#line 293 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
case 35:
#line 300 "gram.y"
#line 299 "gram.y"
{
list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec);
struct cmndspec *prev;
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
HLTQ_CONCAT(yyvsp[-2].cmndspec, yyvsp[0].cmndspec, entries);
#ifdef HAVE_SELINUX
/* propagate role and type */
if (yyvsp[0].cmndspec->role == NULL)
yyvsp[0].cmndspec->role = yyvsp[0].cmndspec->prev->role;
yyvsp[0].cmndspec->role = prev->role;
if (yyvsp[0].cmndspec->type == NULL)
yyvsp[0].cmndspec->type = yyvsp[0].cmndspec->prev->type;
yyvsp[0].cmndspec->type = prev->type;
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
/* propagate privs & limitprivs */
if (yyvsp[0].cmndspec->privs == NULL)
yyvsp[0].cmndspec->privs = yyvsp[0].cmndspec->prev->privs;
yyvsp[0].cmndspec->privs = prev->privs;
if (yyvsp[0].cmndspec->limitprivs == NULL)
yyvsp[0].cmndspec->limitprivs = yyvsp[0].cmndspec->prev->limitprivs;
yyvsp[0].cmndspec->limitprivs = prev->limitprivs;
#endif /* HAVE_PRIV_SET */
/* propagate tags and runas list */
if (yyvsp[0].cmndspec->tags.nopasswd == UNSPEC)
yyvsp[0].cmndspec->tags.nopasswd = yyvsp[0].cmndspec->prev->tags.nopasswd;
yyvsp[0].cmndspec->tags.nopasswd = prev->tags.nopasswd;
if (yyvsp[0].cmndspec->tags.noexec == UNSPEC)
yyvsp[0].cmndspec->tags.noexec = yyvsp[0].cmndspec->prev->tags.noexec;
yyvsp[0].cmndspec->tags.noexec = prev->tags.noexec;
if (yyvsp[0].cmndspec->tags.setenv == UNSPEC &&
yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED)
yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv;
prev->tags.setenv != IMPLIED)
yyvsp[0].cmndspec->tags.setenv = prev->tags.setenv;
if (yyvsp[0].cmndspec->tags.log_input == UNSPEC)
yyvsp[0].cmndspec->tags.log_input = yyvsp[0].cmndspec->prev->tags.log_input;
yyvsp[0].cmndspec->tags.log_input = prev->tags.log_input;
if (yyvsp[0].cmndspec->tags.log_output == UNSPEC)
yyvsp[0].cmndspec->tags.log_output = yyvsp[0].cmndspec->prev->tags.log_output;
if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) &&
tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) &&
(!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) ||
!tq_empty(&yyvsp[0].cmndspec->prev->runasgrouplist))) {
yyvsp[0].cmndspec->runasuserlist = yyvsp[0].cmndspec->prev->runasuserlist;
yyvsp[0].cmndspec->runasgrouplist = yyvsp[0].cmndspec->prev->runasgrouplist;
yyvsp[0].cmndspec->tags.log_output = prev->tags.log_output;
if ((yyvsp[0].cmndspec->runasuserlist == NULL &&
yyvsp[0].cmndspec->runasgrouplist == NULL) &&
(prev->runasuserlist != NULL ||
prev->runasgrouplist != NULL)) {
yyvsp[0].cmndspec->runasuserlist = prev->runasuserlist;
yyvsp[0].cmndspec->runasgrouplist = prev->runasgrouplist;
}
yyval.cmndspec = yyvsp[-2].cmndspec;
}
break;
case 36:
#line 339 "gram.y"
#line 340 "gram.y"
{
struct cmndspec *cs = ecalloc(1, sizeof(*cs));
if (yyvsp[-4].runas != NULL) {
list2tq(&cs->runasuserlist, yyvsp[-4].runas->runasusers);
list2tq(&cs->runasgrouplist, yyvsp[-4].runas->runasgroups);
if (yyvsp[-4].runas->runasusers != NULL) {
cs->runasuserlist =
emalloc(sizeof(*cs->runasuserlist));
HLTQ_TO_TAILQ(cs->runasuserlist,
yyvsp[-4].runas->runasusers, entries);
}
if (yyvsp[-4].runas->runasgroups != NULL) {
cs->runasgrouplist =
emalloc(sizeof(*cs->runasgrouplist));
HLTQ_TO_TAILQ(cs->runasgrouplist,
yyvsp[-4].runas->runasgroups, entries);
}
efree(yyvsp[-4].runas);
} else {
tq_init(&cs->runasuserlist);
tq_init(&cs->runasgrouplist);
}
#ifdef HAVE_SELINUX
cs->role = yyvsp[-3].seinfo.role;
@@ -1386,8 +1408,7 @@ case 36:
#endif
cs->tags = yyvsp[-1].tag;
cs->cmnd = yyvsp[0].member;
cs->prev = cs;
cs->next = NULL;
HLTQ_INIT(cs, entries);
/* sudo "ALL" implies the SETENV tag */
if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
cs->tags.setenv == UNSPEC)
@@ -1396,37 +1417,37 @@ case 36:
}
break;
case 37:
#line 369 "gram.y"
#line 376 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
}
break;
case 38:
#line 372 "gram.y"
#line 379 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
}
break;
case 39:
#line 375 "gram.y"
#line 382 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
}
break;
case 40:
#line 378 "gram.y"
#line 385 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
}
break;
case 41:
#line 383 "gram.y"
#line 390 "gram.y"
{
yyval.member = yyvsp[0].member;
}
break;
case 42:
#line 386 "gram.y"
#line 393 "gram.y"
{
/* XXX - yuck */
struct sudo_command *c = (struct sudo_command *)(yyvsp[0].member->name);
@@ -1435,127 +1456,127 @@ case 42:
}
break;
case 43:
#line 394 "gram.y"
#line 401 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 44:
#line 398 "gram.y"
#line 405 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 45:
#line 404 "gram.y"
#line 411 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 46:
#line 409 "gram.y"
#line 416 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 47:
#line 414 "gram.y"
#line 421 "gram.y"
{
yyval.seinfo.role = NULL;
yyval.seinfo.type = NULL;
}
break;
case 48:
#line 418 "gram.y"
#line 425 "gram.y"
{
yyval.seinfo.role = yyvsp[0].string;
yyval.seinfo.type = NULL;
}
break;
case 49:
#line 422 "gram.y"
#line 429 "gram.y"
{
yyval.seinfo.type = yyvsp[0].string;
yyval.seinfo.role = NULL;
}
break;
case 50:
#line 426 "gram.y"
#line 433 "gram.y"
{
yyval.seinfo.role = yyvsp[-1].string;
yyval.seinfo.type = yyvsp[0].string;
}
break;
case 51:
#line 430 "gram.y"
#line 437 "gram.y"
{
yyval.seinfo.type = yyvsp[-1].string;
yyval.seinfo.role = yyvsp[0].string;
}
break;
case 52:
#line 436 "gram.y"
#line 443 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 53:
#line 440 "gram.y"
#line 447 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 54:
#line 445 "gram.y"
#line 452 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = NULL;
}
break;
case 55:
#line 449 "gram.y"
#line 456 "gram.y"
{
yyval.privinfo.privs = yyvsp[0].string;
yyval.privinfo.limitprivs = NULL;
}
break;
case 56:
#line 453 "gram.y"
#line 460 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 57:
#line 457 "gram.y"
#line 464 "gram.y"
{
yyval.privinfo.privs = yyvsp[-1].string;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 58:
#line 461 "gram.y"
#line 468 "gram.y"
{
yyval.privinfo.limitprivs = yyvsp[-1].string;
yyval.privinfo.privs = yyvsp[0].string;
}
break;
case 59:
#line 467 "gram.y"
#line 474 "gram.y"
{
yyval.runas = NULL;
}
break;
case 60:
#line 470 "gram.y"
#line 477 "gram.y"
{
yyval.runas = yyvsp[-1].runas;
}
break;
case 61:
#line 475 "gram.y"
#line 482 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = new_member(NULL, MYSELF);
@@ -1563,7 +1584,7 @@ case 61:
}
break;
case 62:
#line 480 "gram.y"
#line 487 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = yyvsp[0].member;
@@ -1571,7 +1592,7 @@ case 62:
}
break;
case 63:
#line 485 "gram.y"
#line 492 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = yyvsp[-2].member;
@@ -1579,7 +1600,7 @@ case 63:
}
break;
case 64:
#line 490 "gram.y"
#line 497 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
/* $$->runasusers = NULL; */
@@ -1587,7 +1608,7 @@ case 64:
}
break;
case 65:
#line 495 "gram.y"
#line 502 "gram.y"
{
yyval.runas = ecalloc(1, sizeof(struct runascontainer));
yyval.runas->runasusers = new_member(NULL, MYSELF);
@@ -1595,86 +1616,86 @@ case 65:
}
break;
case 66:
#line 502 "gram.y"
#line 509 "gram.y"
{
yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv =
yyval.tag.log_input = yyval.tag.log_output = UNSPEC;
}
break;
case 67:
#line 506 "gram.y"
#line 513 "gram.y"
{
yyval.tag.nopasswd = true;
}
break;
case 68:
#line 509 "gram.y"
#line 516 "gram.y"
{
yyval.tag.nopasswd = false;
}
break;
case 69:
#line 512 "gram.y"
#line 519 "gram.y"
{
yyval.tag.noexec = true;
}
break;
case 70:
#line 515 "gram.y"
#line 522 "gram.y"
{
yyval.tag.noexec = false;
}
break;
case 71:
#line 518 "gram.y"
#line 525 "gram.y"
{
yyval.tag.setenv = true;
}
break;
case 72:
#line 521 "gram.y"
#line 528 "gram.y"
{
yyval.tag.setenv = false;
}
break;
case 73:
#line 524 "gram.y"
#line 531 "gram.y"
{
yyval.tag.log_input = true;
}
break;
case 74:
#line 527 "gram.y"
#line 534 "gram.y"
{
yyval.tag.log_input = false;
}
break;
case 75:
#line 530 "gram.y"
#line 537 "gram.y"
{
yyval.tag.log_output = true;
}
break;
case 76:
#line 533 "gram.y"
#line 540 "gram.y"
{
yyval.tag.log_output = false;
}
break;
case 77:
#line 538 "gram.y"
#line 545 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 78:
#line 541 "gram.y"
#line 548 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 79:
#line 544 "gram.y"
#line 551 "gram.y"
{
struct sudo_command *c = ecalloc(1, sizeof(*c));
c->cmnd = yyvsp[0].command.cmnd;
@@ -1683,7 +1704,7 @@ case 79:
}
break;
case 82:
#line 556 "gram.y"
#line 563 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) {
@@ -1693,14 +1714,14 @@ case 82:
}
break;
case 84:
#line 566 "gram.y"
#line 573 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 87:
#line 576 "gram.y"
#line 583 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) {
@@ -1710,14 +1731,14 @@ case 87:
}
break;
case 89:
#line 586 "gram.y"
#line 593 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 92:
#line 596 "gram.y"
#line 603 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) {
@@ -1727,7 +1748,7 @@ case 92:
}
break;
case 95:
#line 609 "gram.y"
#line 616 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) {
@@ -1737,96 +1758,96 @@ case 95:
}
break;
case 97:
#line 619 "gram.y"
#line 626 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 98:
#line 625 "gram.y"
#line 632 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 99:
#line 629 "gram.y"
#line 636 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 100:
#line 635 "gram.y"
#line 642 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 101:
#line 638 "gram.y"
#line 645 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 102:
#line 641 "gram.y"
#line 648 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
case 103:
#line 644 "gram.y"
#line 651 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
}
break;
case 104:
#line 647 "gram.y"
#line 654 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
case 106:
#line 653 "gram.y"
#line 660 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 107:
#line 659 "gram.y"
#line 666 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 108:
#line 663 "gram.y"
#line 670 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 109:
#line 669 "gram.y"
#line 676 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 110:
#line 672 "gram.y"
#line 679 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 111:
#line 675 "gram.y"
#line 682 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
#line 1777 "gram.c"
#line 1798 "gram.c"
}
yyssp -= yym;
yystate = *yyssp;

View File

@@ -79,8 +79,8 @@ bool parse_error = false;
int errorlineno = -1;
char *errorfile = NULL;
struct defaults_list defaults;
struct userspec_list userspecs;
struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
/*
* Local protoypes
@@ -230,7 +230,7 @@ entry : COMMENT {
defaults_list : defaults_entry
| defaults_list ',' defaults_entry {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
@@ -254,17 +254,16 @@ defaults_entry : DEFVAR {
privileges : privilege
| privileges ':' privilege {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
privilege : hostlist '=' cmndspeclist {
struct privilege *p = ecalloc(1, sizeof(*p));
list2tq(&p->hostlist, $1);
list2tq(&p->cmndlist, $3);
p->prev = p;
/* p->next = NULL; */
HLTQ_TO_TAILQ(&p->hostlist, $1, entries);
HLTQ_TO_TAILQ(&p->cmndlist, $3, entries);
HLTQ_INIT(p, entries);
$$ = p;
}
;
@@ -298,39 +297,41 @@ host : ALIAS {
cmndspeclist : cmndspec
| cmndspeclist ',' cmndspec {
list_append($1, $3);
struct cmndspec *prev;
prev = HLTQ_LAST($1, cmndspec, entries);
HLTQ_CONCAT($1, $3, entries);
#ifdef HAVE_SELINUX
/* propagate role and type */
if ($3->role == NULL)
$3->role = $3->prev->role;
$3->role = prev->role;
if ($3->type == NULL)
$3->type = $3->prev->type;
$3->type = prev->type;
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
/* propagate privs & limitprivs */
if ($3->privs == NULL)
$3->privs = $3->prev->privs;
$3->privs = prev->privs;
if ($3->limitprivs == NULL)
$3->limitprivs = $3->prev->limitprivs;
$3->limitprivs = prev->limitprivs;
#endif /* HAVE_PRIV_SET */
/* propagate tags and runas list */
if ($3->tags.nopasswd == UNSPEC)
$3->tags.nopasswd = $3->prev->tags.nopasswd;
$3->tags.nopasswd = prev->tags.nopasswd;
if ($3->tags.noexec == UNSPEC)
$3->tags.noexec = $3->prev->tags.noexec;
$3->tags.noexec = prev->tags.noexec;
if ($3->tags.setenv == UNSPEC &&
$3->prev->tags.setenv != IMPLIED)
$3->tags.setenv = $3->prev->tags.setenv;
prev->tags.setenv != IMPLIED)
$3->tags.setenv = prev->tags.setenv;
if ($3->tags.log_input == UNSPEC)
$3->tags.log_input = $3->prev->tags.log_input;
$3->tags.log_input = prev->tags.log_input;
if ($3->tags.log_output == UNSPEC)
$3->tags.log_output = $3->prev->tags.log_output;
if ((tq_empty(&$3->runasuserlist) &&
tq_empty(&$3->runasgrouplist)) &&
(!tq_empty(&$3->prev->runasuserlist) ||
!tq_empty(&$3->prev->runasgrouplist))) {
$3->runasuserlist = $3->prev->runasuserlist;
$3->runasgrouplist = $3->prev->runasgrouplist;
$3->tags.log_output = prev->tags.log_output;
if (($3->runasuserlist == NULL &&
$3->runasgrouplist == NULL) &&
(prev->runasuserlist != NULL ||
prev->runasgrouplist != NULL)) {
$3->runasuserlist = prev->runasuserlist;
$3->runasgrouplist = prev->runasgrouplist;
}
$$ = $1;
}
@@ -339,12 +340,19 @@ cmndspeclist : cmndspec
cmndspec : runasspec selinux solarisprivs cmndtag digcmnd {
struct cmndspec *cs = ecalloc(1, sizeof(*cs));
if ($1 != NULL) {
list2tq(&cs->runasuserlist, $1->runasusers);
list2tq(&cs->runasgrouplist, $1->runasgroups);
if ($1->runasusers != NULL) {
cs->runasuserlist =
emalloc(sizeof(*cs->runasuserlist));
HLTQ_TO_TAILQ(cs->runasuserlist,
$1->runasusers, entries);
}
if ($1->runasgroups != NULL) {
cs->runasgrouplist =
emalloc(sizeof(*cs->runasgrouplist));
HLTQ_TO_TAILQ(cs->runasgrouplist,
$1->runasgroups, entries);
}
efree($1);
} else {
tq_init(&cs->runasuserlist);
tq_init(&cs->runasgrouplist);
}
#ifdef HAVE_SELINUX
cs->role = $2.role;
@@ -356,8 +364,7 @@ cmndspec : runasspec selinux solarisprivs cmndtag digcmnd {
#endif
cs->tags = $4;
cs->cmnd = $5;
cs->prev = cs;
cs->next = NULL;
HLTQ_INIT(cs, entries);
/* sudo "ALL" implies the SETENV tag */
if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
cs->tags.setenv == UNSPEC)
@@ -564,7 +571,7 @@ hostalias : ALIAS '=' hostlist {
hostlist : ophost
| hostlist ',' ophost {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
@@ -584,7 +591,7 @@ cmndalias : ALIAS '=' cmndlist {
cmndlist : digcmnd
| cmndlist ',' digcmnd {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
@@ -617,7 +624,7 @@ useralias : ALIAS '=' userlist {
userlist : opuser
| userlist ',' opuser {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
@@ -651,7 +658,7 @@ user : ALIAS {
grouplist : opgroup
| grouplist ',' opgroup {
list_append($1, $3);
HLTQ_CONCAT($1, $3, entries);
$$ = $1;
}
;
@@ -719,11 +726,10 @@ new_default(char *var, char *val, int op)
d = ecalloc(1, sizeof(struct defaults));
d->var = var;
d->val = val;
tq_init(&d->binding);
/* d->type = 0; */
d->op = op;
d->prev = d;
/* d->next = NULL; */
/* d->binding = NULL */
HLTQ_INIT(d, entries);
debug_return_ptr(d);
}
@@ -737,8 +743,7 @@ new_member(char *name, int type)
m = ecalloc(1, sizeof(struct member));
m->name = name;
m->type = type;
m->prev = m;
/* m->next = NULL; */
HLTQ_INIT(m, entries);
debug_return_ptr(m);
}
@@ -765,30 +770,34 @@ static void
add_defaults(int type, struct member *bmem, struct defaults *defs)
{
struct defaults *d;
struct member_list binding;
struct member_list *binding;
debug_decl(add_defaults, SUDO_DEBUG_PARSER)
/*
* We can only call list2tq once on bmem as it will zero
* out the prev pointer when it consumes bmem.
* We use a single binding for each entry in defs.
*/
list2tq(&binding, bmem);
binding = emalloc(sizeof(*binding));
if (bmem != NULL)
HLTQ_TO_TAILQ(binding, bmem, entries);
else
TAILQ_INIT(binding);
/*
* Set type and binding (who it applies to) for new entries.
* Then add to the global defaults list.
*/
for (d = defs; d != NULL; d = d->next) {
HLTQ_FOREACH(d, defs, entries) {
d->type = type;
d->binding = binding;
}
tq_append(&defaults, defs);
TAILQ_CONCAT_HLTQ(&defaults, defs, entries);
debug_return;
}
/*
* Allocate a new struct userspec, populate it, and insert it at the
* and of the userspecs list.
* end of the userspecs list.
*/
static void
add_userspec(struct member *members, struct privilege *privs)
@@ -797,11 +806,9 @@ add_userspec(struct member *members, struct privilege *privs)
debug_decl(add_userspec, SUDO_DEBUG_PARSER)
u = ecalloc(1, sizeof(*u));
list2tq(&u->users, members);
list2tq(&u->privileges, privs);
u->prev = u;
/* u->next = NULL; */
tq_append(&userspecs, u);
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
debug_return;
}
@@ -813,21 +820,24 @@ add_userspec(struct member *members, struct privilege *privs)
void
init_parser(const char *path, bool quiet)
{
struct member_list *binding;
struct member *m;
struct defaults *d;
struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
struct sudo_command *c;
debug_decl(init_parser, SUDO_DEBUG_PARSER)
while ((us = tq_pop(&userspecs)) != NULL) {
while ((m = tq_pop(&us->users)) != NULL) {
while ((us = TAILQ_FIRST(&userspecs)) != NULL) {
TAILQ_REMOVE(&userspecs, us, entries);
while ((m = TAILQ_FIRST(&us->users)) != NULL) {
TAILQ_REMOVE(&us->users, m, entries);
efree(m->name);
efree(m);
}
while ((priv = tq_pop(&us->privileges)) != NULL) {
struct member *runasuser = NULL, *runasgroup = NULL;
while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
#ifdef HAVE_SELINUX
char *role = NULL, *type = NULL;
#endif /* HAVE_SELINUX */
@@ -835,11 +845,14 @@ init_parser(const char *path, bool quiet)
char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */
while ((m = tq_pop(&priv->hostlist)) != NULL) {
TAILQ_REMOVE(&us->privileges, priv, entries);
while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) {
TAILQ_REMOVE(&priv->hostlist, m, entries);
efree(m->name);
efree(m);
}
while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) {
TAILQ_REMOVE(&priv->cmndlist, cs, entries);
#ifdef HAVE_SELINUX
/* Only free the first instance of a role/type. */
if (cs->role != role) {
@@ -862,19 +875,24 @@ init_parser(const char *path, bool quiet)
efree(cs->limitprivs);
}
#endif /* HAVE_PRIV_SET */
if (tq_last(&cs->runasuserlist) != runasuser) {
runasuser = tq_last(&cs->runasuserlist);
while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
/* Only free the first instance of runas user/group lists. */
if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
runasuserlist = cs->runasuserlist;
while ((m = TAILQ_FIRST(runasuserlist)) != NULL) {
TAILQ_REMOVE(runasuserlist, m, entries);
efree(m->name);
efree(m);
}
efree(runasuserlist);
}
if (tq_last(&cs->runasgrouplist) != runasgroup) {
runasgroup = tq_last(&cs->runasgrouplist);
while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
runasgrouplist = cs->runasgrouplist;
while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) {
TAILQ_REMOVE(runasgrouplist, m, entries);
efree(m->name);
efree(m);
}
efree(runasgrouplist);
}
if (cs->cmnd->type == COMMAND) {
c = (struct sudo_command *) cs->cmnd->name;
@@ -889,13 +907,15 @@ init_parser(const char *path, bool quiet)
}
efree(us);
}
tq_init(&userspecs);
TAILQ_INIT(&userspecs);
binding = NULL;
while ((d = tq_pop(&defaults)) != NULL) {
if (tq_last(&d->binding) != binding) {
binding = tq_last(&d->binding);
while ((m = tq_pop(&d->binding)) != NULL) {
while ((d = TAILQ_FIRST(&defaults)) != NULL) {
TAILQ_REMOVE(&defaults, d, entries);
if (d->binding != binding) {
binding = d->binding;
while ((m = TAILQ_FIRST(d->binding)) != NULL) {
TAILQ_REMOVE(d->binding, m, entries);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
efree(c->cmnd);
@@ -904,12 +924,13 @@ init_parser(const char *path, bool quiet)
efree(m->name);
efree(m);
}
efree(d->binding);
}
efree(d->var);
efree(d->val);
efree(d);
}
tq_init(&defaults);
TAILQ_INIT(&defaults);
init_aliases();

View File

@@ -91,7 +91,7 @@
#include "sha2.h"
#include <gram.h>
static struct member_list empty;
static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty);
static bool command_matches_dir(char *, size_t);
#ifndef SUDOERS_NAME_MATCH
@@ -117,7 +117,7 @@ userlist_matches(struct passwd *pw, struct member_list *list)
int rval, matched = UNSPEC;
debug_decl(userlist_matches, SUDO_DEBUG_MATCH)
tq_foreach_rev(list, m) {
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
switch (m->type) {
case ALL:
matched = !m->negated;
@@ -169,46 +169,48 @@ runaslist_matches(struct member_list *user_list,
if (runas_pw != NULL) {
/* If no runas user or runas group listed in sudoers, use default. */
if (tq_empty(user_list) && tq_empty(group_list))
if (user_list == NULL && group_list == NULL)
debug_return_int(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
tq_foreach_rev(user_list, m) {
switch (m->type) {
case ALL:
user_matched = !m->negated;
break;
case NETGROUP:
if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
if (user_list != NULL) {
TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
switch (m->type) {
case ALL:
user_matched = !m->negated;
break;
case USERGROUP:
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
user_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rval = runaslist_matches(&a->members, &empty,
matching_user, NULL);
if (rval != UNSPEC)
user_matched = m->negated ? !rval : rval;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
user_matched = !m->negated;
case NETGROUP:
if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
user_matched = !m->negated;
break;
case USERGROUP:
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
user_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rval = runaslist_matches(&a->members, &empty,
matching_user, NULL);
if (rval != UNSPEC)
user_matched = m->negated ? !rval : rval;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
user_matched = !m->negated;
break;
case MYSELF:
if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
strcmp(user_name, runas_pw->pw_name) == 0)
user_matched = !m->negated;
break;
}
if (user_matched != UNSPEC) {
if (matching_user != NULL && m->type != ALIAS)
*matching_user = m;
break;
case MYSELF:
if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
strcmp(user_name, runas_pw->pw_name) == 0)
user_matched = !m->negated;
break;
}
if (user_matched != UNSPEC) {
if (matching_user != NULL && m->type != ALIAS)
*matching_user = m;
break;
}
}
}
}
@@ -218,30 +220,32 @@ runaslist_matches(struct member_list *user_list,
if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0)
user_matched = ALLOW; /* only changing group */
}
tq_foreach_rev(group_list, m) {
switch (m->type) {
case ALL:
group_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rval = runaslist_matches(&empty, &a->members,
NULL, matching_group);
if (rval != UNSPEC)
group_matched = m->negated ? !rval : rval;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (group_matches(m->name, runas_gr))
if (group_list != NULL) {
TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
switch (m->type) {
case ALL:
group_matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) {
rval = runaslist_matches(&empty, &a->members,
NULL, matching_group);
if (rval != UNSPEC)
group_matched = m->negated ? !rval : rval;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (group_matches(m->name, runas_gr))
group_matched = !m->negated;
break;
}
if (group_matched != UNSPEC) {
if (matching_group != NULL && m->type != ALIAS)
*matching_group = m;
break;
}
if (group_matched != UNSPEC) {
if (matching_group != NULL && m->type != ALIAS)
*matching_group = m;
break;
}
}
}
if (group_matched == UNSPEC) {
@@ -269,7 +273,7 @@ hostlist_matches(struct member_list *list)
int rval, matched = UNSPEC;
debug_decl(hostlist_matches, SUDO_DEBUG_MATCH)
tq_foreach_rev(list, m) {
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
switch (m->type) {
case ALL:
matched = !m->negated;
@@ -313,7 +317,7 @@ cmndlist_matches(struct member_list *list)
int matched = UNSPEC;
debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH)
tq_foreach_rev(list, m) {
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = cmnd_matches(m);
if (matched != UNSPEC)
break;

View File

@@ -181,13 +181,13 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag)
CLR(validated, FLAG_NO_USER);
CLR(validated, FLAG_NO_HOST);
match = DENY;
tq_foreach_fwd(&userspecs, us) {
TAILQ_FOREACH(us, &userspecs, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
tq_foreach_fwd(&us->privileges, priv) {
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
tq_foreach_fwd(&priv->cmndlist, cs) {
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
/* Only check the command when listing another user. */
if (user_uid == 0 || list_pw == NULL ||
user_uid == list_pw->pw_uid ||
@@ -215,20 +215,20 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag)
set_perms(PERM_RUNAS);
match = UNSPEC;
tq_foreach_rev(&userspecs, us) {
TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
CLR(validated, FLAG_NO_USER);
tq_foreach_rev(&us->privileges, priv) {
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match == ALLOW)
CLR(validated, FLAG_NO_HOST);
else
continue;
tq_foreach_rev(&priv->cmndlist, cs) {
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
matching_user = NULL;
runas_match = runaslist_matches(&cs->runasuserlist,
&cs->runasgrouplist, &matching_user, NULL);
runas_match = runaslist_matches(cs->runasuserlist,
cs->runasgrouplist, &matching_user, NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
@@ -340,10 +340,8 @@ sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
#define RUNAS_CHANGED(cs1, cs2) \
(cs1 == NULL || cs2 == NULL || \
cs1->runasuserlist.first != cs2->runasuserlist.first || \
cs1->runasuserlist.last != cs2->runasuserlist.last || \
cs1->runasgrouplist.first != cs2->runasgrouplist.first || \
cs1->runasgrouplist.last != cs2->runasgrouplist.last)
cs1->runasuserlist != cs2->runasuserlist || \
cs1->runasgrouplist != cs2->runasgrouplist)
static int
sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
@@ -362,30 +360,30 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
tq_foreach_fwd(&us->privileges, priv) {
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
tq_foreach_fwd(&priv->cmndlist, cs) {
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (RUNAS_CHANGED(cs, prev_cs)) {
if (cs != tq_first(&priv->cmndlist))
if (cs != TAILQ_FIRST(&priv->cmndlist))
lbuf_append(lbuf, "\n");
lbuf_append(lbuf, " (");
if (!tq_empty(&cs->runasuserlist)) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist))
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
} else if (tq_empty(&cs->runasgrouplist)) {
} else if (cs->runasgrouplist == NULL) {
lbuf_append(lbuf, "%s", def_runas_default);
} else {
lbuf_append(lbuf, "%s", pw->pw_name);
}
if (!tq_empty(&cs->runasgrouplist)) {
if (cs->runasgrouplist != NULL) {
lbuf_append(lbuf, " : ");
tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m != tq_first(&cs->runasgrouplist))
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
@@ -396,7 +394,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
} else if (cs != tq_first(&priv->cmndlist)) {
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
lbuf_append(lbuf, ", ");
}
sudo_file_append_cmnd(cs, &tags, lbuf);
@@ -452,30 +450,30 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
int nfound = 0, olen;
debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
tq_foreach_fwd(&us->privileges, priv) {
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
prev_cs = NULL;
tq_foreach_fwd(&priv->cmndlist, cs) {
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (new_long_entry(cs, prev_cs)) {
lbuf_append(lbuf, _("\nSudoers entry:\n"));
lbuf_append(lbuf, _(" RunAsUsers: "));
if (!tq_empty(&cs->runasuserlist)) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist))
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
} else if (tq_empty(&cs->runasgrouplist)) {
} else if (cs->runasgrouplist == NULL) {
lbuf_append(lbuf, "%s", def_runas_default);
} else {
lbuf_append(lbuf, "%s", pw->pw_name);
}
lbuf_append(lbuf, "\n");
if (!tq_empty(&cs->runasgrouplist)) {
if (cs->runasgrouplist != NULL) {
lbuf_append(lbuf, _(" RunAsGroups: "));
tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m != tq_first(&cs->runasgrouplist))
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m, RUNASALIAS);
}
@@ -534,7 +532,7 @@ sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw,
if (nss->handle == NULL)
goto done;
tq_foreach_fwd(&userspecs, us) {
TAILQ_FOREACH(us, &userspecs, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
continue;
@@ -567,14 +565,14 @@ sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw,
else
prefix = ", ";
tq_foreach_fwd(&defaults, d) {
TAILQ_FOREACH(d, &defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
if (hostlist_matches(&d->binding) != ALLOW)
if (hostlist_matches(d->binding) != ALLOW)
continue;
break;
case DEFAULTS_USER:
if (userlist_matches(pw, &d->binding) != ALLOW)
if (userlist_matches(pw, d->binding) != ALLOW)
continue;
break;
case DEFAULTS_RUNAS:
@@ -624,7 +622,8 @@ static int
display_bound_defaults(int dtype, struct lbuf *lbuf)
{
struct defaults *d;
struct member *m, *binding = NULL;
struct member_list *binding = NULL;
struct member *m;
char *dsep;
int atype, nfound = 0;
debug_decl(display_bound_defaults, SUDO_DEBUG_NSS)
@@ -649,18 +648,18 @@ display_bound_defaults(int dtype, struct lbuf *lbuf)
default:
debug_return_int(-1);
}
tq_foreach_fwd(&defaults, d) {
TAILQ_FOREACH(d, &defaults, entries) {
if (d->type != dtype)
continue;
nfound++;
if (binding != tq_first(&d->binding)) {
binding = tq_first(&d->binding);
if (binding != d->binding) {
binding = d->binding;
if (nfound != 1)
lbuf_append(lbuf, "\n");
lbuf_append(lbuf, " Defaults%s", dsep);
for (m = binding; m != NULL; m = m->next) {
if (m != binding)
TAILQ_FOREACH(m, binding, entries) {
if (m != TAILQ_FIRST(binding))
lbuf_append(lbuf, ",");
print_member(lbuf, m, atype);
lbuf_append(lbuf, " ");
@@ -692,17 +691,17 @@ sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
goto done;
match = NULL;
tq_foreach_rev(&userspecs, us) {
TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(pw, &us->users) != ALLOW)
continue;
tq_foreach_rev(&us->privileges, priv) {
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
host_match = hostlist_matches(&priv->hostlist);
if (host_match != ALLOW)
continue;
tq_foreach_rev(&priv->cmndlist, cs) {
runas_match = runaslist_matches(&cs->runasuserlist,
&cs->runasgrouplist, NULL, NULL);
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
runas_match = runaslist_matches(cs->runasuserlist,
cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
@@ -754,8 +753,8 @@ _print_member(struct lbuf *lbuf, char *name, int type, int negated,
break;
case ALIAS:
if ((a = alias_get(name, alias_type)) != NULL) {
tq_foreach_fwd(&a->members, m) {
if (m != tq_first(&a->members))
TAILQ_FOREACH(m, &a->members, entries) {
if (m != TAILQ_FIRST(&a->members))
lbuf_append(lbuf, "%s", separator);
_print_member(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, separator,

View File

@@ -18,8 +18,6 @@
#ifndef _SUDOERS_PARSE_H
#define _SUDOERS_PARSE_H
#include "list.h" /* XXX */
#undef UNSPEC
#define UNSPEC -1
#undef DENY
@@ -86,31 +84,30 @@ struct solaris_privs_info {
* modelled after the yacc grammar.
*
* Other than the alias struct, which is stored in a red-black tree,
* the data structure used is basically a doubly-linked tail queue without
* a separate head struct--the first entry acts as the head where the prev
* pointer does double duty as the tail pointer. This makes it possible
* 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).
* the data structure used is a doubly-linked tail queue. While sudoers
* is being parsed, a headless tail queue is used where the first entry
* acts as the head and the prev pointer does double duty as the tail pointer.
* This makes it possible 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. When the tail queue is finalized, it is converted to a
* normal BSD tail queue.
*/
/*
* Tail queue list head structure.
*/
TQ_DECLARE(defaults)
TQ_DECLARE(userspec)
TQ_DECLARE(member)
TQ_DECLARE(privilege)
TQ_DECLARE(cmndspec)
TAILQ_HEAD(defaults_list, defaults);
TAILQ_HEAD(userspec_list, userspec);
TAILQ_HEAD(member_list, member);
TAILQ_HEAD(privilege_list, privilege);
TAILQ_HEAD(cmndspec_list, cmndspec);
/*
* Structure describing a user specification and list thereof.
*/
struct userspec {
struct userspec *prev, *next;
TAILQ_ENTRY(userspec) entries;
struct member_list users; /* list of users */
struct privilege_list privileges; /* list of privileges */
};
@@ -119,7 +116,7 @@ struct userspec {
* Structure describing a privilege specification.
*/
struct privilege {
struct privilege *prev, *next;
TAILQ_ENTRY(privilege) entries;
struct member_list hostlist; /* list of hosts */
struct cmndspec_list cmndlist; /* list of Cmnd_Specs */
};
@@ -128,9 +125,9 @@ struct privilege {
* Structure describing a linked list of Cmnd_Specs.
*/
struct cmndspec {
struct cmndspec *prev, *next;
struct member_list runasuserlist; /* list of runas users */
struct member_list runasgrouplist; /* list of runas groups */
TAILQ_ENTRY(cmndspec) entries;
struct member_list *runasuserlist; /* list of runas users */
struct member_list *runasgrouplist; /* list of runas groups */
struct member *cmnd; /* command to allow/deny */
char *digest; /* optional command digest */
struct cmndtag tags; /* tag specificaion */
@@ -146,7 +143,7 @@ struct cmndspec {
* Generic structure to hold users, hosts, commands.
*/
struct member {
struct member *prev, *next;
TAILQ_ENTRY(member) entries;
char *name; /* member name */
short type; /* type (see gram.h) */
short negated; /* negated via '!'? */
@@ -172,10 +169,10 @@ struct alias {
* Structure describing a Defaults entry and a list thereof.
*/
struct defaults {
struct defaults *prev, *next;
TAILQ_ENTRY(defaults) entries;
char *var; /* variable name */
char *val; /* variable value */
struct member_list binding; /* user/host/runas binding */
struct member_list *binding; /* user/host/runas binding */
int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
int op; /* true, false, '+', '-' */
};

View File

@@ -43,7 +43,7 @@
#define SUDO_ERROR_WRAP 0
#include "missing.h"
#include "list.h"
#include "queue.h"
#include "parse.h"
#include "toke.h"
#include "sudo_plugin.h"

View File

@@ -304,19 +304,19 @@ main(int argc, char *argv[])
/* This loop must match the one in sudo_file_lookup() */
printf("\nEntries for user %s:\n", user_name);
match = UNSPEC;
tq_foreach_rev(&userspecs, us) {
TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
continue;
tq_foreach_rev(&us->privileges, priv) {
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
putchar('\n');
print_privilege(priv); /* XXX */
print_privilege(priv);
putchar('\n');
host_match = hostlist_matches(&priv->hostlist);
if (host_match == ALLOW) {
puts("\thost matched");
tq_foreach_rev(&priv->cmndlist, cs) {
runas_match = runaslist_matches(&cs->runasuserlist,
&cs->runasgrouplist, NULL, NULL);
TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
runas_match = runaslist_matches(cs->runasuserlist,
cs->runasgrouplist, NULL, NULL);
if (runas_match == ALLOW) {
puts("\trunas matched");
cmnd_match = cmnd_matches(cs->cmnd);
@@ -342,6 +342,8 @@ main(int argc, char *argv[])
*/
exitcode = parse_error ? 1 : (match == ALLOW ? 0 : match + 3);
done:
sudo_endpwent();
sudo_endgrent();
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
exit(exitcode);
}
@@ -492,7 +494,7 @@ print_defaults(void)
struct member *m;
debug_decl(print_member, SUDO_DEBUG_UTIL)
tq_foreach_fwd(&defaults, d) {
TAILQ_FOREACH(d, &defaults, entries) {
(void) fputs("Defaults", stdout);
switch (d->type) {
case DEFAULTS_HOST:
@@ -508,8 +510,8 @@ print_defaults(void)
putchar('!');
break;
}
tq_foreach_fwd(&d->binding, m) {
if (m != tq_first(&d->binding))
TAILQ_FOREACH(m, d->binding, entries) {
if (m != TAILQ_FIRST(d->binding))
putchar(',');
print_member(m);
}
@@ -545,8 +547,8 @@ print_alias(void *v1, void *v2)
(void) printf("Runas_Alias\t%s = ", a->name);
break;
}
tq_foreach_fwd(&a->members, m) {
if (m != tq_first(&a->members))
TAILQ_FOREACH(m, &a->members, entries) {
if (m != TAILQ_FIRST(&a->members))
fputs(", ", stdout);
if (m->type == COMMAND) {
c = (struct sudo_command *) m->name;
@@ -567,66 +569,61 @@ print_privilege(struct privilege *priv)
{
struct cmndspec *cs;
struct member *m;
struct privilege *p;
struct cmndtag tags;
debug_decl(print_privilege, SUDO_DEBUG_UTIL)
for (p = priv; p != NULL; p = p->next) {
if (p != priv)
fputs(" : ", stdout);
tq_foreach_fwd(&p->hostlist, m) {
if (m != tq_first(&p->hostlist))
fputs(", ", stdout);
print_member(m);
}
fputs(" = ", stdout);
tags.nopasswd = UNSPEC;
tags.noexec = UNSPEC;
tq_foreach_fwd(&p->cmndlist, cs) {
if (cs != tq_first(&p->cmndlist))
fputs(", ", stdout);
if (!tq_empty(&cs->runasuserlist) || !tq_empty(&cs->runasgrouplist)) {
fputs("(", stdout);
if (!tq_empty(&cs->runasuserlist)) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist))
fputs(", ", stdout);
print_member(m);
}
} else if (tq_empty(&cs->runasgrouplist)) {
fputs(def_runas_default, stdout);
} else {
fputs(sudo_user.pw->pw_name, stdout);
TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m != TAILQ_FIRST(&priv->hostlist))
fputs(", ", stdout);
print_member(m);
}
fputs(" = ", stdout);
tags.nopasswd = UNSPEC;
tags.noexec = UNSPEC;
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (cs != TAILQ_FIRST(&priv->cmndlist))
fputs(", ", stdout);
if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) {
fputs("(", stdout);
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m != TAILQ_FIRST(cs->runasuserlist))
fputs(", ", stdout);
print_member(m);
}
if (!tq_empty(&cs->runasgrouplist)) {
fputs(" : ", stdout);
tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m != tq_first(&cs->runasgrouplist))
fputs(", ", stdout);
print_member(m);
}
}
fputs(") ", stdout);
} else if (cs->runasgrouplist == NULL) {
fputs(def_runas_default, stdout);
} else {
fputs(sudo_user.pw->pw_name, stdout);
}
if (cs->runasgrouplist != NULL) {
fputs(" : ", stdout);
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m != TAILQ_FIRST(cs->runasgrouplist))
fputs(", ", stdout);
print_member(m);
}
}
fputs(") ", stdout);
}
#ifdef HAVE_SELINUX
if (cs->role)
printf("ROLE=%s ", cs->role);
if (cs->type)
printf("TYPE=%s ", cs->type);
if (cs->role)
printf("ROLE=%s ", cs->role);
if (cs->type)
printf("TYPE=%s ", cs->type);
#endif /* HAVE_SELINUX */
#ifdef HAVE_PRIV_SET
if (cs->privs)
printf("PRIVS=%s ", cs->privs);
if (cs->limitprivs)
printf("LIMITPRIVS=%s ", cs->limitprivs);
if (cs->privs)
printf("PRIVS=%s ", cs->privs);
if (cs->limitprivs)
printf("LIMITPRIVS=%s ", cs->limitprivs);
#endif /* HAVE_PRIV_SET */
if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd)
printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec)
printf("%sEXEC: ", cs->tags.noexec ? "NO" : "");
print_member(cs->cmnd);
memcpy(&tags, &cs->tags, sizeof(tags));
}
if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd)
printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec)
printf("%sEXEC: ", cs->tags.noexec ? "NO" : "");
print_member(cs->cmnd);
memcpy(&tags, &cs->tags, sizeof(tags));
}
debug_return;
}
@@ -636,16 +633,21 @@ print_userspecs(void)
{
struct member *m;
struct userspec *us;
struct privilege *priv;
debug_decl(print_userspecs, SUDO_DEBUG_UTIL)
tq_foreach_fwd(&userspecs, us) {
tq_foreach_fwd(&us->users, m) {
if (m != tq_first(&us->users))
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) {
if (m != TAILQ_FIRST(&us->users))
fputs(", ", stdout);
print_member(m);
}
putchar('\t');
print_privilege(us->privileges.first); /* XXX */
TAILQ_FOREACH(priv, &us->privileges, entries) {
if (priv != TAILQ_FIRST(&us->privileges))
fputs(" : ", stdout);
print_privilege(priv);
}
putchar('\n');
}
debug_return;

View File

@@ -1085,7 +1085,7 @@ alias_remove_recursive(char *name, int type)
debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS)
if ((a = alias_remove(name, type)) != NULL) {
tq_foreach_fwd(&a->members, m) {
TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, type))
rval = false;
@@ -1106,7 +1106,7 @@ check_alias(char *name, int type, int strict, int quiet)
if ((a = alias_get(name, type)) != NULL) {
/* check alias contents */
tq_foreach_fwd(&a->members, m) {
TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS)
errors += check_alias(m->name, type, strict, quiet);
}
@@ -1143,7 +1143,7 @@ static int
check_aliases(bool strict, bool quiet)
{
struct cmndspec *cs;
struct member *m, *binding;
struct member *m;
struct privilege *priv;
struct userspec *us;
struct defaults *d;
@@ -1153,22 +1153,31 @@ check_aliases(bool strict, bool quiet)
alias_freelist = rbcreate(alias_compare);
/* Forward check. */
tq_foreach_fwd(&userspecs, us) {
tq_foreach_fwd(&us->users, m) {
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, USERALIAS, strict, quiet);
}
}
tq_foreach_fwd(&us->privileges, priv) {
tq_foreach_fwd(&priv->hostlist, m) {
TAILQ_FOREACH(priv, &us->privileges, entries) {
TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, HOSTALIAS, strict, quiet);
}
}
tq_foreach_fwd(&priv->cmndlist, cs) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m->type == ALIAS) {
errors += check_alias(m->name, RUNASALIAS, strict, quiet);
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, RUNASALIAS, strict, quiet);
}
}
}
if (cs->runasgrouplist != NULL) {
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m->type == ALIAS) {
errors += check_alias(m->name, RUNASALIAS, strict, quiet);
}
}
}
if ((m = cs->cmnd)->type == ALIAS) {
@@ -1179,31 +1188,35 @@ check_aliases(bool strict, bool quiet)
}
/* Reverse check (destructive) */
tq_foreach_fwd(&userspecs, us) {
tq_foreach_fwd(&us->users, m) {
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, USERALIAS))
errors++;
}
}
tq_foreach_fwd(&us->privileges, priv) {
tq_foreach_fwd(&priv->hostlist, m) {
TAILQ_FOREACH(priv, &us->privileges, entries) {
TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, HOSTALIAS))
errors++;
}
}
tq_foreach_fwd(&priv->cmndlist, cs) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, RUNASALIAS))
errors++;
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, RUNASALIAS))
errors++;
}
}
}
tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, RUNASALIAS))
errors++;
if (cs->runasgrouplist != NULL) {
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, RUNASALIAS))
errors++;
}
}
}
if ((m = cs->cmnd)->type == ALIAS) {
@@ -1213,7 +1226,7 @@ check_aliases(bool strict, bool quiet)
}
}
}
tq_foreach_fwd(&defaults, d) {
TAILQ_FOREACH(d, &defaults, entries) {
switch (d->type) {
case DEFAULTS_HOST:
atype = HOSTALIAS;
@@ -1230,12 +1243,10 @@ check_aliases(bool strict, bool quiet)
default:
continue; /* not an alias */
}
tq_foreach_fwd(&d->binding, binding) {
for (m = binding; m != NULL; m = m->next) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, atype))
errors++;
}
TAILQ_FOREACH(m, d->binding, entries) {
if (m->type == ALIAS) {
if (!alias_remove_recursive(m->name, atype))
errors++;
}
}
}