Use SLIST and STAILQ macros instead of doing headless singly linked

lists manually.  As a bonus we now use a tail queue for ldap.c and
sudoreplay.c.
This commit is contained in:
Todd C. Miller
2013-10-22 09:08:09 -06:00
parent 923edabe6c
commit f85106ea67
17 changed files with 299 additions and 311 deletions

View File

@@ -189,7 +189,8 @@ event_select.lo: $(srcdir)/event_select.c $(top_builddir)/config.h \
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_select.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_select.c
fatal.lo: $(srcdir)/fatal.c $(top_builddir)/config.h \ fatal.lo: $(srcdir)/fatal.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \ $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \
$(incdir)/fatal.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h $(incdir)/fatal.h $(incdir)/queue.h $(incdir)/sudo_plugin.h \
$(incdir)/gettext.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/fatal.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/fatal.c
fileops.lo: $(srcdir)/fileops.c $(top_builddir)/config.h \ fileops.lo: $(srcdir)/fileops.c $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/timespec.h \ $(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/timespec.h \

View File

@@ -31,17 +31,21 @@
#include "missing.h" #include "missing.h"
#include "alloc.h" #include "alloc.h"
#include "fatal.h" #include "fatal.h"
#include "queue.h"
#include "sudo_plugin.h" #include "sudo_plugin.h"
#define DEFAULT_TEXT_DOMAIN "sudo" #define DEFAULT_TEXT_DOMAIN "sudo"
#include "gettext.h" #include "gettext.h"
struct sudo_fatal_callback {
SLIST_ENTRY(sudo_fatal_callback) entries;
void (*func)(void);
};
SLIST_HEAD(sudo_fatal_callback_list, sudo_fatal_callback);
sigjmp_buf fatal_jmp; sigjmp_buf fatal_jmp;
static bool setjmp_enabled = false; static bool setjmp_enabled = false;
static struct sudo_fatal_callback { static struct sudo_fatal_callback_list callbacks;
void (*func)(void);
struct sudo_fatal_callback *next;
} *callbacks;
static void _warning(int, const char *, va_list); static void _warning(int, const char *, va_list);
@@ -51,8 +55,8 @@ do_cleanup(void)
struct sudo_fatal_callback *cb; struct sudo_fatal_callback *cb;
/* Run callbacks, removing them from the list as we go. */ /* Run callbacks, removing them from the list as we go. */
while ((cb = callbacks) != NULL) { while ((cb = SLIST_FIRST(&callbacks)) != NULL) {
callbacks = cb->next; SLIST_REMOVE_HEAD(&callbacks, entries);
cb->func(); cb->func();
free(cb); free(cb);
} }
@@ -173,8 +177,7 @@ fatal_callback_register(void (*func)(void))
if (cb == NULL) if (cb == NULL)
return -1; return -1;
cb->func = func; cb->func = func;
cb->next = callbacks; SLIST_INSERT_HEAD(&callbacks, cb, entries);
callbacks = cb;
return 0; return 0;
} }

View File

@@ -841,8 +841,8 @@ sudoreplay.o: $(srcdir)/sudoreplay.c $(top_builddir)/config.h \
$(top_srcdir)/compat/getopt.h $(top_builddir)/pathnames.h \ $(top_srcdir)/compat/getopt.h $(top_builddir)/pathnames.h \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
$(incdir)/gettext.h $(srcdir)/logging.h $(srcdir)/iolog.h \ $(incdir)/gettext.h $(srcdir)/logging.h $(srcdir)/iolog.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ $(incdir)/queue.h $(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/queue.h $(incdir)/sudo_debug.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c
testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \ testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \
$(top_srcdir)/compat/fnmatch.h $(srcdir)/tsgetgrpw.h \ $(top_srcdir)/compat/fnmatch.h $(srcdir)/tsgetgrpw.h \
@@ -903,6 +903,6 @@ visudo.o: $(srcdir)/visudo.c $(top_builddir)/config.h \
$(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \
$(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \ $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \
$(incdir)/queue.h $(incdir)/gettext.h $(srcdir)/sudoers_version.h \ $(incdir)/gettext.h $(srcdir)/sudoers_version.h \
$(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h $(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c

View File

@@ -162,9 +162,9 @@ dump_defaults(void)
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); sudo_printf(SUDO_CONV_INFO_MSG, "\n");
break; break;
case T_LIST: case T_LIST:
if (cur->sd_un.list) { if (!SLIST_EMPTY(&cur->sd_un.list)) {
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc); sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
for (item = cur->sd_un.list; item; item = item->next) { SLIST_FOREACH(item, &cur->sd_un.list, entries) {
sudo_printf(SUDO_CONV_INFO_MSG, sudo_printf(SUDO_CONV_INFO_MSG,
"\t%s\n", item->value); "\t%s\n", item->value);
} }
@@ -826,43 +826,41 @@ store_mode(char *val, struct sudo_defs_types *def, int op)
static void static void
list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op) list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
{ {
struct list_member *cur, *prev, *tmp; struct list_member *tmp, *cur, *prev = NULL;
debug_decl(list_op, SUDO_DEBUG_DEFAULTS) debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
if (op == freeall) { if (op == freeall) {
for (cur = def->sd_un.list; cur; ) { SLIST_FOREACH_SAFE(cur, &def->sd_un.list, entries, tmp) {
tmp = cur;
cur = tmp->next;
efree(tmp->value); efree(tmp->value);
efree(tmp); efree(tmp);
} }
def->sd_un.list = NULL; SLIST_INIT(&def->sd_un.list);
debug_return; debug_return;
} }
for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) { SLIST_FOREACH(cur, &def->sd_un.list, entries) {
if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) { if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
if (op == add) if (op == add)
debug_return; /* already exists */ debug_return; /* already exists */
/* Delete node */ /* Delete node */
if (prev != NULL) if (prev == NULL)
prev->next = cur->next; SLIST_REMOVE_HEAD(&def->sd_un.list, entries);
else else
def->sd_un.list = cur->next; SLIST_REMOVE_AFTER(prev, entries);
efree(cur->value); efree(cur->value);
efree(cur); efree(cur);
break; break;
} }
prev = cur;
} }
/* Add new node to the head of the list. */ /* Add new node to the head of the list. */
if (op == add) { if (op == add) {
cur = ecalloc(1, sizeof(struct list_member)); cur = ecalloc(1, sizeof(struct list_member));
cur->value = estrndup(val, len); cur->value = estrndup(val, len);
cur->next = def->sd_un.list; SLIST_INSERT_HEAD(&def->sd_un.list, cur, entries);
def->sd_un.list = cur;
} }
debug_return; debug_return;
} }

View File

@@ -25,10 +25,12 @@
#include <def_data.h> #include <def_data.h>
struct list_member { struct list_member {
SLIST_ENTRY(list_member) entries;
char *value; char *value;
struct list_member *next;
}; };
SLIST_HEAD(list_members, list_member);
struct def_values { struct def_values {
char *sval; /* string value */ char *sval; /* string value */
int ival; /* actually an enum */ int ival; /* actually an enum */
@@ -56,7 +58,7 @@ struct sudo_defs_types {
enum def_tuple tuple; enum def_tuple tuple;
char *str; char *str;
mode_t mode; mode_t mode;
struct list_member *list; struct list_members list;
} sd_un; } sd_un;
}; };

View File

