Escape/unescape commas when serializing/deserializing a stringlist.
This commit is contained in:
3
MANIFEST
3
MANIFEST
@@ -799,6 +799,7 @@ plugins/sudoers/regress/parser/check_digest.out.ok
|
|||||||
plugins/sudoers/regress/parser/check_fill.c
|
plugins/sudoers/regress/parser/check_fill.c
|
||||||
plugins/sudoers/regress/parser/check_gentime.c
|
plugins/sudoers/regress/parser/check_gentime.c
|
||||||
plugins/sudoers/regress/parser/check_hexchar.c
|
plugins/sudoers/regress/parser/check_hexchar.c
|
||||||
|
plugins/sudoers/regress/serialize_list/check_serialize_list.c
|
||||||
plugins/sudoers/regress/starttime/check_starttime.c
|
plugins/sudoers/regress/starttime/check_starttime.c
|
||||||
plugins/sudoers/regress/sudoers/test1.in
|
plugins/sudoers/regress/sudoers/test1.in
|
||||||
plugins/sudoers/regress/sudoers/test1.json.ok
|
plugins/sudoers/regress/sudoers/test1.json.ok
|
||||||
@@ -1011,6 +1012,7 @@ plugins/sudoers/regress/visudo/test8.out.ok
|
|||||||
plugins/sudoers/regress/visudo/test8.sh
|
plugins/sudoers/regress/visudo/test8.sh
|
||||||
plugins/sudoers/regress/visudo/test9.out.ok
|
plugins/sudoers/regress/visudo/test9.out.ok
|
||||||
plugins/sudoers/regress/visudo/test9.sh
|
plugins/sudoers/regress/visudo/test9.sh
|
||||||
|
plugins/sudoers/serialize_list.c
|
||||||
plugins/sudoers/set_perms.c
|
plugins/sudoers/set_perms.c
|
||||||
plugins/sudoers/solaris_audit.c
|
plugins/sudoers/solaris_audit.c
|
||||||
plugins/sudoers/solaris_audit.h
|
plugins/sudoers/solaris_audit.h
|
||||||
@@ -1047,6 +1049,7 @@ plugins/sudoers/toke_util.c
|
|||||||
plugins/sudoers/tsdump.c
|
plugins/sudoers/tsdump.c
|
||||||
plugins/sudoers/tsgetgrpw.c
|
plugins/sudoers/tsgetgrpw.c
|
||||||
plugins/sudoers/tsgetgrpw.h
|
plugins/sudoers/tsgetgrpw.h
|
||||||
|
plugins/sudoers/unesc_str.c
|
||||||
plugins/sudoers/visudo.c
|
plugins/sudoers/visudo.c
|
||||||
plugins/system_group/Makefile.in
|
plugins/system_group/Makefile.in
|
||||||
plugins/system_group/system_group.c
|
plugins/system_group/system_group.c
|
||||||
|
@@ -158,8 +158,8 @@ PROGS = sudoers.la visudo sudoreplay cvtsudoers testsudoers
|
|||||||
# Regression tests
|
# Regression tests
|
||||||
TEST_PROGS = check_addr check_base64 check_digest check_editor \
|
TEST_PROGS = check_addr check_base64 check_digest check_editor \
|
||||||
check_env_pattern check_exptilde check_fill check_gentime \
|
check_env_pattern check_exptilde check_fill check_gentime \
|
||||||
check_hexchar check_iolog_plugin check_starttime \
|
check_hexchar check_iolog_plugin check_serialize_list \
|
||||||
check_unesc @SUDOERS_TEST_PROGS@
|
check_starttime check_unesc @SUDOERS_TEST_PROGS@
|
||||||
|
|
||||||
# Fuzzers
|
# Fuzzers
|
||||||
LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
|
LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
|
||||||
@@ -185,9 +185,9 @@ SUDOERS_OBJS = $(AUTH_OBJS) audit.lo boottime.lo check.lo editor.lo env.lo \
|
|||||||
sudoers_hooks.lo env_pattern.lo file.lo find_path.lo \
|
sudoers_hooks.lo env_pattern.lo file.lo find_path.lo \
|
||||||
fmtsudoers.lo gc.lo goodpath.lo group_plugin.lo interfaces.lo \
|
fmtsudoers.lo gc.lo goodpath.lo group_plugin.lo interfaces.lo \
|
||||||
iolog.lo iolog_path_escapes.lo locale.lo log_client.lo \
|
iolog.lo iolog_path_escapes.lo locale.lo log_client.lo \
|
||||||
logging.lo parse.lo policy.lo prompt.lo set_perms.lo \
|
logging.lo parse.lo policy.lo prompt.lo serialize_list.lo \
|
||||||
starttime.lo strlcpy_unesc.lo strvec_join.lo sudo_nss.lo \
|
set_perms.lo starttime.lo strlcpy_unesc.lo strvec_join.lo \
|
||||||
sudoers.lo timestamp.lo @SUDOERS_OBJS@
|
sudo_nss.lo sudoers.lo timestamp.lo unesc_str.lo @SUDOERS_OBJS@
|
||||||
|
|
||||||
SUDOERS_IOBJS = $(SUDOERS_OBJS:.lo=.i)
|
SUDOERS_IOBJS = $(SUDOERS_OBJS:.lo=.i)
|
||||||
|
|
||||||
@@ -241,17 +241,22 @@ CHECK_HEXCHAR_OBJS = check_hexchar.o hexchar.lo sudoers_debug.lo
|
|||||||
|
|
||||||
CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo log_client.lo \
|
CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo log_client.lo \
|
||||||
locale.lo pwutil.lo pwutil_impl.lo redblack.lo \
|
locale.lo pwutil.lo pwutil_impl.lo redblack.lo \
|
||||||
strlist.lo sudoers_debug.lo
|
strlist.lo sudoers_debug.lo unesc_str.lo
|
||||||
|
|
||||||
CHECK_SYMBOLS_OBJS = check_symbols.o
|
CHECK_SYMBOLS_OBJS = check_symbols.o
|
||||||
|
|
||||||
CHECK_STARTTIME_OBJS = check_starttime.o starttime.lo sudoers_debug.lo
|
CHECK_STARTTIME_OBJS = check_starttime.o starttime.lo sudoers_debug.lo
|
||||||
|
|
||||||
CHECK_UNESC_OBJS = check_unesc.o strlcpy_unesc.lo strvec_join.lo sudoers_debug.lo
|
CHECK_UNESC_OBJS = check_unesc.o strlcpy_unesc.lo strvec_join.lo \
|
||||||
|
sudoers_debug.lo unesc_str.lo
|
||||||
|
|
||||||
|
CHECK_SERIALIZE_LIST_OBJS = check_serialize_list.lo serialize_list.lo \
|
||||||
|
sudoers_debug.lo
|
||||||
|
|
||||||
FUZZ_POLICY_OBJS = editor.lo env.lo env_pattern.lo fuzz_policy.o fuzz_stubs.o \
|
FUZZ_POLICY_OBJS = editor.lo env.lo env_pattern.lo fuzz_policy.o fuzz_stubs.o \
|
||||||
gc.lo iolog_path_escapes.lo locale.lo policy.lo \
|
gc.lo iolog_path_escapes.lo locale.lo policy.lo \
|
||||||
strlcpy_unesc.lo strvec_join.lo sudoers.lo sudoers_hooks.lo
|
serialize_list.lo strlcpy_unesc.lo strvec_join.lo \
|
||||||
|
sudoers.lo sudoers_hooks.lo
|
||||||
|
|
||||||
FUZZ_POLICY_CORPUS = $(srcdir)/regress/corpus/seed/policy/policy.*
|
FUZZ_POLICY_CORPUS = $(srcdir)/regress/corpus/seed/policy/policy.*
|
||||||
|
|
||||||
@@ -386,6 +391,9 @@ check_hexchar: $(CHECK_HEXCHAR_OBJS) $(LIBUTIL)
|
|||||||
check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV)
|
check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV)
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG) $(LIBLOGSRV) @LIBTLS@
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG) $(LIBLOGSRV) @LIBTLS@
|
||||||
|
|
||||||
|
check_serialize_list: $(CHECK_SERIALIZE_LIST_OBJS) $(LIBUTIL)
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_SERIALIZE_LIST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
|
check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
@@ -659,6 +667,7 @@ check: $(TEST_PROGS) visudo testsudoers cvtsudoers check-fuzzer
|
|||||||
./check_hexchar || rval=`expr $$rval + $$?`; \
|
./check_hexchar || rval=`expr $$rval + $$?`; \
|
||||||
mkdir -p regress/iolog_plugin; \
|
mkdir -p regress/iolog_plugin; \
|
||||||
./check_iolog_plugin regress/iolog_plugin/iolog || rval=`expr $$rval + $$?`; \
|
./check_iolog_plugin regress/iolog_plugin/iolog || rval=`expr $$rval + $$?`; \
|
||||||
|
./check_serialize_list || rval=`expr $$rval + $$?`; \
|
||||||
./check_starttime || rval=`expr $$rval + $$?`; \
|
./check_starttime || rval=`expr $$rval + $$?`; \
|
||||||
./check_unesc || rval=`expr $$rval + $$?`; \
|
./check_unesc || rval=`expr $$rval + $$?`; \
|
||||||
if test -f check_symbols; then \
|
if test -f check_symbols; then \
|
||||||
@@ -1259,6 +1268,34 @@ check_iolog_plugin.i: $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
check_iolog_plugin.plog: check_iolog_plugin.i
|
check_iolog_plugin.plog: check_iolog_plugin.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c --i-file $< --output-file $@
|
||||||
|
check_serialize_list.lo: \
|
||||||
|
$(srcdir)/regress/serialize_list/check_serialize_list.c \
|
||||||
|
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
$(incdir)/sudo_util.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
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/serialize_list/check_serialize_list.c
|
||||||
|
check_serialize_list.i: \
|
||||||
|
$(srcdir)/regress/serialize_list/check_serialize_list.c \
|
||||||
|
$(devdir)/def_data.h $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
$(incdir)/sudo_util.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
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
check_serialize_list.plog: check_serialize_list.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/serialize_list/check_serialize_list.c --i-file $< --output-file $@
|
||||||
check_starttime.o: $(srcdir)/regress/starttime/check_starttime.c \
|
check_starttime.o: $(srcdir)/regress/starttime/check_starttime.c \
|
||||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
|
||||||
@@ -2671,6 +2708,30 @@ securid5.i: $(authdir)/securid5.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
securid5.plog: securid5.i
|
securid5.plog: securid5.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/securid5.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/securid5.c --i-file $< --output-file $@
|
||||||
|
serialize_list.lo: $(srcdir)/serialize_list.c $(devdir)/def_data.h \
|
||||||
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
|
$(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_queue.h $(incdir)/sudo_util.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
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/serialize_list.c
|
||||||
|
serialize_list.i: $(srcdir)/serialize_list.c $(devdir)/def_data.h \
|
||||||
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
|
$(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_queue.h $(incdir)/sudo_util.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
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
serialize_list.plog: serialize_list.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/serialize_list.c --i-file $< --output-file $@
|
||||||
set_perms.lo: $(srcdir)/set_perms.c $(devdir)/def_data.h \
|
set_perms.lo: $(srcdir)/set_perms.c $(devdir)/def_data.h \
|
||||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
@@ -3213,6 +3274,12 @@ tsgetgrpw.i: $(srcdir)/tsgetgrpw.c $(devdir)/def_data.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
tsgetgrpw.plog: tsgetgrpw.i
|
tsgetgrpw.plog: tsgetgrpw.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tsgetgrpw.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tsgetgrpw.c --i-file $< --output-file $@
|
||||||
|
unesc_str.lo: $(srcdir)/unesc_str.c
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/unesc_str.c
|
||||||
|
unesc_str.i: $(srcdir)/unesc_str.c
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
unesc_str.plog: unesc_str.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/unesc_str.c --i-file $< --output-file $@
|
||||||
visudo.o: $(srcdir)/visudo.c $(devdir)/def_data.h $(devdir)/gram.h \
|
visudo.o: $(srcdir)/visudo.c $(devdir)/def_data.h $(devdir)/gram.h \
|
||||||
$(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
|
$(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
|
@@ -211,7 +211,6 @@ free_iolog_details(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a comma-separated list to a string list.
|
* Convert a comma-separated list to a string list.
|
||||||
* XXX - handle escaped commas
|
|
||||||
*/
|
*/
|
||||||
static struct sudoers_str_list *
|
static struct sudoers_str_list *
|
||||||
deserialize_stringlist(const char *s)
|
deserialize_stringlist(const char *s)
|
||||||
@@ -235,6 +234,7 @@ deserialize_stringlist(const char *s)
|
|||||||
free(str);
|
free(str);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
unescape_string(str->str);
|
||||||
STAILQ_INSERT_TAIL(strlist, str, entries);
|
STAILQ_INSERT_TAIL(strlist, str, entries);
|
||||||
}
|
}
|
||||||
if (STAILQ_EMPTY(strlist))
|
if (STAILQ_EMPTY(strlist))
|
||||||
@@ -265,9 +265,9 @@ set_passprompt_regex(const char *cstr)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX - handle escaped commas */
|
|
||||||
for ((cp = strtok_r(str, ",", &last)); cp != NULL;
|
for ((cp = strtok_r(str, ",", &last)); cp != NULL;
|
||||||
(cp = strtok_r(NULL, ",", &last))) {
|
(cp = strtok_r(NULL, ",", &last))) {
|
||||||
|
unescape_string(cp);
|
||||||
if (!iolog_pwfilt_add(handle, cp))
|
if (!iolog_pwfilt_add(handle, cp))
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
@@ -572,46 +572,6 @@ bad:
|
|||||||
debug_return_int(MODE_ERROR);
|
debug_return_int(MODE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert struct list_members to a comma-separated string with
|
|
||||||
* the given variable name.
|
|
||||||
* XXX - escape commas in member values
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
serialize_list(const char *varname, struct list_members *members)
|
|
||||||
{
|
|
||||||
struct list_member *lm, *next;
|
|
||||||
size_t len, result_size;
|
|
||||||
char *result;
|
|
||||||
debug_decl(serialize_list, SUDOERS_DEBUG_PLUGIN);
|
|
||||||
|
|
||||||
result_size = strlen(varname) + 1;
|
|
||||||
SLIST_FOREACH(lm, members, entries) {
|
|
||||||
result_size += strlen(lm->value) + 1;
|
|
||||||
}
|
|
||||||
if ((result = malloc(result_size)) == NULL)
|
|
||||||
goto bad;
|
|
||||||
/* No need to check len for overflow here. */
|
|
||||||
len = strlcpy(result, varname, result_size);
|
|
||||||
result[len++] = '=';
|
|
||||||
result[len] = '\0';
|
|
||||||
SLIST_FOREACH_SAFE(lm, members, entries, next) {
|
|
||||||
len = strlcat(result, lm->value, result_size);
|
|
||||||
if (len + (next != NULL) >= result_size) {
|
|
||||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
if (next != NULL) {
|
|
||||||
result[len++] = ',';
|
|
||||||
result[len] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_str(result);
|
|
||||||
bad:
|
|
||||||
free(result);
|
|
||||||
debug_return_str(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the execution environment and other front-end settings.
|
* Store the execution environment and other front-end settings.
|
||||||
* Builds up the command_info list and sets argv and envp.
|
* Builds up the command_info list and sets argv and envp.
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SUDO_ERROR_WRAP 0
|
||||||
|
|
||||||
|
#include "sudoers.h"
|
||||||
|
|
||||||
|
sudo_dso_public int main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_serialize_list(int *ntests_out, int *errors_out)
|
||||||
|
{
|
||||||
|
int ntests = *ntests_out;
|
||||||
|
int errors = *errors_out;
|
||||||
|
const char *expected = "myvar=a value with spaces,this\\,and\\,that,\\,";
|
||||||
|
struct list_members members = SLIST_HEAD_INITIALIZER(members);
|
||||||
|
struct list_member lm1, lm2, lm3;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
lm1.value = "a value with spaces";
|
||||||
|
lm2.value = "this,and,that";
|
||||||
|
lm3.value = ",";
|
||||||
|
SLIST_INSERT_HEAD(&members, &lm3, entries);
|
||||||
|
SLIST_INSERT_HEAD(&members, &lm2, entries);
|
||||||
|
SLIST_INSERT_HEAD(&members, &lm1, entries);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = serialize_list("myvar", &members);
|
||||||
|
if (result == NULL) {
|
||||||
|
sudo_warnx("serialize_list returns NULL");
|
||||||
|
++errors;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ntests++;
|
||||||
|
if (strcmp(result, expected) != 0) {
|
||||||
|
sudo_warnx("got \"%s\", expected \"%s\"", result, expected);
|
||||||
|
++errors;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
*ntests_out = ntests;
|
||||||
|
*errors_out = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ntests = 0, errors = 0;
|
||||||
|
|
||||||
|
initprogname(argc > 0 ? argv[0] : "check_serialize_list");
|
||||||
|
|
||||||
|
test_serialize_list(&ntests, &errors);
|
||||||
|
|
||||||
|
if (ntests != 0) {
|
||||||
|
printf("%s: %d tests run, %d errors, %d%% success rate\n",
|
||||||
|
getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(errors);
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -31,7 +31,10 @@ struct test_data {
|
|||||||
char *result;
|
char *result;
|
||||||
size_t result_len;
|
size_t result_len;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
} test_data[] = {
|
};
|
||||||
|
|
||||||
|
/* strlcpy_unescape() does not unescape whitespace */
|
||||||
|
static struct test_data strlcpy_unescape_test_data[] = {
|
||||||
{ "\\\0ABC", "\\", 1, 2 }, /* 1 */
|
{ "\\\0ABC", "\\", 1, 2 }, /* 1 */
|
||||||
{ "\\ \\;", "\\ ;", 3, 4 }, /* 2 */
|
{ "\\ \\;", "\\ ;", 3, 4 }, /* 2 */
|
||||||
{ "\\\t\\;", "\\\t;", 3, 4 }, /* 3 */
|
{ "\\\t\\;", "\\\t;", 3, 4 }, /* 3 */
|
||||||
@@ -43,6 +46,20 @@ struct test_data {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* unescape_string() _does_ unescape whitespace */
|
||||||
|
static struct test_data unescape_string_test_data[] = {
|
||||||
|
{ "foo\\ bar", "foo bar", 7, 8 }, /* 1 */
|
||||||
|
{ "foo\\,bar", "foo,bar", 7, 8 }, /* 2 */
|
||||||
|
{ "baz \\", "baz \\", 5, 5 }, /* 3 */
|
||||||
|
{ "\\foo", "foo", 3, 4 }, /* 4 */
|
||||||
|
{ "var=aaa,b\\,b", "var=aaa,b,b", 11, 12 }, /* 5 */
|
||||||
|
{ "\\a\\ b\\ c\\\\", "a b c\\", 6, 10 }, /* 6 */
|
||||||
|
{ "\\", "\\", 1, 1 }, /* 7 */
|
||||||
|
{ "foo", "foo", 3, 3 }, /* 8 */
|
||||||
|
{ "", "", 0, 0 }, /* 9 */
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
sudo_dso_public int main(int argc, char *argv[]);
|
sudo_dso_public int main(int argc, char *argv[]);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -54,7 +71,7 @@ test_strlcpy_unescape(int *ntests_out, int *errors_out)
|
|||||||
char buf[1024];
|
char buf[1024];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
for (td = test_data; td->input != NULL; td++) {
|
for (td = strlcpy_unescape_test_data; td->input != NULL; td++) {
|
||||||
ntests++;
|
ntests++;
|
||||||
memset(buf, 'A', sizeof(buf));
|
memset(buf, 'A', sizeof(buf));
|
||||||
len = strlcpy_unescape(buf, td->input, td->bufsize);
|
len = strlcpy_unescape(buf, td->input, td->bufsize);
|
||||||
@@ -85,6 +102,31 @@ test_strlcpy_unescape(int *ntests_out, int *errors_out)
|
|||||||
*errors_out = errors;
|
*errors_out = errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_unescape_string(int *ntests_out, int *errors_out)
|
||||||
|
{
|
||||||
|
int ntests = *ntests_out;
|
||||||
|
int errors = *errors_out;
|
||||||
|
struct test_data *td;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
for (td = unescape_string_test_data; td->input != NULL; td++) {
|
||||||
|
ntests++;
|
||||||
|
memset(buf, 'A', sizeof(buf));
|
||||||
|
memcpy(buf, td->input, td->bufsize);
|
||||||
|
buf[td->bufsize] = '\0';
|
||||||
|
unescape_string(buf);
|
||||||
|
if (strcmp(td->result, buf) != 0) {
|
||||||
|
sudo_warnx("%d: \"%s\": got \"%s\", expected \"%s\"",
|
||||||
|
ntests, td->input, buf, td->result);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ntests_out = ntests;
|
||||||
|
*errors_out = errors;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_strvec_join(char sep, int *ntests_out, int *errors_out)
|
test_strvec_join(char sep, int *ntests_out, int *errors_out)
|
||||||
{
|
{
|
||||||
@@ -132,6 +174,9 @@ main(int argc, char *argv[])
|
|||||||
/* strlcpy_unescape tests */
|
/* strlcpy_unescape tests */
|
||||||
test_strlcpy_unescape(&ntests, &errors);
|
test_strlcpy_unescape(&ntests, &errors);
|
||||||
|
|
||||||
|
/* unescape_string test */
|
||||||
|
test_unescape_string(&ntests, &errors);
|
||||||
|
|
||||||
/* strvec_join test */
|
/* strvec_join test */
|
||||||
test_strvec_join(' ', &ntests, &errors);
|
test_strvec_join(' ', &ntests, &errors);
|
||||||
test_strvec_join('\n', &ntests, &errors);
|
test_strvec_join('\n', &ntests, &errors);
|
||||||
|
82
plugins/sudoers/serialize_list.c
Normal file
82
plugins/sudoers/serialize_list.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sudoers.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert struct list_members to a comma-separated string with
|
||||||
|
* the given variable name. Escapes backslashes and commas.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
serialize_list(const char *varname, struct list_members *members)
|
||||||
|
{
|
||||||
|
struct list_member *lm, *next;
|
||||||
|
size_t len, result_size;
|
||||||
|
char *cp, *result;
|
||||||
|
debug_decl(serialize_list, SUDOERS_DEBUG_PLUGIN);
|
||||||
|
|
||||||
|
result_size = strlen(varname) + 1;
|
||||||
|
SLIST_FOREACH(lm, members, entries) {
|
||||||
|
for (cp = lm->value; *cp != '\0'; cp++) {
|
||||||
|
result_size++;
|
||||||
|
if (*cp == '\\' || *cp == ',')
|
||||||
|
result_size++;
|
||||||
|
}
|
||||||
|
result_size++;
|
||||||
|
}
|
||||||
|
if ((result = malloc(result_size)) == NULL)
|
||||||
|
goto bad;
|
||||||
|
/* No need to check len for overflow here. */
|
||||||
|
len = strlcpy(result, varname, result_size);
|
||||||
|
result[len++] = '=';
|
||||||
|
SLIST_FOREACH_SAFE(lm, members, entries, next) {
|
||||||
|
for (cp = lm->value; *cp != '\0'; cp++) {
|
||||||
|
bool escape = (*cp == '\\' || *cp == ',');
|
||||||
|
if (len + 1 + escape >= result_size) {
|
||||||
|
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (escape)
|
||||||
|
result[len++] = '\\';
|
||||||
|
result[len++] = *cp;
|
||||||
|
}
|
||||||
|
if (next != NULL) {
|
||||||
|
if (len + 1 >= result_size) {
|
||||||
|
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
result[len++] = ',';
|
||||||
|
}
|
||||||
|
result[len] = '\0';
|
||||||
|
}
|
||||||
|
debug_return_str(result);
|
||||||
|
bad:
|
||||||
|
free(result);
|
||||||
|
debug_return_str(NULL);
|
||||||
|
}
|
@@ -467,4 +467,10 @@ size_t strlcpy_unescape(char *dst, const char *src, size_t size);
|
|||||||
/* strvec_join.c */
|
/* strvec_join.c */
|
||||||
char *strvec_join(char *const argv[], char sep, size_t (*cpy)(char *, const char *, size_t));
|
char *strvec_join(char *const argv[], char sep, size_t (*cpy)(char *, const char *, size_t));
|
||||||
|
|
||||||
|
/* unesc_str.c */
|
||||||
|
void unescape_string(char *str);
|
||||||
|
|
||||||
|
/* serialize_list.c */
|
||||||
|
char *serialize_list(const char *varname, struct list_members *members);
|
||||||
|
|
||||||
#endif /* SUDOERS_SUDOERS_H */
|
#endif /* SUDOERS_SUDOERS_H */
|
||||||
|
42
plugins/sudoers/unesc_str.c
Normal file
42
plugins/sudoers/unesc_str.c
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove backslash escape chars.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
unescape_string(char *str)
|
||||||
|
{
|
||||||
|
char *cp = str;
|
||||||
|
char *ep = str + strlen(str);
|
||||||
|
|
||||||
|
while ((cp = strchr(cp, '\\')) != NULL) {
|
||||||
|
if (cp[1] == '\0')
|
||||||
|
break;
|
||||||
|
memmove(cp, cp + 1, (size_t)(ep - cp));
|
||||||
|
cp++;
|
||||||
|
ep--;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user