diff --git a/MANIFEST b/MANIFEST index f2e81be20..105030924 100644 --- a/MANIFEST +++ b/MANIFEST @@ -643,6 +643,8 @@ plugins/sudoers/solaris_audit.c plugins/sudoers/solaris_audit.h plugins/sudoers/sssd.c plugins/sudoers/starttime.c +plugins/sudoers/strlist.c +plugins/sudoers/strlist.h plugins/sudoers/stubs.c plugins/sudoers/sudo_ldap.h plugins/sudoers/sudo_ldap_conf.h diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index e090bea0b..9a2e1e184 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -164,8 +164,8 @@ VISUDO_OBJS = editor.lo find_path.lo goodpath.lo locale.lo stubs.o \ sudo_printf.o visudo.o CVTSUDOERS_OBJS = cvtsudoers.o cvtsudoers_json.o cvtsudoers_ldif.o \ - cvtsudoers_pwutil.o fmtsudoers.lo locale.lo stubs.o \ - sudo_printf.o ldap_util.lo + cvtsudoers_pwutil.o fmtsudoers.lo locale.lo \ + strlist.o stubs.o sudo_printf.o ldap_util.lo REPLAY_OBJS = getdate.o sudoreplay.o iolog_util.lo @@ -752,9 +752,10 @@ cvtsudoers.o: $(srcdir)/cvtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ - $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ - $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \ - $(top_builddir)/config.h $(top_builddir)/pathnames.h + $(srcdir)/redblack.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \ + $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ + $(srcdir)/sudoers_version.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers.c cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \ $(devdir)/gram.h $(incdir)/compat/stdbool.h \ @@ -763,9 +764,10 @@ cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \ - $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ - $(top_builddir)/config.h $(top_builddir)/pathnames.h + $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/strlist.h \ + $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ + $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_json.c cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \ $(devdir)/gram.h $(incdir)/compat/stdbool.h \ @@ -775,10 +777,10 @@ cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ - $(srcdir)/redblack.h $(srcdir)/sudo_ldap.h \ - $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ - $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h + $(srcdir)/redblack.h $(srcdir)/strlist.h \ + $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \ + $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ + $(top_builddir)/config.h $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_ldif.c cvtsudoers_pwutil.o: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ @@ -787,9 +789,10 @@ cvtsudoers_pwutil.o: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \ $(srcdir)/defaults.h $(srcdir)/logging.h \ - $(srcdir)/parse.h $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ - $(top_builddir)/config.h $(top_builddir)/pathnames.h + $(srcdir)/parse.h $(srcdir)/pwutil.h $(srcdir)/strlist.h \ + $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ + $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_pwutil.c dce.lo: $(authdir)/dce.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ @@ -1275,6 +1278,11 @@ starttime.lo: $(srcdir)/starttime.c $(devdir)/def_data.h \ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ $(top_builddir)/config.h $(top_builddir)/pathnames.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/starttime.c +strlist.o: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \ + $(srcdir)/sudoers_debug.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/strlist.c stubs.o: $(srcdir)/stubs.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c index a2881f0d7..3adf52153 100644 --- a/plugins/sudoers/cvtsudoers.c +++ b/plugins/sudoers/cvtsudoers.c @@ -548,7 +548,7 @@ cvtsudoers_parse_filter(char *expression) * user=foo,group=bar,host=baz */ char *keyword; - struct cvtsudoers_string *s; + struct sudoers_string *s; if ((s = malloc(sizeof(*s))) == NULL) { sudo_fatalx(U_("%s: %s"), __func__, @@ -581,65 +581,6 @@ cvtsudoers_parse_filter(char *expression) debug_return_bool(true); } -struct cvtsudoers_string * -cvtsudoers_string_alloc(const char *s) -{ - struct cvtsudoers_string *cs; - debug_decl(cvtsudoers_string_alloc, SUDOERS_DEBUG_UTIL) - - if ((cs = malloc(sizeof(*cs))) != NULL) { - if ((cs->str = strdup(s)) == NULL) { - free(cs); - cs = NULL; - } - } - - debug_return_ptr(cs); -} - -void -cvtsudoers_string_free(struct cvtsudoers_string *cs) -{ - if (cs != NULL) { - free(cs->str); - free(cs); - } -} - -struct cvtsudoers_str_list * -str_list_alloc(void) -{ - struct cvtsudoers_str_list *strlist; - debug_decl(str_list_alloc, SUDOERS_DEBUG_UTIL) - - strlist = malloc(sizeof(*strlist)); - if (strlist != NULL) { - STAILQ_INIT(strlist); - strlist->refcnt = 1; - } - - debug_return_ptr(strlist); -} - -void -str_list_free(void *v) -{ - struct cvtsudoers_str_list *strlist = v; - struct cvtsudoers_string *first; - debug_decl(str_list_free, SUDOERS_DEBUG_UTIL) - - if (strlist != NULL) { - if (--strlist->refcnt == 0) { - while ((first = STAILQ_FIRST(strlist)) != NULL) { - STAILQ_REMOVE_HEAD(strlist, entries); - cvtsudoers_string_free(first); - } - free(strlist); - } - } - debug_return; -} - static bool parse_sudoers(const char *input_file, struct cvtsudoers_config *conf) { @@ -680,7 +621,7 @@ static bool userlist_matches_filter(struct sudoers_parse_tree *parse_tree, struct member_list *users, struct cvtsudoers_config *conf) { - struct cvtsudoers_string *s; + struct sudoers_string *s; struct member *m, *next; bool ret = false; debug_decl(userlist_matches_filter, SUDOERS_DEBUG_UTIL) @@ -755,7 +696,7 @@ static bool hostlist_matches_filter(struct sudoers_parse_tree *parse_tree, struct member_list *hostlist, struct cvtsudoers_config *conf) { - struct cvtsudoers_string *s; + struct sudoers_string *s; struct member *m, *next; char *lhost, *shost; bool ret = false; diff --git a/plugins/sudoers/cvtsudoers.h b/plugins/sudoers/cvtsudoers.h index 1826b8463..8d6d48407 100644 --- a/plugins/sudoers/cvtsudoers.h +++ b/plugins/sudoers/cvtsudoers.h @@ -17,6 +17,8 @@ #ifndef SUDOERS_CVTSUDOERS_H #define SUDOERS_CVTSUDOERS_H +#include "strlist.h" + /* Supported input/output formats. */ enum sudoers_formats { format_json, @@ -24,19 +26,6 @@ enum sudoers_formats { format_sudoers }; -/* - * Simple string list with optional reference count. - */ -struct cvtsudoers_string { - STAILQ_ENTRY(cvtsudoers_string) entries; - char *str; -}; -struct cvtsudoers_str_list { - struct cvtsudoers_string *stqh_first; - struct cvtsudoers_string **stqh_last; - unsigned int refcnt; -}; - /* Flags for cvtsudoers_config.defaults */ #define CVT_DEFAULTS_GLOBAL 0x01 #define CVT_DEFAULTS_USER 0x02 @@ -81,17 +70,13 @@ struct cvtsudoers_conf_table { }; struct cvtsudoers_filter { - struct cvtsudoers_str_list users; - struct cvtsudoers_str_list groups; - struct cvtsudoers_str_list hosts; + struct sudoers_str_list users; + struct sudoers_str_list groups; + struct sudoers_str_list hosts; }; /* cvtsudoers.c */ extern struct cvtsudoers_filter *filters; -struct cvtsudoers_str_list *str_list_alloc(void); -void str_list_free(void *v); -struct cvtsudoers_string *cvtsudoers_string_alloc(const char *s); -void cvtsudoers_string_free(struct cvtsudoers_string *ls); /* cvtsudoers_json.c */ bool convert_sudoers_json(struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf); diff --git a/plugins/sudoers/cvtsudoers_ldif.c b/plugins/sudoers/cvtsudoers_ldif.c index f9cd522fd..2d5d2edae 100644 --- a/plugins/sudoers/cvtsudoers_ldif.c +++ b/plugins/sudoers/cvtsudoers_ldif.c @@ -661,12 +661,12 @@ struct sudo_role { char *notbefore; char *notafter; double order; - struct cvtsudoers_str_list *cmnds; - struct cvtsudoers_str_list *hosts; - struct cvtsudoers_str_list *users; - struct cvtsudoers_str_list *runasusers; - struct cvtsudoers_str_list *runasgroups; - struct cvtsudoers_str_list *options; + struct sudoers_str_list *cmnds; + struct sudoers_str_list *hosts; + struct sudoers_str_list *users; + struct sudoers_str_list *runasusers; + struct sudoers_str_list *runasgroups; + struct sudoers_str_list *options; }; STAILQ_HEAD(sudo_role_list, sudo_role); @@ -771,23 +771,23 @@ ldif_parse_attribute(char *str) } /* - * Allocate a struct cvtsudoers_string, store str in it and + * Allocate a struct sudoers_string, store str in it and * insert into the specified strlist. */ static void -ldif_store_string(const char *str, struct cvtsudoers_str_list *strlist, bool sorted) +ldif_store_string(const char *str, struct sudoers_str_list *strlist, bool sorted) { - struct cvtsudoers_string *ls; + struct sudoers_string *ls; debug_decl(ldif_store_string, SUDOERS_DEBUG_UTIL) - if ((ls = cvtsudoers_string_alloc(str)) == NULL) { + if ((ls = sudoers_string_alloc(str)) == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); } if (!sorted) { STAILQ_INSERT_TAIL(strlist, ls, entries); } else { - struct cvtsudoers_string *prev, *next; + struct sudoers_string *prev, *next; /* Insertion sort, list is small. */ prev = STAILQ_FIRST(strlist); @@ -808,13 +808,13 @@ ldif_store_string(const char *str, struct cvtsudoers_str_list *strlist, bool sor /* * Iterator for sudo_ldap_role_to_priv(). - * Takes a pointer to a struct cvtsudoers_string *. + * Takes a pointer to a struct sudoers_string *. * Returns the string or NULL if we've reached the end. */ static char * -cvtsudoers_string_iter(void **vp) +sudoers_string_iter(void **vp) { - struct cvtsudoers_string *ls = *vp; + struct sudoers_string *ls = *vp; if (ls == NULL) return NULL; @@ -840,10 +840,10 @@ role_order_cmp(const void *va, const void *vb) */ static void ldif_store_options(struct sudoers_parse_tree *parse_tree, - struct cvtsudoers_str_list *options) + struct sudoers_str_list *options) { struct defaults *d; - struct cvtsudoers_string *ls; + struct sudoers_string *ls; char *var, *val; debug_decl(ldif_store_options, SUDOERS_DEBUG_UTIL) @@ -874,10 +874,10 @@ ldif_store_options(struct sudoers_parse_tree *parse_tree, static int str_list_cmp(const void *aa, const void *bb) { - const struct cvtsudoers_str_list *a = aa; - const struct cvtsudoers_str_list *b = bb; - const struct cvtsudoers_string *lsa = STAILQ_FIRST(a); - const struct cvtsudoers_string *lsb = STAILQ_FIRST(b); + const struct sudoers_str_list *a = aa; + const struct sudoers_str_list *b = bb; + const struct sudoers_string *lsa = STAILQ_FIRST(a); + const struct sudoers_string *lsb = STAILQ_FIRST(b); int ret; while (lsa != NULL && lsb != NULL) { @@ -890,9 +890,9 @@ str_list_cmp(const void *aa, const void *bb) } static int -str_list_cache(struct rbtree *cache, struct cvtsudoers_str_list **strlistp) +str_list_cache(struct rbtree *cache, struct sudoers_str_list **strlistp) { - struct cvtsudoers_str_list *strlist = *strlistp; + struct sudoers_str_list *strlist = *strlistp; struct rbnode *node; int ret; debug_decl(str_list_cache, SUDOERS_DEBUG_UTIL) @@ -924,7 +924,7 @@ role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role, bool reuse_runas) { struct privilege *priv; - struct cvtsudoers_string *ls; + struct sudoers_string *ls; struct userspec *us; struct member *m; debug_decl(role_to_sudoers, SUDOERS_DEBUG_UTIL) @@ -1009,7 +1009,7 @@ role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role, STAILQ_FIRST(role->runasusers), STAILQ_FIRST(role->runasgroups), STAILQ_FIRST(role->cmnds), STAILQ_FIRST(role->options), role->notbefore, role->notafter, true, store_options, - cvtsudoers_string_iter); + sudoers_string_iter); if (priv == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); diff --git a/plugins/sudoers/cvtsudoers_pwutil.c b/plugins/sudoers/cvtsudoers_pwutil.c index 74d158fdc..50d42afd0 100644 --- a/plugins/sudoers/cvtsudoers_pwutil.c +++ b/plugins/sudoers/cvtsudoers_pwutil.c @@ -80,7 +80,7 @@ cvtsudoers_make_pwitem(uid_t uid, const char *name) size_t nsize, psize, csize, gsize, dsize, ssize, total; struct cache_item_pw *pwitem; struct passwd pw, *newpw; - struct cvtsudoers_string *s = NULL; + struct sudoers_string *s = NULL; debug_decl(sudo_make_pwitem, SUDOERS_DEBUG_NSS) /* Look up name or uid in filter list. */ @@ -186,7 +186,7 @@ cvtsudoers_make_gritem(gid_t gid, const char *name) size_t nsize, psize, nmem, total, len; struct cache_item_gr *gritem; struct group gr, *newgr; - struct cvtsudoers_string *s = NULL; + struct sudoers_string *s = NULL; debug_decl(sudo_make_gritem, SUDOERS_DEBUG_NSS) /* Look up name or gid in filter list. */ @@ -299,7 +299,7 @@ cvtsudoers_make_gidlist_item(const struct passwd *pw, char * const *unused1, char *cp; size_t nsize, total; struct cache_item_gidlist *glitem; - struct cvtsudoers_string *s; + struct sudoers_string *s; struct gid_list *gidlist; GETGROUPS_T *gids = NULL; int i, ngids = 0; @@ -397,7 +397,7 @@ cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1) char *cp; size_t nsize, ngroups, total, len; struct cache_item_grlist *grlitem; - struct cvtsudoers_string *s; + struct sudoers_string *s; struct group_list *grlist; int groupname_len; debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS) diff --git a/plugins/sudoers/strlist.c b/plugins/sudoers/strlist.c new file mode 100644 index 000000000..384e3d525 --- /dev/null +++ b/plugins/sudoers/strlist.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 Todd C. Miller + * + * 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 + +#include +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ + +#include "sudo_compat.h" +#include "sudo_util.h" +#include "sudo_queue.h" +#include "sudoers_debug.h" +#include "strlist.h" + +struct sudoers_string * +sudoers_string_alloc(const char *s) +{ + struct sudoers_string *cs; + debug_decl(sudoers_string_alloc, SUDOERS_DEBUG_UTIL) + + if ((cs = malloc(sizeof(*cs))) != NULL) { + if ((cs->str = strdup(s)) == NULL) { + free(cs); + cs = NULL; + } + } + + debug_return_ptr(cs); +} + +void +sudoers_string_free(struct sudoers_string *cs) +{ + if (cs != NULL) { + free(cs->str); + free(cs); + } +} + +struct sudoers_str_list * +str_list_alloc(void) +{ + struct sudoers_str_list *strlist; + debug_decl(str_list_alloc, SUDOERS_DEBUG_UTIL) + + strlist = malloc(sizeof(*strlist)); + if (strlist != NULL) { + STAILQ_INIT(strlist); + strlist->refcnt = 1; + } + + debug_return_ptr(strlist); +} + +void +str_list_free(void *v) +{ + struct sudoers_str_list *strlist = v; + struct sudoers_string *first; + debug_decl(str_list_free, SUDOERS_DEBUG_UTIL) + + if (strlist != NULL) { + if (--strlist->refcnt == 0) { + while ((first = STAILQ_FIRST(strlist)) != NULL) { + STAILQ_REMOVE_HEAD(strlist, entries); + sudoers_string_free(first); + } + free(strlist); + } + } + debug_return; +} diff --git a/plugins/sudoers/strlist.h b/plugins/sudoers/strlist.h new file mode 100644 index 000000000..1a0dfc6c8 --- /dev/null +++ b/plugins/sudoers/strlist.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Todd C. Miller + * + * 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 SUDOERS_STRLIST_H +#define SUDOERS_STRLIST_H + +/* + * Simple string list with optional reference count. + */ +struct sudoers_string { + STAILQ_ENTRY(sudoers_string) entries; + char *str; +}; +struct sudoers_str_list { + struct sudoers_string *stqh_first; + struct sudoers_string **stqh_last; + unsigned int refcnt; +}; + +struct sudoers_str_list *str_list_alloc(void); +void str_list_free(void *v); +struct sudoers_string *sudoers_string_alloc(const char *s); +void sudoers_string_free(struct sudoers_string *ls); + +#endif /* SUDOERS_STRLIST_H */