@@ -558,7 +558,7 @@ matches_env_delete(const char *var)
debug_decl(matches_env_delete, SUDO_DEBUG_ENV) debug_decl(matches_env_delete, SUDO_DEBUG_ENV)
/* Skip anything listed in env_delete. */ /* Skip anything listed in env_delete. */
for (cur = def_env_delete; cur; cur = cur->next) { SLIST_FOREACH(cur, &def_env_delete, entries) {
len = strlen(cur->value); len = strlen(cur->value);
/* Deal with '*' wildcard */ /* Deal with '*' wildcard */
if (cur->value[len - 1] == '*') { if (cur->value[len - 1] == '*') {
@@ -589,7 +589,7 @@ matches_env_check(const char *var)
int keepit = -1; int keepit = -1;
debug_decl(matches_env_check, SUDO_DEBUG_ENV) debug_decl(matches_env_check, SUDO_DEBUG_ENV)
for (cur = def_env_check; cur; cur = cur->next) { SLIST_FOREACH(cur, &def_env_check, entries) {
len = strlen(cur->value); len = strlen(cur->value);
/* Deal with '*' wildcard */ /* Deal with '*' wildcard */
if (cur->value[len - 1] == '*') { if (cur->value[len - 1] == '*') {
@@ -624,7 +624,7 @@ matches_env_keep(const char *var)
goto done; goto done;
} }
for (cur = def_env_keep; cur; cur = cur->next) { SLIST_FOREACH(cur, &def_env_keep, entries) {
len = strlen(cur->value); len = strlen(cur->value);
/* Deal with '*' wildcard */ /* Deal with '*' wildcard */
if (cur->value[len - 1] == '*') { if (cur->value[len - 1] == '*') {
@@ -1085,24 +1085,21 @@ init_envtables(void)
for (p = initial_badenv_table; *p; p++) { for (p = initial_badenv_table; *p; p++) {
cur = ecalloc(1, sizeof(struct list_member)); cur = ecalloc(1, sizeof(struct list_member));
cur->value = estrdup(*p); cur->value = estrdup(*p);
cur->next = def_env_delete; SLIST_INSERT_HEAD(&def_env_delete, cur, entries);
def_env_delete = cur;
} }
/* Fill in the "env_check" list. */ /* Fill in the "env_check" list. */
for (p = initial_checkenv_table; *p; p++) { for (p = initial_checkenv_table; *p; p++) {
cur = ecalloc(1, sizeof(struct list_member)); cur = ecalloc(1, sizeof(struct list_member));
cur->value = estrdup(*p); cur->value = estrdup(*p);
cur->next = def_env_check; SLIST_INSERT_HEAD(&def_env_check, cur, entries);
def_env_check = cur;
} }
/* Fill in the "env_keep" list. */ /* Fill in the "env_keep" list. */
for (p = initial_keepenv_table; *p; p++) { for (p = initial_keepenv_table; *p; p++) {
cur = ecalloc(1, sizeof(struct list_member)); cur = ecalloc(1, sizeof(struct list_member));
cur->value = estrdup(*p); cur->value = estrdup(*p);
cur->next = def_env_keep; SLIST_INSERT_HEAD(&def_env_keep, cur, entries);
def_env_keep = cur;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010-2012 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -51,7 +51,7 @@
# define INADDR_NONE ((unsigned int)-1) # define INADDR_NONE ((unsigned int)-1)
#endif #endif
static struct interface *interfaces; static struct interface_list interfaces;
/* /*
* Parse a space-delimited list of IP address/netmask pairs and * Parse a space-delimited list of IP address/netmask pairs and
@@ -95,17 +95,16 @@ set_interfaces(const char *ai)
continue; continue;
} }
} }
ifp->next = interfaces; SLIST_INSERT_HEAD(&interfaces, ifp, entries);
interfaces = ifp;
} }
efree(addrinfo); efree(addrinfo);
debug_return; debug_return;
} }
struct interface * struct interface_list *
get_interfaces(void) get_interfaces(void)
{ {
return interfaces; return &interfaces;
} }
void void

View File

@@ -36,18 +36,20 @@ union sudo_in_addr_un {
* IP address and netmask pairs for checking against local interfaces. * IP address and netmask pairs for checking against local interfaces.
*/ */
struct interface { struct interface {
SLIST_ENTRY(interface) entries;
int family; /* AF_INET or AF_INET6 */ int family; /* AF_INET or AF_INET6 */
union sudo_in_addr_un addr; union sudo_in_addr_un addr;
union sudo_in_addr_un netmask; union sudo_in_addr_un netmask;
struct interface *next;
}; };
SLIST_HEAD(interface_list, interface);
/* /*
* Prototypes for external functions. * Prototypes for external functions.
*/ */
int get_net_ifs(char **addrinfo); int get_net_ifs(char **addrinfo);
void dump_interfaces(const char *); void dump_interfaces(const char *);
void set_interfaces(const char *); void set_interfaces(const char *);
struct interface *get_interfaces(void); struct interface_list *get_interfaces(void);
#endif /* _SUDOERS_INTERFACES_H */ #endif /* _SUDOERS_INTERFACES_H */

View File

@@ -159,13 +159,13 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength);
* The ldap_search structure implements a linked list of ldap and * The ldap_search structure implements a linked list of ldap and
* search result pointers, which allows us to remove them after * search result pointers, which allows us to remove them after
* all search results have been combined in memory. * all search results have been combined in memory.
* XXX - should probably be a tailq since we do appends
*/ */
struct ldap_search_list { struct ldap_search_result {
STAILQ_ENTRY(ldap_search_result) entries;
LDAP *ldap; LDAP *ldap;
LDAPMessage *searchresult; LDAPMessage *searchresult;
struct ldap_search_list *next;
}; };
STAILQ_HEAD(ldap_search_list, ldap_search_result);
/* /*
* The ldap_entry_wrapper structure is used to implement sorted result entries. * The ldap_entry_wrapper structure is used to implement sorted result entries.
@@ -184,7 +184,7 @@ struct ldap_entry_wrapper {
* well as an array of all result entries sorted by the sudoOrder attribute. * well as an array of all result entries sorted by the sudoOrder attribute.
*/ */
struct ldap_result { struct ldap_result {
struct ldap_search_list *searches; struct ldap_search_list searches;
struct ldap_entry_wrapper *entries; struct ldap_entry_wrapper *entries;
int allocated_entries; int allocated_entries;
int nentries; int nentries;
@@ -200,11 +200,13 @@ struct ldap_config_table {
void *valp; /* pointer into ldap_conf */ void *valp; /* pointer into ldap_conf */
}; };
struct ldap_config_list_str { struct ldap_config_str {
struct ldap_config_list_str *next; STAILQ_ENTRY(ldap_config_str) entries;
char val[1]; char val[1];
}; };
STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
/* LDAP configuration structure */ /* LDAP configuration structure */
static struct ldap_config { static struct ldap_config {
int port; int port;
@@ -221,11 +223,11 @@ static struct ldap_config {
int timed; int timed;
int deref; int deref;
char *host; char *host;
struct ldap_config_list_str *uri; struct ldap_config_str_list uri;
char *binddn; char *binddn;
char *bindpw; char *bindpw;
char *rootbinddn; char *rootbinddn;
struct ldap_config_list_str *base; struct ldap_config_str_list base;
char *search_filter; char *search_filter;
char *ssl; char *ssl;
char *tls_cacertfile; char *tls_cacertfile;
@@ -433,16 +435,17 @@ toobig:
* where the trailing slash is optional. * where the trailing slash is optional.
*/ */
static int static int
sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list) sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
{ {
const struct ldap_config_str *entry;
char *buf, *uri, *host, *cp, *port; char *buf, *uri, *host, *cp, *port;
char hostbuf[LINE_MAX]; char hostbuf[LINE_MAX];
int nldap = 0, nldaps = 0; int nldap = 0, nldaps = 0;
int rc = -1; int rc = -1;
debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP)
do { STAILQ_FOREACH(entry, uri_list, entries) {
buf = estrdup(uri_list->val); buf = estrdup(entry->val);
hostbuf[0] = '\0'; hostbuf[0] = '\0';
for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) { for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
if (strncasecmp(uri, "ldap://", 7) == 0) { if (strncasecmp(uri, "ldap://", 7) == 0) {
@@ -481,7 +484,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
} }
} }
if (hostbuf[0] == '\0') { if (hostbuf[0] == '\0') {
warningx(_("invalid uri: %s"), uri_list->val); warningx(_("invalid uri: %s"), entry->val);
goto done; goto done;
} }
@@ -500,7 +503,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
efree(ldap_conf.host); efree(ldap_conf.host);
ldap_conf.host = estrdup(hostbuf); ldap_conf.host = estrdup(hostbuf);
efree(buf); efree(buf);
} while ((uri_list = uri_list->next)); }
buf = NULL; buf = NULL;
rc = 0; rc = 0;
@@ -514,23 +517,24 @@ toobig:
} }
#else #else
static char * static char *
sudo_ldap_join_uri(struct ldap_config_list_str *uri_list) sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
{ {
struct ldap_config_list_str *uri; struct ldap_config_str *uri;
size_t len = 0; size_t len = 0;
char *buf, *cp; char *buf, *cp;
debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP)
/* Usually just a single entry. */ /* Usually just a single entry. */
if (uri_list->next == NULL) if (STAILQ_NEXT(STAILQ_FIRST(uri_list), entries) == NULL)
debug_return_str(estrdup(uri_list->val)); debug_return_str(estrdup(STAILQ_FIRST(uri_list)->val));
for (uri = uri_list; uri != NULL; uri = uri->next) { /* Multiple entries. */
STAILQ_FOREACH(uri, uri_list, entries) {
len += strlen(uri->val) + 1; len += strlen(uri->val) + 1;
} }
buf = cp = emalloc(len); buf = cp = emalloc(len);
buf[0] = '\0'; buf[0] = '\0';
for (uri = uri_list; uri != NULL; uri = uri->next) { STAILQ_FOREACH(uri, uri_list, entries) {
cp += strlcpy(cp, uri->val, len - (cp - buf)); cp += strlcpy(cp, uri->val, len - (cp - buf));
*cp++ = ' '; *cp++ = ' ';
} }
@@ -1420,16 +1424,15 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
break; break;
case CONF_LIST_STR: case CONF_LIST_STR:
{ {
struct ldap_config_list_str **p; struct ldap_config_str_list *head;
struct ldap_config_str *str;
size_t len = strlen(value); size_t len = strlen(value);
if (len > 0) { if (len > 0) {
p = (struct ldap_config_list_str **)cur->valp; head = (struct ldap_config_str_list *)cur->valp;
while (*p != NULL) str = emalloc(sizeof(*str) + len);
p = &(*p)->next; memcpy(str->val, value, len + 1);
*p = emalloc(sizeof(struct ldap_config_list_str) + len); STAILQ_INSERT_TAIL(head, str, entries);
memcpy((*p)->val, value, len + 1);
(*p)->next = NULL;
} }
} }
break; break;
@@ -1513,6 +1516,8 @@ sudo_ldap_read_config(void)
ldap_conf.use_sasl = -1; ldap_conf.use_sasl = -1;
ldap_conf.rootuse_sasl = -1; ldap_conf.rootuse_sasl = -1;
ldap_conf.deref = -1; ldap_conf.deref = -1;
STAILQ_INIT(&ldap_conf.uri);
STAILQ_INIT(&ldap_conf.base);
if ((fp = fopen(path_ldap_conf, "r")) == NULL) if ((fp = fopen(path_ldap_conf, "r")) == NULL)
debug_return_bool(false); debug_return_bool(false);
@@ -1545,12 +1550,12 @@ sudo_ldap_read_config(void)
DPRINTF1("LDAP Config Summary"); DPRINTF1("LDAP Config Summary");
DPRINTF1("==================="); DPRINTF1("===================");
if (ldap_conf.uri) { if (!STAILQ_EMPTY(&ldap_conf.uri)) {
struct ldap_config_list_str *uri = ldap_conf.uri; struct ldap_config_str *uri;
do { STAILQ_FOREACH(uri, &ldap_conf.uri, entries) {
DPRINTF1("uri %s", uri->val); DPRINTF1("uri %s", uri->val);
} while ((uri = uri->next) != NULL); }
} else { } else {
DPRINTF1("host %s", DPRINTF1("host %s",
ldap_conf.host ? ldap_conf.host : "(NONE)"); ldap_conf.host ? ldap_conf.host : "(NONE)");
@@ -1558,11 +1563,11 @@ sudo_ldap_read_config(void)
} }
DPRINTF1("ldap_version %d", ldap_conf.version); DPRINTF1("ldap_version %d", ldap_conf.version);
if (ldap_conf.base) { if (!STAILQ_EMPTY(&ldap_conf.base)) {
struct ldap_config_list_str *base = ldap_conf.base; struct ldap_config_str *base;
do { STAILQ_FOREACH(base, &ldap_conf.base, entries) {
DPRINTF1("sudoers_base %s", base->val); DPRINTF1("sudoers_base %s", base->val);
} while ((base = base->next) != NULL); }
} else { } else {
DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)"); DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)");
} }
@@ -1622,7 +1627,7 @@ sudo_ldap_read_config(void)
#endif #endif
DPRINTF1("==================="); DPRINTF1("===================");
if (!ldap_conf.base) if (STAILQ_EMPTY(&ldap_conf.base))
debug_return_bool(false); /* if no base is defined, ignore LDAP */ debug_return_bool(false); /* if no base is defined, ignore LDAP */
if (ldap_conf.bind_timelimit > 0) if (ldap_conf.bind_timelimit > 0)
@@ -1647,19 +1652,20 @@ sudo_ldap_read_config(void)
#ifndef HAVE_LDAP_INITIALIZE #ifndef HAVE_LDAP_INITIALIZE
/* Convert uri list to host list if no ldap_initialize(). */ /* Convert uri list to host list if no ldap_initialize(). */
if (ldap_conf.uri) { if (!STAILQ_EMPTY(&ldap_conf.uri)) {
struct ldap_config_list_str *uri = ldap_conf.uri; struct ldap_config_str *uri;
if (sudo_ldap_parse_uri(uri) != 0)
if (sudo_ldap_parse_uri(&ldap_conf.uri) != 0)
debug_return_bool(false); debug_return_bool(false);
do { while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
ldap_conf.uri = uri->next; STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
efree(uri); efree(uri);
} while ((uri = ldap_conf.uri)); }
ldap_conf.port = LDAP_PORT; ldap_conf.port = LDAP_PORT;
} }
#endif #endif
if (!ldap_conf.uri) { if (STAILQ_EMPTY(&ldap_conf.uri)) {
/* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */ /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */
if (ldap_conf.port < 0) if (ldap_conf.port < 0)
ldap_conf.port = ldap_conf.port =
@@ -1744,7 +1750,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
{ {
struct berval **bv, **p; struct berval **bv, **p;
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
struct ldap_config_list_str *base; struct ldap_config_str *base;
struct sudo_ldap_handle *handle = nss->handle; struct sudo_ldap_handle *handle = nss->handle;
LDAP *ld; LDAP *ld;
LDAPMessage *entry, *result; LDAPMessage *entry, *result;
@@ -1757,7 +1763,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
ld = handle->ld; ld = handle->ld;
filt = sudo_ldap_build_default_filter(); filt = sudo_ldap_build_default_filter();
for (base = ldap_conf.base; base != NULL; base = base->next) { STAILQ_FOREACH(base, &ldap_conf.base, entries) {
if (ldap_conf.timeout > 0) { if (ldap_conf.timeout > 0) {
tv.tv_sec = ldap_conf.timeout; tv.tv_sec = ldap_conf.timeout;
tv.tv_usec = 0; tv.tv_usec = 0;
@@ -2299,7 +2305,10 @@ sudo_ldap_result_alloc(void)
struct ldap_result *result; struct ldap_result *result;
debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP)
debug_return_ptr(ecalloc(1, sizeof(*result))); result = ecalloc(1, sizeof(*result));
STAILQ_INIT(&result->searches);
debug_return_ptr(result);
} }
/* /*
@@ -2308,7 +2317,7 @@ sudo_ldap_result_alloc(void)
static void static void
sudo_ldap_result_free(struct ldap_result *lres) sudo_ldap_result_free(struct ldap_result *lres)
{ {
struct ldap_search_list *s; struct ldap_search_result *s;
debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP)
if (lres != NULL) { if (lres != NULL) {
@@ -2316,13 +2325,11 @@ sudo_ldap_result_free(struct ldap_result *lres)
efree(lres->entries); efree(lres->entries);
lres->entries = NULL; lres->entries = NULL;
} }
if (lres->searches) { while ((s = STAILQ_FIRST(&lres->searches)) != NULL) {
while ((s = lres->searches) != NULL) { STAILQ_REMOVE_HEAD(&lres->searches, entries);
ldap_msgfree(s->searchresult); ldap_msgfree(s->searchresult);
lres->searches = s->next;
efree(s); efree(s);
} }
}
efree(lres); efree(lres);
} }
debug_return; debug_return;
@@ -2331,26 +2338,19 @@ sudo_ldap_result_free(struct ldap_result *lres)
/* /*
* Add a search result to the ldap_result structure. * Add a search result to the ldap_result structure.
*/ */
static struct ldap_search_list * static struct ldap_search_result *
sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap, sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
LDAPMessage *searchresult) LDAPMessage *searchresult)
{ {
struct ldap_search_list *s, *news; struct ldap_search_result *news;
debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP)
news = ecalloc(1, sizeof(struct ldap_search_list)); /* Create new entry and add it to the end of the chain. */
news = ecalloc(1, sizeof(*news));
news->ldap = ldap; news->ldap = ldap;
news->searchresult = searchresult; news->searchresult = searchresult;
/* news->next = NULL; */ STAILQ_INSERT_TAIL(&lres->searches, news, entries);
/* Add entry to the end of the chain (XXX - tailq instead?). */
if (lres->searches) {
for (s = lres->searches; s->next != NULL; s = s->next)
continue;
s->next = news;
} else {
lres->searches = news;
}
debug_return_ptr(news); debug_return_ptr(news);
} }
@@ -2471,8 +2471,8 @@ sudo_ldap_open(struct sudo_nss *nss)
/* Connect to LDAP server */ /* Connect to LDAP server */
#ifdef HAVE_LDAP_INITIALIZE #ifdef HAVE_LDAP_INITIALIZE
if (ldap_conf.uri != NULL) { if (!STAILQ_EMPTY(&ldap_conf.uri)) {
char *buf = sudo_ldap_join_uri(ldap_conf.uri); char *buf = sudo_ldap_join_uri(&ldap_conf.uri);
DPRINTF2("ldap_initialize(ld, %s)", buf); DPRINTF2("ldap_initialize(ld, %s)", buf);
rc = ldap_initialize(&ld, buf); rc = ldap_initialize(&ld, buf);
efree(buf); efree(buf);
@@ -2537,7 +2537,7 @@ sudo_ldap_open(struct sudo_nss *nss)
static int static int
sudo_ldap_setdefs(struct sudo_nss *nss) sudo_ldap_setdefs(struct sudo_nss *nss)
{ {
struct ldap_config_list_str *base; struct ldap_config_str *base;
struct sudo_ldap_handle *handle = nss->handle; struct sudo_ldap_handle *handle = nss->handle;
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
LDAP *ld; LDAP *ld;
@@ -2553,7 +2553,7 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
filt = sudo_ldap_build_default_filter(); filt = sudo_ldap_build_default_filter();
DPRINTF1("Looking for cn=defaults: %s", filt); DPRINTF1("Looking for cn=defaults: %s", filt);
for (base = ldap_conf.base; base != NULL; base = base->next) { STAILQ_FOREACH(base, &ldap_conf.base, entries) {
if (ldap_conf.timeout > 0) { if (ldap_conf.timeout > 0) {
tv.tv_sec = ldap_conf.timeout; tv.tv_sec = ldap_conf.timeout;
tv.tv_usec = 0; tv.tv_usec = 0;
@@ -2713,21 +2713,15 @@ ldap_entry_compare(const void *a, const void *b)
} }
/* /*
* Find the last entry in the list of searches, usually the * Return the last entry in the list of searches, usually the
* one currently being used to add entries. * one currently being used to add entries.
* XXX - use a tailq instead?
*/ */
static struct ldap_search_list * static struct ldap_search_result *
sudo_ldap_result_last_search(struct ldap_result *lres) sudo_ldap_result_last_search(struct ldap_result *lres)
{ {
struct ldap_search_list *result = lres->searches;
debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP)
if (result) { debug_return_ptr(STAILQ_LAST(&lres->searches, ldap_search_result, entries));
while (result->next)
result = result->next;
}
debug_return_ptr(result);
} }
/* /*
@@ -2736,7 +2730,7 @@ sudo_ldap_result_last_search(struct ldap_result *lres)
static struct ldap_entry_wrapper * static struct ldap_entry_wrapper *
sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry) sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
{ {
struct ldap_search_list *last; struct ldap_search_result *last;
struct berval **bv; struct berval **bv;
double order = 0.0; double order = 0.0;
char *ep; char *ep;
@@ -2806,7 +2800,7 @@ static struct ldap_result *
sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
{ {
struct sudo_ldap_handle *handle = nss->handle; struct sudo_ldap_handle *handle = nss->handle;
struct ldap_config_list_str *base; struct ldap_config_str *base;
struct ldap_result *lres; struct ldap_result *lres;
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
LDAPMessage *entry, *result; LDAPMessage *entry, *result;
@@ -2854,7 +2848,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
for (pass = 0; pass < 2; pass++) { for (pass = 0; pass < 2; pass++) {
filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw); filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw);
DPRINTF1("ldap search '%s'", filt); DPRINTF1("ldap search '%s'", filt);
for (base = ldap_conf.base; base != NULL; base = base->next) { STAILQ_FOREACH(base, &ldap_conf.base, entries) {
DPRINTF1("searching from base '%s'", DPRINTF1("searching from base '%s'",
base->val); base->val);
if (ldap_conf.timeout > 0) { if (ldap_conf.timeout > 0) {
@@ -2957,7 +2951,7 @@ sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult)
* Build a new list node for the search result, this creates the * Build a new list node for the search result, this creates the
* list node. * list node.
*/ */
struct ldap_search_list *last = sudo_ldap_result_add_search(result, struct ldap_search_result *last = sudo_ldap_result_add_search(result,
ldap, searchresult); ldap, searchresult);
/* /*

View File

@@ -70,7 +70,7 @@ addr_matches_if(char *n)
addr.ip4.s_addr = inet_addr(n); addr.ip4.s_addr = inet_addr(n);
} }
for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) { SLIST_FOREACH(ifp, get_interfaces(), entries) {
if (ifp->family != family) if (ifp->family != family)
continue; continue;
switch (family) { switch (family) {
@@ -153,7 +153,7 @@ addr_matches_if_netmask(char *n, char *m)
} }
#endif /* HAVE_STRUCT_IN6_ADDR */ #endif /* HAVE_STRUCT_IN6_ADDR */
for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) { SLIST_FOREACH(ifp, get_interfaces(), entries) {
if (ifp->family != family) if (ifp->family != family)
continue; continue;
switch (family) { switch (family) {

View File

@@ -101,6 +101,7 @@
#include "gettext.h" #include "gettext.h"
#include "logging.h" #include "logging.h"
#include "iolog.h" #include "iolog.h"
#include "queue.h"
#include "sudo_plugin.h" #include "sudo_plugin.h"
#include "sudo_conf.h" #include "sudo_conf.h"
#include "sudo_debug.h" #include "sudo_debug.h"
@@ -128,8 +129,9 @@ struct log_info {
* Handle expressions like: * Handle expressions like:
* ( user millert or user root ) and tty console and command /bin/sh * ( user millert or user root ) and tty console and command /bin/sh
*/ */
static struct search_node { STAILQ_HEAD(search_node_list, search_node);
struct search_node *next; struct search_node {
STAILQ_ENTRY(search_node) entries;
#define ST_EXPR 1 #define ST_EXPR 1
#define ST_TTY 2 #define ST_TTY 2
#define ST_USER 3 #define ST_USER 3
@@ -140,9 +142,8 @@ static struct search_node {
#define ST_TODATE 8 #define ST_TODATE 8
#define ST_CWD 9 #define ST_CWD 9
char type; char type;
char negated; bool negated;
char or; bool or;
char pad;
union { union {
#ifdef HAVE_REGCOMP #ifdef HAVE_REGCOMP
regex_t cmdre; regex_t cmdre;
@@ -154,14 +155,12 @@ static struct search_node {
char *pattern; char *pattern;
char *runas_group; char *runas_group;
char *runas_user; char *runas_user;
struct search_node *expr; struct search_node_list expr;
void *ptr; void *ptr;
} u; } u;
} *search_expr; };
#define STACK_NODE_SIZE 32 static struct search_node_list search_expr = STAILQ_HEAD_INITIALIZER(search_expr);
static struct search_node *node_stack[32];
static int stack_top;
static int timing_idx_adj = 0; static int timing_idx_adj = 0;
@@ -186,7 +185,7 @@ extern int term_restore(int, int);
extern void get_ttysize(int *rowp, int *colp); extern void get_ttysize(int *rowp, int *colp);
static int list_sessions(int, char **, const char *, const char *, const char *); static int list_sessions(int, char **, const char *, const char *, const char *);
static int parse_expr(struct search_node **, char **); static int parse_expr(struct search_node_list *, char **, bool);
static void check_input(int, double *); static void check_input(int, double *);
static void delay(double); static void delay(double);
static void help(void) __attribute__((__noreturn__)); static void help(void) __attribute__((__noreturn__));
@@ -606,14 +605,14 @@ atomic_writev(int fd, struct iovec *iov, int iovcnt)
* Build expression list from search args * Build expression list from search args
*/ */
static int static int
parse_expr(struct search_node **headp, char *argv[]) parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
{ {
struct search_node *sn, *newsn; bool or = false, not = false;
char or = 0, not = 0, type, **av; struct search_node *sn;
char type, **av;
debug_decl(parse_expr, SUDO_DEBUG_UTIL) debug_decl(parse_expr, SUDO_DEBUG_UTIL)
sn = *headp; for (av = argv; *av != NULL; av++) {
for (av = argv; *av; av++) {
switch (av[0][0]) { switch (av[0][0]) {
case 'a': /* and (ignore) */ case 'a': /* and (ignore) */
if (strncmp(*av, "and", strlen(*av)) != 0) if (strncmp(*av, "and", strlen(*av)) != 0)
@@ -622,12 +621,12 @@ parse_expr(struct search_node **headp, char *argv[])
case 'o': /* or */ case 'o': /* or */
if (strncmp(*av, "or", strlen(*av)) != 0) if (strncmp(*av, "or", strlen(*av)) != 0)
goto bad; goto bad;
or = 1; or = true;
continue; continue;
case '!': /* negate */ case '!': /* negate */
if (av[0][1] != '\0') if (av[0][1] != '\0')
goto bad; goto bad;
not = 1; not = true;
continue; continue;
case 'c': /* command */ case 'c': /* command */
if (av[0][1] == '\0') if (av[0][1] == '\0')
@@ -672,21 +671,13 @@ parse_expr(struct search_node **headp, char *argv[])
case '(': /* start sub-expression */ case '(': /* start sub-expression */
if (av[0][1] != '\0') if (av[0][1] != '\0')
goto bad; goto bad;
if (stack_top + 1 == STACK_NODE_SIZE) {
fatalx(_("too many parenthesized expressions, max %d"),
STACK_NODE_SIZE);
}
node_stack[stack_top++] = sn;
type = ST_EXPR; type = ST_EXPR;
break; break;
case ')': /* end sub-expression */ case ')': /* end sub-expression */
if (av[0][1] != '\0') if (av[0][1] != '\0')
goto bad; goto bad;
/* pop */ if (!sub_expr)
if (--stack_top < 0)
fatalx(_("unmatched ')' in expression")); fatalx(_("unmatched ')' in expression"));
if (node_stack[stack_top])
sn->next = node_stack[stack_top]->next;
debug_return_int(av - argv + 1); debug_return_int(av - argv + 1);
bad: bad:
default: default:
@@ -695,38 +686,34 @@ parse_expr(struct search_node **headp, char *argv[])
} }
/* Allocate new search node */ /* Allocate new search node */
newsn = ecalloc(1, sizeof(*newsn)); sn = ecalloc(1, sizeof(*sn));
newsn->type = type; sn->type = type;
newsn->or = or; sn->or = or;
newsn->negated = not; sn->negated = not;
/* newsn->next = NULL; */
if (type == ST_EXPR) { if (type == ST_EXPR) {
av += parse_expr(&newsn->u.expr, av + 1); STAILQ_INIT(&sn->u.expr);
av += parse_expr(&sn->u.expr, av + 1, true);
} else { } else {
if (*(++av) == NULL) if (*(++av) == NULL)
fatalx(_("%s requires an argument"), av[-1]); fatalx(_("%s requires an argument"), av[-1]);
#ifdef HAVE_REGCOMP #ifdef HAVE_REGCOMP
if (type == ST_PATTERN) { if (type == ST_PATTERN) {
if (regcomp(&newsn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0) if (regcomp(&sn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0)
fatalx(_("invalid regular expression: %s"), *av); fatalx(_("invalid regular expression: %s"), *av);
} else } else
#endif #endif
if (type == ST_TODATE || type == ST_FROMDATE) { if (type == ST_TODATE || type == ST_FROMDATE) {
newsn->u.tstamp = get_date(*av); sn->u.tstamp = get_date(*av);
if (newsn->u.tstamp == -1) if (sn->u.tstamp == -1)
fatalx(_("could not parse date \"%s\""), *av); fatalx(_("could not parse date \"%s\""), *av);
} else { } else {
newsn->u.ptr = *av; sn->u.ptr = *av;
} }
} }
not = or = 0; /* reset state */ not = or = false; /* reset state */
if (sn) STAILQ_INSERT_TAIL(head, sn, entries);
sn->next = newsn;
else
*headp = newsn;
sn = newsn;
} }
if (stack_top) if (sub_expr)
fatalx(_("unmatched '(' in expression")); fatalx(_("unmatched '(' in expression"));
if (or) if (or)
fatalx(_("illegal trailing \"or\"")); fatalx(_("illegal trailing \"or\""));
@@ -737,17 +724,17 @@ parse_expr(struct search_node **headp, char *argv[])
} }
static bool static bool
match_expr(struct search_node *head, struct log_info *log, bool last_match) match_expr(struct search_node_list *head, struct log_info *log, bool last_match)
{ {
struct search_node *sn; struct search_node *sn;
bool res, matched = last_match; bool res, matched = last_match;
int rc; int rc;
debug_decl(match_expr, SUDO_DEBUG_UTIL) debug_decl(match_expr, SUDO_DEBUG_UTIL)
for (sn = head; sn; sn = sn->next) { STAILQ_FOREACH(sn, head, entries) {
switch (sn->type) { switch (sn->type) {
case ST_EXPR: case ST_EXPR:
res = match_expr(sn->u.expr, log, matched); res = match_expr(&sn->u.expr, log, matched);
break; break;
case ST_CWD: case ST_CWD:
res = strcmp(sn->u.cwd, log->cwd) == 0; res = strcmp(sn->u.cwd, log->cwd) == 0;
@@ -909,7 +896,7 @@ list_session(char *logfile, REGEX_T *re, const char *user, const char *tty)
goto done; goto done;
/* Match on search expression if there is one. */ /* Match on search expression if there is one. */
if (search_expr && !match_expr(search_expr, li, true)) if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, li, true))
goto done; goto done;
/* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */ /* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */
@@ -1042,7 +1029,7 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user,
debug_decl(list_sessions, SUDO_DEBUG_UTIL) debug_decl(list_sessions, SUDO_DEBUG_UTIL)
/* Parse search expression if present */ /* Parse search expression if present */
parse_expr(&search_expr, argv); parse_expr(&search_expr, argv, false);
#ifdef HAVE_REGCOMP #ifdef HAVE_REGCOMP
/* optional regex */ /* optional regex */

View File

@@ -3983,37 +3983,42 @@ int main()
#line 725 "toke.l" #line 725 "toke.l"
struct path_list { struct path_list {
SLIST_ENTRY(path_list) entries;
char *path; char *path;
struct path_list *next;
}; };
SLIST_HEAD(path_list_head, path_list);
struct include_stack { struct include_stack {
YY_BUFFER_STATE bs; YY_BUFFER_STATE bs;
char *path; char *path;
struct path_list *more; /* more files in case of includedir */ struct path_list_head more; /* more files in case of includedir */
int lineno; int lineno;
bool keepopen; bool keepopen;
}; };
/*
* Compare two struct path_list structs in reverse order.
*/
static int static int
pl_compare(const void *v1, const void *v2) pl_compare(const void *v1, const void *v2)
{ {
const struct path_list * const *p1 = v1; const struct path_list * const *p1 = v1;
const struct path_list * const *p2 = v2; const struct path_list * const *p2 = v2;
return strcmp((*p1)->path, (*p2)->path); return strcmp((*p2)->path, (*p1)->path);
} }
static char * static char *
switch_dir(struct include_stack *stack, char *dirpath) switch_dir(struct include_stack *stack, char *dirpath)
{ {
DIR *dir; DIR *dir;
int i, count = 0; unsigned int i, count = 0;
unsigned int max_paths = 32;
char *path = NULL; char *path = NULL;
struct dirent *dent; struct dirent *dent;
struct stat sb; struct stat sb;
struct path_list *pl, *first = NULL; struct path_list *pl, **paths = NULL;
struct path_list **sorted = NULL;
debug_decl(switch_dir, SUDO_DEBUG_PARSER) debug_decl(switch_dir, SUDO_DEBUG_PARSER)
if (!(dir = opendir(dirpath))) { if (!(dir = opendir(dirpath))) {
@@ -4023,6 +4028,11 @@ switch_dir(struct include_stack *stack, char *dirpath)
} }
goto done; goto done;
} }
paths = malloc(sizeof(*paths) * max_paths);
if (paths == NULL) {
closedir(dir);
goto bad;
}
while ((dent = readdir(dir))) { while ((dent = readdir(dir))) {
/* Ignore files that end in '~' or have a '.' in them. */ /* Ignore files that end in '~' or have a '.' in them. */
if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
@@ -4042,54 +4052,47 @@ switch_dir(struct include_stack *stack, char *dirpath)
if (pl == NULL) if (pl == NULL)
goto bad; goto bad;
pl->path = path; pl->path = path;
pl->next = first; if (count >= max_paths) {
first = pl; struct path_list **tmp;
max_paths <<= 1;
tmp = realloc(paths, sizeof(*paths) * max_paths);
if (tmp == NULL) {
closedir(dir);
goto bad;
}
paths = tmp;
}
paths[count++] = pl;
path = NULL; path = NULL;
count++;
} }
closedir(dir); closedir(dir);
if (count == 0) if (count == 0)
goto done; goto done;
/* Sort the list as an array. */ /* Sort the list as an array in reverse order. */
sorted = malloc(sizeof(*sorted) * count); qsort(paths, count, sizeof(*paths), pl_compare);
if (sorted == NULL)
goto bad;
pl = first;
for (i = 0; i < count; i++) {
sorted[i] = pl;
pl = pl->next;
}
qsort(sorted, count, sizeof(*sorted), pl_compare);
/* Apply sorting to the list. */ /* Build up the list in sorted order. */
first = sorted[0]; for (i = 0; i < count; i++) {
sorted[count - 1]->next = NULL; SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
for (i = 1; i < count; i++) }
sorted[i - 1]->next = sorted[i];
efree(sorted);
/* Pull out the first element for parsing, leave the rest for later. */ /* Pull out the first element for parsing, leave the rest for later. */
if (count) { pl = SLIST_FIRST(&stack->more);
path = first->path; SLIST_REMOVE_HEAD(&stack->more, entries);
pl = first->next; path = pl->path;
efree(first); efree(pl);
stack->more = pl;
} else {
path = NULL;
}
done: done:
efree(paths);
efree(dirpath); efree(dirpath);
debug_return_str(path); debug_return_str(path);
bad: bad:
while (first != NULL) { for (i = 0; i < count; i++) {
pl = first; efree(paths[i]->path);
first = pl->next; efree(paths[i]);
efree(pl->path);
efree(pl);
} }
efree(sorted); efree(paths);
efree(dirpath); efree(dirpath);
efree(path); efree(path);
debug_return_str(NULL); debug_return_str(NULL);
@@ -4110,8 +4113,8 @@ init_lexer(void)
while (idepth) { while (idepth) {
idepth--; idepth--;
while ((pl = istack[idepth].more) != NULL) { while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
istack[idepth].more = pl->next; SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
efree(pl->path); efree(pl->path);
efree(pl); efree(pl);
} }
@@ -4154,6 +4157,7 @@ _push_include(char *path, bool isdir)
debug_return_bool(false); debug_return_bool(false);
} }
} }
SLIST_INIT(&istack[idepth].more);
if (isdir) { if (isdir) {
struct stat sb; struct stat sb;
switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) { switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) {
@@ -4197,10 +4201,10 @@ _push_include(char *path, bool isdir)
while ((fp = open_sudoers(path, false, &keepopen)) == NULL) { while ((fp = open_sudoers(path, false, &keepopen)) == NULL) {
/* Unable to open path in includedir, go to next one, if any. */ /* Unable to open path in includedir, go to next one, if any. */
efree(path); efree(path);
if ((pl = istack[idepth].more) == NULL) if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL)
debug_return_bool(false); debug_return_bool(false);
SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
path = pl->path; path = pl->path;
istack[idepth].more = pl->next;
efree(pl); efree(pl);
} }
} else { } else {
@@ -4209,7 +4213,6 @@ _push_include(char *path, bool isdir)
sudoerserror(NULL); sudoerserror(NULL);
debug_return_bool(false); debug_return_bool(false);
} }
istack[idepth].more = NULL;
} }
/* Push the old (current) file and open the new one. */ /* Push the old (current) file and open the new one. */
istack[idepth].path = sudoers; /* push old path */ istack[idepth].path = sudoers; /* push old path */
@@ -4238,10 +4241,10 @@ pop_include(void)
fclose(YY_CURRENT_BUFFER->yy_input_file); fclose(YY_CURRENT_BUFFER->yy_input_file);
sudoers_delete_buffer(YY_CURRENT_BUFFER); sudoers_delete_buffer(YY_CURRENT_BUFFER);
/* If we are in an include dir, move to the next file. */ /* If we are in an include dir, move to the next file. */
while ((pl = istack[idepth - 1].more) != NULL) { while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
fp = open_sudoers(pl->path, false, &keepopen); fp = open_sudoers(pl->path, false, &keepopen);
if (fp != NULL) { if (fp != NULL) {
istack[idepth - 1].more = pl->next;
efree(sudoers); efree(sudoers);
sudoers = pl->path; sudoers = pl->path;
sudolineno = 1; sudolineno = 1;
@@ -4250,7 +4253,6 @@ pop_include(void)
break; break;
} }
/* Unable to open path in include dir, go to next one. */ /* Unable to open path in include dir, go to next one. */
istack[idepth - 1].more = pl->next;
efree(pl->path); efree(pl->path);
efree(pl); efree(pl);
} }

View File

@@ -724,37 +724,42 @@ sudoedit {
%% %%
struct path_list { struct path_list {
SLIST_ENTRY(path_list) entries;
char *path; char *path;
struct path_list *next;
}; };
SLIST_HEAD(path_list_head, path_list);
struct include_stack { struct include_stack {
YY_BUFFER_STATE bs; YY_BUFFER_STATE bs;
char *path; char *path;
struct path_list *more; /* more files in case of includedir */ struct path_list_head more; /* more files in case of includedir */
int lineno; int lineno;
bool keepopen; bool keepopen;
}; };
/*
* Compare two struct path_list structs in reverse order.
*/
static int static int
pl_compare(const void *v1, const void *v2) pl_compare(const void *v1, const void *v2)
{ {
const struct path_list * const *p1 = v1; const struct path_list * const *p1 = v1;
const struct path_list * const *p2 = v2; const struct path_list * const *p2 = v2;
return strcmp((*p1)->path, (*p2)->path); return strcmp((*p2)->path, (*p1)->path);
} }
static char * static char *
switch_dir(struct include_stack *stack, char *dirpath) switch_dir(struct include_stack *stack, char *dirpath)
{ {
DIR *dir; DIR *dir;
int i, count = 0; unsigned int i, count = 0;
unsigned int max_paths = 32;
char *path = NULL; char *path = NULL;
struct dirent *dent; struct dirent *dent;
struct stat sb; struct stat sb;
struct path_list *pl, *first = NULL; struct path_list *pl, **paths = NULL;
struct path_list **sorted = NULL;
debug_decl(switch_dir, SUDO_DEBUG_PARSER) debug_decl(switch_dir, SUDO_DEBUG_PARSER)
if (!(dir = opendir(dirpath))) { if (!(dir = opendir(dirpath))) {
@@ -764,6 +769,11 @@ switch_dir(struct include_stack *stack, char *dirpath)
} }
goto done; goto done;
} }
paths = malloc(sizeof(*paths) * max_paths);
if (paths == NULL) {
closedir(dir);
goto bad;
}
while ((dent = readdir(dir))) { while ((dent = readdir(dir))) {
/* Ignore files that end in '~' or have a '.' in them. */ /* Ignore files that end in '~' or have a '.' in them. */
if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
@@ -783,54 +793,47 @@ switch_dir(struct include_stack *stack, char *dirpath)
if (pl == NULL) if (pl == NULL)
goto bad; goto bad;
pl->path = path; pl->path = path;
pl->next = first; if (count >= max_paths) {
first = pl; struct path_list **tmp;
max_paths <<= 1;
tmp = realloc(paths, sizeof(*paths) * max_paths);
if (tmp == NULL) {
closedir(dir);
goto bad;
}
paths = tmp;
}
paths[count++] = pl;
path = NULL; path = NULL;
count++;
} }
closedir(dir); closedir(dir);
if (count == 0) if (count == 0)
goto done; goto done;
/* Sort the list as an array. */ /* Sort the list as an array in reverse order. */
sorted = malloc(sizeof(*sorted) * count); qsort(paths, count, sizeof(*paths), pl_compare);
if (sorted == NULL)
goto bad;
pl = first;
for (i = 0; i < count; i++) {
sorted[i] = pl;
pl = pl->next;
}
qsort(sorted, count, sizeof(*sorted), pl_compare);
/* Apply sorting to the list. */ /* Build up the list in sorted order. */
first = sorted[0]; for (i = 0; i < count; i++) {
sorted[count - 1]->next = NULL; SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
for (i = 1; i < count; i++) }
sorted[i - 1]->next = sorted[i];
efree(sorted);
/* Pull out the first element for parsing, leave the rest for later. */ /* Pull out the first element for parsing, leave the rest for later. */
if (count) { pl = SLIST_FIRST(&stack->more);
path = first->path; SLIST_REMOVE_HEAD(&stack->more, entries);
pl = first->next; path = pl->path;
efree(first); efree(pl);
stack->more = pl;
} else {
path = NULL;
}
done: done:
efree(paths);
efree(dirpath); efree(dirpath);
debug_return_str(path); debug_return_str(path);
bad: bad:
while (first != NULL) { for (i = 0; i < count; i++) {
pl = first; efree(paths[i]->path);
first = pl->next; efree(paths[i]);
efree(pl->path);
efree(pl);
} }
efree(sorted); efree(paths);
efree(dirpath); efree(dirpath);
efree(path); efree(path);
debug_return_str(NULL); debug_return_str(NULL);
@@ -851,8 +854,8 @@ init_lexer(void)
while (idepth) { while (idepth) {
idepth--; idepth--;
while ((pl = istack[idepth].more) != NULL) { while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
istack[idepth].more = pl->next; SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
efree(pl->path); efree(pl->path);
efree(pl); efree(pl);
} }
@@ -895,6 +898,7 @@ _push_include(char *path, bool isdir)
debug_return_bool(false); debug_return_bool(false);
} }
} }
SLIST_INIT(&istack[idepth].more);
if (isdir) { if (isdir) {
struct stat sb; struct stat sb;
switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) { switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) {
@@ -938,10 +942,10 @@ _push_include(char *path, bool isdir)
while ((fp = open_sudoers(path, false, &keepopen)) == NULL) { while ((fp = open_sudoers(path, false, &keepopen)) == NULL) {
/* Unable to open path in includedir, go to next one, if any. */ /* Unable to open path in includedir, go to next one, if any. */
efree(path); efree(path);
if ((pl = istack[idepth].more) == NULL) if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL)
debug_return_bool(false); debug_return_bool(false);
SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
path = pl->path; path = pl->path;
istack[idepth].more = pl->next;
efree(pl); efree(pl);
} }
} else { } else {
@@ -950,7 +954,6 @@ _push_include(char *path, bool isdir)
sudoerserror(NULL); sudoerserror(NULL);
debug_return_bool(false); debug_return_bool(false);
} }
istack[idepth].more = NULL;
} }
/* Push the old (current) file and open the new one. */ /* Push the old (current) file and open the new one. */
istack[idepth].path = sudoers; /* push old path */ istack[idepth].path = sudoers; /* push old path */
@@ -979,10 +982,10 @@ pop_include(void)
fclose(YY_CURRENT_BUFFER->yy_input_file); fclose(YY_CURRENT_BUFFER->yy_input_file);
sudoers_delete_buffer(YY_CURRENT_BUFFER); sudoers_delete_buffer(YY_CURRENT_BUFFER);
/* If we are in an include dir, move to the next file. */ /* If we are in an include dir, move to the next file. */
while ((pl = istack[idepth - 1].more) != NULL) { while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
fp = open_sudoers(pl->path, false, &keepopen); fp = open_sudoers(pl->path, false, &keepopen);
if (fp != NULL) { if (fp != NULL) {
istack[idepth - 1].more = pl->next;
efree(sudoers); efree(sudoers);
sudoers = pl->path; sudoers = pl->path;
sudolineno = 1; sudolineno = 1;
@@ -991,7 +994,6 @@ pop_include(void)
break; break;
} }
/* Unable to open path in include dir, go to next one. */ /* Unable to open path in include dir, go to next one. */
istack[idepth - 1].more = pl->next;
efree(pl->path); efree(pl->path);
efree(pl); efree(pl);
} }

View File

@@ -79,7 +79,6 @@
#include "sudoers.h" #include "sudoers.h"
#include "parse.h" #include "parse.h"
#include "redblack.h" #include "redblack.h"
#include "queue.h"
#include "gettext.h" #include "gettext.h"
#include "sudoers_version.h" #include "sudoers_version.h"
#include "sudo_conf.h" #include "sudo_conf.h"

View File

@@ -231,7 +231,7 @@ hooks.o: $(srcdir)/hooks.c $(top_builddir)/config.h $(srcdir)/sudo.h \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \
$(incdir)/fileops.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ $(incdir)/fileops.h $(incdir)/sudo_conf.h $(incdir)/queue.h \
$(incdir)/sudo_debug.h $(incdir)/gettext.h $(incdir)/sudo_plugin.h \ $(incdir)/sudo_debug.h $(incdir)/gettext.h $(incdir)/sudo_plugin.h \
$(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h $(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h $(incdir)/queue.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/hooks.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/hooks.c
load_plugins.o: $(srcdir)/load_plugins.c $(top_builddir)/config.h \ load_plugins.o: $(srcdir)/load_plugins.c $(top_builddir)/config.h \
$(top_srcdir)/compat/dlfcn.h $(srcdir)/sudo.h \ $(top_srcdir)/compat/dlfcn.h $(srcdir)/sudo.h \

View File

@@ -77,7 +77,7 @@
#endif #endif
struct io_buffer { struct io_buffer {
struct io_buffer *next; SLIST_ENTRY(io_buffer) entries;
struct sudo_event *revent; struct sudo_event *revent;
struct sudo_event *wevent; struct sudo_event *wevent;
bool (*action)(const char *buf, unsigned int len); bool (*action)(const char *buf, unsigned int len);
@@ -86,10 +86,7 @@ struct io_buffer {
char buf[32 * 1024]; char buf[32 * 1024];
}; };
struct io_buffer_list { SLIST_HEAD(io_buffer_list, io_buffer);
struct io_buffer *first;
/* XXX - stash cstat too? */
};
static char slavename[PATH_MAX]; static char slavename[PATH_MAX];
static bool foreground, pipeline, tty_initialized; static bool foreground, pipeline, tty_initialized;
@@ -609,9 +606,8 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int),
if (n != -1 && !ISSET(n, O_NONBLOCK)) if (n != -1 && !ISSET(n, O_NONBLOCK))
(void) fcntl(wfd, F_SETFL, n | O_NONBLOCK); (void) fcntl(wfd, F_SETFL, n | O_NONBLOCK);
/* Add to head of list. */ /* Allocate and add to head of list. */
iob = emalloc(sizeof(*iob)); iob = emalloc(sizeof(*iob));
iob->next = head->first;
iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, io_callback, iob); iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, io_callback, iob);
iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, io_callback, iob); iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, io_callback, iob);
iob->len = 0; iob->len = 0;
@@ -620,7 +616,7 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int),
iob->buf[0] = '\0'; iob->buf[0] = '\0';
if (iob->revent == NULL || iob->wevent == NULL) if (iob->revent == NULL || iob->wevent == NULL)
fatal(NULL); fatal(NULL);
head->first = iob; SLIST_INSERT_HEAD(head, iob, entries);
debug_return; debug_return;
} }
@@ -822,8 +818,8 @@ pty_close(struct command_status *cstat)
del_io_events(); del_io_events();
/* Free I/O buffers. */ /* Free I/O buffers. */
while ((iob = iobufs.first) != NULL) { while ((iob = SLIST_FIRST(&iobufs)) != NULL) {
iobufs.first = iob->next; SLIST_REMOVE_HEAD(&iobufs, entries);
efree(iob); efree(iob);
} }
@@ -871,7 +867,7 @@ add_io_events(struct sudo_event_base *evbase)
* Schedule writers that contain buffered data. * Schedule writers that contain buffered data.
* Normally, write buffers are added on demand when data is read. * Normally, write buffers are added on demand when data is read.
*/ */
for (iob = iobufs.first; iob != NULL; iob = iob->next) { SLIST_FOREACH(iob, &iobufs, entries) {
/* Don't read/write from /dev/tty if we are not in the foreground. */ /* Don't read/write from /dev/tty if we are not in the foreground. */
if (iob->revent != NULL && if (iob->revent != NULL &&
(ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) { (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) {
@@ -909,7 +905,7 @@ del_io_events(void)
debug_decl(del_io_events, SUDO_DEBUG_EXEC); debug_decl(del_io_events, SUDO_DEBUG_EXEC);
/* Remove iobufs from existing event base. */ /* Remove iobufs from existing event base. */
for (iob = iobufs.first; iob != NULL; iob = iob->next) { SLIST_FOREACH(iob, &iobufs, entries) {
if (iob->revent != NULL) { if (iob->revent != NULL) {
sudo_debug_printf(SUDO_DEBUG_INFO, sudo_debug_printf(SUDO_DEBUG_INFO,
"deleted I/O revent %p, fd %d, events %d", "deleted I/O revent %p, fd %d, events %d",
@@ -930,7 +926,7 @@ del_io_events(void)
fatal(NULL); fatal(NULL);
/* Avoid reading from /dev/tty, just flush existing data. */ /* Avoid reading from /dev/tty, just flush existing data. */
for (iob = iobufs.first; iob != NULL; iob = iob->next) { SLIST_FOREACH(iob, &iobufs, entries) {
/* Don't read from /dev/tty while flushing. */ /* Don't read from /dev/tty while flushing. */
if (iob->revent != NULL && !USERTTY_EVENT(iob->revent)) { if (iob->revent != NULL && !USERTTY_EVENT(iob->revent)) {
if (iob->len != sizeof(iob->buf)) { if (iob->len != sizeof(iob->buf)) {
@@ -951,7 +947,7 @@ del_io_events(void)
(void) sudo_ev_loop(evbase, SUDO_EVLOOP_NONBLOCK); (void) sudo_ev_loop(evbase, SUDO_EVLOOP_NONBLOCK);
/* Free temporary event base. */ /* Free temporary event base. */
for (iob = iobufs.first; iob != NULL; iob = iob->next) { SLIST_FOREACH(iob, &iobufs, entries) {
if (iob->revent != NULL) if (iob->revent != NULL)
sudo_ev_del(evbase, iob->revent); sudo_ev_del(evbase, iob->revent);
if (iob->wevent != NULL) if (iob->wevent != NULL)
@@ -1484,7 +1480,7 @@ safe_close(int fd)
debug_return_int(-1); debug_return_int(-1);
} }
/* Deschedule any other users of the fd. */ /* Deschedule any other users of the fd. */
for (iob = iobufs.first; iob != NULL; iob = iob->next) { SLIST_FOREACH(iob, &iobufs, entries) {
if (iob->revent != NULL) { if (iob->revent != NULL) {
if (sudo_ev_get_fd(iob->revent) == fd) { if (sudo_ev_get_fd(iob->revent) == fd) {
sudo_debug_printf(SUDO_DEBUG_INFO, sudo_debug_printf(SUDO_DEBUG_INFO,

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2012-2013 Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -40,10 +40,11 @@
#include "sudo_plugin.h" #include "sudo_plugin.h"
#include "sudo_plugin_int.h" #include "sudo_plugin_int.h"
#include "sudo_debug.h" #include "sudo_debug.h"
#include "queue.h"
/* Singly linked hook list. */ /* Singly linked hook list. */
struct sudo_hook_list { struct sudo_hook_entry {
struct sudo_hook_list *next; SLIST_ENTRY(sudo_hook_entry) entries;
union { union {
sudo_hook_fn_t generic_fn; sudo_hook_fn_t generic_fn;
sudo_hook_fn_setenv_t setenv_fn; sudo_hook_fn_setenv_t setenv_fn;
@@ -53,22 +54,27 @@ struct sudo_hook_list {
} u; } u;
void *closure; void *closure;
}; };
SLIST_HEAD(sudo_hook_list, sudo_hook_entry);
/* Each hook type gets own hook list. */ /* Each hook type gets own hook list. */
static struct sudo_hook_list *sudo_hook_setenv_list; static struct sudo_hook_list sudo_hook_setenv_list =
static struct sudo_hook_list *sudo_hook_unsetenv_list; SLIST_HEAD_INITIALIZER(sudo_hook_setenv_list);
static struct sudo_hook_list *sudo_hook_getenv_list; static struct sudo_hook_list sudo_hook_unsetenv_list =
static struct sudo_hook_list *sudo_hook_putenv_list; SLIST_HEAD_INITIALIZER(sudo_hook_unsetenv_list);
static struct sudo_hook_list sudo_hook_getenv_list =
SLIST_HEAD_INITIALIZER(sudo_hook_getenv_list);
static struct sudo_hook_list sudo_hook_putenv_list =
SLIST_HEAD_INITIALIZER(sudo_hook_putenv_list);
/* NOTE: must not anything that might call setenv() */ /* NOTE: must not anything that might call setenv() */
int int
process_hooks_setenv(const char *name, const char *value, int overwrite) process_hooks_setenv(const char *name, const char *value, int overwrite)
{ {
struct sudo_hook_list *hook; struct sudo_hook_entry *hook;
int rc = SUDO_HOOK_RET_NEXT; int rc = SUDO_HOOK_RET_NEXT;
/* First process the hooks. */ /* First process the hooks. */
for (hook = sudo_hook_setenv_list; hook != NULL; hook = hook->next) { SLIST_FOREACH(hook, &sudo_hook_setenv_list, entries) {
rc = hook->u.setenv_fn(name, value, overwrite, hook->closure); rc = hook->u.setenv_fn(name, value, overwrite, hook->closure);
switch (rc) { switch (rc) {
case SUDO_HOOK_RET_NEXT: case SUDO_HOOK_RET_NEXT:
@@ -89,11 +95,11 @@ done:
int int
process_hooks_putenv(char *string) process_hooks_putenv(char *string)
{ {
struct sudo_hook_list *hook; struct sudo_hook_entry *hook;
int rc = SUDO_HOOK_RET_NEXT; int rc = SUDO_HOOK_RET_NEXT;
/* First process the hooks. */ /* First process the hooks. */
for (hook = sudo_hook_putenv_list; hook != NULL; hook = hook->next) { SLIST_FOREACH(hook, &sudo_hook_putenv_list, entries) {
rc = hook->u.putenv_fn(string, hook->closure); rc = hook->u.putenv_fn(string, hook->closure);
switch (rc) { switch (rc) {
case SUDO_HOOK_RET_NEXT: case SUDO_HOOK_RET_NEXT:
@@ -114,12 +120,12 @@ done:
int int
process_hooks_getenv(const char *name, char **value) process_hooks_getenv(const char *name, char **value)
{ {
struct sudo_hook_list *hook; struct sudo_hook_entry *hook;
char *val = NULL; char *val = NULL;
int rc = SUDO_HOOK_RET_NEXT; int rc = SUDO_HOOK_RET_NEXT;
/* First process the hooks. */ /* First process the hooks. */
for (hook = sudo_hook_getenv_list; hook != NULL; hook = hook->next) { SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) {
rc = hook->u.getenv_fn(name, &val, hook->closure); rc = hook->u.getenv_fn(name, &val, hook->closure);
switch (rc) { switch (rc) {
case SUDO_HOOK_RET_NEXT: case SUDO_HOOK_RET_NEXT:
@@ -142,11 +148,11 @@ done:
int int
process_hooks_unsetenv(const char *name) process_hooks_unsetenv(const char *name)
{ {
struct sudo_hook_list *hook; struct sudo_hook_entry *hook;
int rc = SUDO_HOOK_RET_NEXT; int rc = SUDO_HOOK_RET_NEXT;
/* First process the hooks. */ /* First process the hooks. */
for (hook = sudo_hook_unsetenv_list; hook != NULL; hook = hook->next) { SLIST_FOREACH(hook, &sudo_hook_unsetenv_list, entries) {
rc = hook->u.unsetenv_fn(name, hook->closure); rc = hook->u.unsetenv_fn(name, hook->closure);
switch (rc) { switch (rc) {
case SUDO_HOOK_RET_NEXT: case SUDO_HOOK_RET_NEXT:
@@ -165,17 +171,16 @@ done:
/* Hook registration internals. */ /* Hook registration internals. */
static void static void
register_hook_internal(struct sudo_hook_list **head, register_hook_internal(struct sudo_hook_list *head,
int (*hook_fn)(), void *closure) int (*hook_fn)(), void *closure)
{ {
struct sudo_hook_list *hook; struct sudo_hook_entry *hook;
debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS) debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS)
hook = ecalloc(1, sizeof(*hook)); hook = ecalloc(1, sizeof(*hook));
hook->u.generic_fn = hook_fn; hook->u.generic_fn = hook_fn;
hook->closure = closure; hook->closure = closure;
hook->next = *head; SLIST_INSERT_HEAD(head, hook, entries);
*head = hook;
debug_return; debug_return;
} }
@@ -220,22 +225,23 @@ register_hook(struct sudo_hook *hook)
/* Hook deregistration internals. */ /* Hook deregistration internals. */
static void static void
deregister_hook_internal(struct sudo_hook_list **head, deregister_hook_internal(struct sudo_hook_list *head,
int (*hook_fn)(), void *closure) int (*hook_fn)(), void *closure)
{ {
struct sudo_hook_list *hook, *prev = NULL; struct sudo_hook_entry *hook, *prev = NULL;
debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS) debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS)
for (hook = *head, prev = NULL; hook != NULL; prev = hook, hook = hook->next) { SLIST_FOREACH(hook, head, entries) {
if (hook->u.generic_fn == hook_fn && hook->closure == closure) { if (hook->u.generic_fn == hook_fn && hook->closure == closure) {
/* Remove from list and free. */ /* Remove from list and free. */
if (prev == NULL) if (prev == NULL)
*head = hook->next; SLIST_REMOVE_HEAD(head, entries);
else else
prev->next = hook->next; SLIST_REMOVE_AFTER(prev, entries);
efree(hook); efree(hook);
break; break;
} }
prev = hook;
} }
debug_return; debug_return;