From 38c381a0ccc9b1b02552b4177eed56882abd88c4 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 24 Feb 2021 17:14:51 -0700 Subject: [PATCH] Split fmtsudoers.c into the parts used by sudoers plugin and cvtsudoers. Only testsudoers and cvtsudoers use the full set of formatting functions. --- MANIFEST | 1 + plugins/sudoers/Makefile.in | 33 ++++- plugins/sudoers/fmtsudoers.c | 186 -------------------------- plugins/sudoers/fmtsudoers_cvt.c | 219 +++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 189 deletions(-) create mode 100644 plugins/sudoers/fmtsudoers_cvt.c diff --git a/MANIFEST b/MANIFEST index 6b9ecc525..214d4c76f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -524,6 +524,7 @@ plugins/sudoers/file.c plugins/sudoers/filedigest.c plugins/sudoers/find_path.c plugins/sudoers/fmtsudoers.c +plugins/sudoers/fmtsudoers_cvt.c plugins/sudoers/gc.c plugins/sudoers/gentime.c plugins/sudoers/getdate.c diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index dbcffda71..6fcfe2d0c 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -194,7 +194,8 @@ VISUDO_IOBJS = sudo_printf.i visudo.i CVTSUDOERS_OBJS = b64_encode.o cvtsudoers.o cvtsudoers_json.o \ cvtsudoers_ldif.o cvtsudoers_pwutil.o fmtsudoers.lo \ - locale.lo parse_ldif.o stubs.o sudo_printf.o ldap_util.lo + fmtsudoers_cvt.lo locale.lo parse_ldif.o stubs.o \ + sudo_printf.o ldap_util.lo CVTSUDOERS_IOBJS = cvtsudoers.i cvtsudoers_json.i cvtsudoers_ldif.i \ cvtsudoers_pwutil.i @@ -203,8 +204,8 @@ REPLAY_OBJS = getdate.o sudoreplay.o REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i) -TEST_OBJS = fmtsudoers.lo group_plugin.lo interfaces.lo ldap_util.lo \ - locale.lo net_ifs.o parse_ldif.o sudo_printf.o \ +TEST_OBJS = fmtsudoers.lo fmtsudoers_cvt.lo group_plugin.lo interfaces.lo \ + ldap_util.lo locale.lo net_ifs.o parse_ldif.o sudo_printf.o \ testsudoers.o tsgetgrpw.o IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \ @@ -1575,6 +1576,32 @@ fmtsudoers.i: $(srcdir)/fmtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \ $(CC) -E -o $@ $(CPPFLAGS) $< fmtsudoers.plog: fmtsudoers.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fmtsudoers.c --i-file $< --output-file $@ +fmtsudoers_cvt.lo: $(srcdir)/fmtsudoers_cvt.c $(devdir)/def_data.h \ + $(devdir)/gram.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_lbuf.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)/fmtsudoers_cvt.c +fmtsudoers_cvt.i: $(srcdir)/fmtsudoers_cvt.c $(devdir)/def_data.h \ + $(devdir)/gram.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_lbuf.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) $< +fmtsudoers_cvt.plog: fmtsudoers_cvt.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fmtsudoers_cvt.c --i-file $< --output-file $@ fuzz_policy.o: $(srcdir)/regress/fuzz/fuzz_policy.c $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ diff --git a/plugins/sudoers/fmtsudoers.c b/plugins/sudoers/fmtsudoers.c index 07961a485..9ab1473f2 100644 --- a/plugins/sudoers/fmtsudoers.c +++ b/plugins/sudoers/fmtsudoers.c @@ -268,130 +268,6 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf, debug_return_bool(!sudo_lbuf_error(lbuf)); } -/* - * Write a privilege to lbuf in sudoers format. - */ -bool -sudoers_format_privilege(struct sudo_lbuf *lbuf, - struct sudoers_parse_tree *parse_tree, struct privilege *priv, - bool expand_aliases) -{ - struct cmndspec *cs, *prev_cs; - struct cmndtag tags; - struct member *m; - debug_decl(sudoers_format_privilege, SUDOERS_DEBUG_UTIL); - - /* Convert per-privilege defaults to tags. */ - sudoers_defaults_list_to_tags(&priv->defaults, &tags); - - /* Print hosts list. */ - TAILQ_FOREACH(m, &priv->hostlist, entries) { - if (m != TAILQ_FIRST(&priv->hostlist)) - sudo_lbuf_append(lbuf, ", "); - sudoers_format_member(lbuf, parse_tree, m, ", ", - expand_aliases ? HOSTALIAS : UNSPEC); - } - - /* Print commands. */ - sudo_lbuf_append(lbuf, " = "); - prev_cs = NULL; - TAILQ_FOREACH(cs, &priv->cmndlist, entries) { - if (prev_cs == NULL || RUNAS_CHANGED(cs, prev_cs)) { - if (cs != TAILQ_FIRST(&priv->cmndlist)) - sudo_lbuf_append(lbuf, ", "); - if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) - sudo_lbuf_append(lbuf, "("); - if (cs->runasuserlist != NULL) { - TAILQ_FOREACH(m, cs->runasuserlist, entries) { - if (m != TAILQ_FIRST(cs->runasuserlist)) - sudo_lbuf_append(lbuf, ", "); - sudoers_format_member(lbuf, parse_tree, m, ", ", - expand_aliases ? RUNASALIAS : UNSPEC); - } - } - if (cs->runasgrouplist != NULL) { - sudo_lbuf_append(lbuf, " : "); - TAILQ_FOREACH(m, cs->runasgrouplist, entries) { - if (m != TAILQ_FIRST(cs->runasgrouplist)) - sudo_lbuf_append(lbuf, ", "); - sudoers_format_member(lbuf, parse_tree, m, ", ", - expand_aliases ? RUNASALIAS : UNSPEC); - } - } - if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) - sudo_lbuf_append(lbuf, ") "); - } else if (cs != TAILQ_FIRST(&priv->cmndlist)) { - sudo_lbuf_append(lbuf, ", "); - } - sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, tags, - expand_aliases); - prev_cs = cs; - } - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - -/* - * Write a userspec to lbuf in sudoers format. - */ -bool -sudoers_format_userspec(struct sudo_lbuf *lbuf, - struct sudoers_parse_tree *parse_tree, - struct userspec *us, bool expand_aliases) -{ - struct privilege *priv; - struct sudoers_comment *comment; - struct member *m; - debug_decl(sudoers_format_userspec, SUDOERS_DEBUG_UTIL); - - /* Print comments (if any). */ - STAILQ_FOREACH(comment, &us->comments, entries) { - sudo_lbuf_append(lbuf, "# %s\n", comment->str); - } - - /* Print users list. */ - TAILQ_FOREACH(m, &us->users, entries) { - if (m != TAILQ_FIRST(&us->users)) - sudo_lbuf_append(lbuf, ", "); - sudoers_format_member(lbuf, parse_tree, m, ", ", - expand_aliases ? USERALIAS : UNSPEC); - } - - TAILQ_FOREACH(priv, &us->privileges, entries) { - if (priv != TAILQ_FIRST(&us->privileges)) - sudo_lbuf_append(lbuf, " : "); - else - sudo_lbuf_append(lbuf, " "); - if (!sudoers_format_privilege(lbuf, parse_tree, priv, expand_aliases)) - break; - } - sudo_lbuf_append(lbuf, "\n"); - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - -/* - * Write a userspec_list to lbuf in sudoers format. - */ -bool -sudoers_format_userspecs(struct sudo_lbuf *lbuf, - struct sudoers_parse_tree *parse_tree, const char *separator, - bool expand_aliases, bool flush) -{ - struct userspec *us; - debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL); - - TAILQ_FOREACH(us, &parse_tree->userspecs, entries) { - if (separator != NULL && us != TAILQ_FIRST(&parse_tree->userspecs)) - sudo_lbuf_append(lbuf, "%s", separator); - if (!sudoers_format_userspec(lbuf, parse_tree, us, expand_aliases)) - break; - sudo_lbuf_print(lbuf); - } - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - /* * Format and append a defaults entry to the specified lbuf. */ @@ -414,65 +290,3 @@ sudoers_format_default(struct sudo_lbuf *lbuf, struct defaults *d) } debug_return_bool(!sudo_lbuf_error(lbuf)); } - -/* - * Format and append a defaults line to the specified lbuf. - * If next, is specified, it must point to the next defaults - * entry in the list; this is used to print multiple defaults - * entries with the same binding on a single line. - */ -bool -sudoers_format_default_line( struct sudo_lbuf *lbuf, - struct sudoers_parse_tree *parse_tree, struct defaults *d, - struct defaults **next, bool expand_aliases) -{ - struct member *m; - int alias_type; - debug_decl(sudoers_format_default_line, SUDOERS_DEBUG_UTIL); - - /* Print Defaults type and binding (if present) */ - switch (d->type) { - case DEFAULTS_HOST: - sudo_lbuf_append(lbuf, "Defaults@"); - alias_type = expand_aliases ? HOSTALIAS : UNSPEC; - break; - case DEFAULTS_USER: - sudo_lbuf_append(lbuf, "Defaults:"); - alias_type = expand_aliases ? USERALIAS : UNSPEC; - break; - case DEFAULTS_RUNAS: - sudo_lbuf_append(lbuf, "Defaults>"); - alias_type = expand_aliases ? RUNASALIAS : UNSPEC; - break; - case DEFAULTS_CMND: - sudo_lbuf_append(lbuf, "Defaults!"); - alias_type = expand_aliases ? CMNDALIAS : UNSPEC; - break; - default: - sudo_lbuf_append(lbuf, "Defaults"); - alias_type = UNSPEC; - break; - } - TAILQ_FOREACH(m, d->binding, entries) { - if (m != TAILQ_FIRST(d->binding)) - sudo_lbuf_append(lbuf, ", "); - sudoers_format_member(lbuf, parse_tree, m, ", ", alias_type); - } - - sudo_lbuf_append(lbuf, " "); - sudoers_format_default(lbuf, d); - - if (next != NULL) { - /* Merge Defaults with the same binding, there may be multiple. */ - struct defaults *n; - while ((n = TAILQ_NEXT(d, entries)) && d->binding == n->binding) { - sudo_lbuf_append(lbuf, ", "); - sudoers_format_default(lbuf, n); - d = n; - } - *next = n; - } - sudo_lbuf_append(lbuf, "\n"); - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} diff --git a/plugins/sudoers/fmtsudoers_cvt.c b/plugins/sudoers/fmtsudoers_cvt.c new file mode 100644 index 000000000..a7f95d0ad --- /dev/null +++ b/plugins/sudoers/fmtsudoers_cvt.c @@ -0,0 +1,219 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2004-2005, 2007-2020 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. + */ + +/* + * 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 + +#include +#include +#include +#include + +#include "sudoers.h" +#include "sudo_lbuf.h" +#include + +/* + * Write a privilege to lbuf in sudoers format. + */ +bool +sudoers_format_privilege(struct sudo_lbuf *lbuf, + struct sudoers_parse_tree *parse_tree, struct privilege *priv, + bool expand_aliases) +{ + struct cmndspec *cs, *prev_cs; + struct cmndtag tags; + struct member *m; + debug_decl(sudoers_format_privilege, SUDOERS_DEBUG_UTIL); + + /* Convert per-privilege defaults to tags. */ + sudoers_defaults_list_to_tags(&priv->defaults, &tags); + + /* Print hosts list. */ + TAILQ_FOREACH(m, &priv->hostlist, entries) { + if (m != TAILQ_FIRST(&priv->hostlist)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, parse_tree, m, ", ", + expand_aliases ? HOSTALIAS : UNSPEC); + } + + /* Print commands. */ + sudo_lbuf_append(lbuf, " = "); + prev_cs = NULL; + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (prev_cs == NULL || RUNAS_CHANGED(cs, prev_cs)) { + if (cs != TAILQ_FIRST(&priv->cmndlist)) + sudo_lbuf_append(lbuf, ", "); + if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) + sudo_lbuf_append(lbuf, "("); + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m != TAILQ_FIRST(cs->runasuserlist)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, parse_tree, m, ", ", + expand_aliases ? RUNASALIAS : UNSPEC); + } + } + if (cs->runasgrouplist != NULL) { + sudo_lbuf_append(lbuf, " : "); + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m != TAILQ_FIRST(cs->runasgrouplist)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, parse_tree, m, ", ", + expand_aliases ? RUNASALIAS : UNSPEC); + } + } + if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) + sudo_lbuf_append(lbuf, ") "); + } else if (cs != TAILQ_FIRST(&priv->cmndlist)) { + sudo_lbuf_append(lbuf, ", "); + } + sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, tags, + expand_aliases); + prev_cs = cs; + } + + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +/* + * Write a userspec to lbuf in sudoers format. + */ +bool +sudoers_format_userspec(struct sudo_lbuf *lbuf, + struct sudoers_parse_tree *parse_tree, + struct userspec *us, bool expand_aliases) +{ + struct privilege *priv; + struct sudoers_comment *comment; + struct member *m; + debug_decl(sudoers_format_userspec, SUDOERS_DEBUG_UTIL); + + /* Print comments (if any). */ + STAILQ_FOREACH(comment, &us->comments, entries) { + sudo_lbuf_append(lbuf, "# %s\n", comment->str); + } + + /* Print users list. */ + TAILQ_FOREACH(m, &us->users, entries) { + if (m != TAILQ_FIRST(&us->users)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, parse_tree, m, ", ", + expand_aliases ? USERALIAS : UNSPEC); + } + + TAILQ_FOREACH(priv, &us->privileges, entries) { + if (priv != TAILQ_FIRST(&us->privileges)) + sudo_lbuf_append(lbuf, " : "); + else + sudo_lbuf_append(lbuf, " "); + if (!sudoers_format_privilege(lbuf, parse_tree, priv, expand_aliases)) + break; + } + sudo_lbuf_append(lbuf, "\n"); + + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +/* + * Write a userspec_list to lbuf in sudoers format. + */ +bool +sudoers_format_userspecs(struct sudo_lbuf *lbuf, + struct sudoers_parse_tree *parse_tree, const char *separator, + bool expand_aliases, bool flush) +{ + struct userspec *us; + debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL); + + TAILQ_FOREACH(us, &parse_tree->userspecs, entries) { + if (separator != NULL && us != TAILQ_FIRST(&parse_tree->userspecs)) + sudo_lbuf_append(lbuf, "%s", separator); + if (!sudoers_format_userspec(lbuf, parse_tree, us, expand_aliases)) + break; + sudo_lbuf_print(lbuf); + } + + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +/* + * Format and append a defaults line to the specified lbuf. + * If next, is specified, it must point to the next defaults + * entry in the list; this is used to print multiple defaults + * entries with the same binding on a single line. + */ +bool +sudoers_format_default_line(struct sudo_lbuf *lbuf, + struct sudoers_parse_tree *parse_tree, struct defaults *d, + struct defaults **next, bool expand_aliases) +{ + struct member *m; + int alias_type; + debug_decl(sudoers_format_default_line, SUDOERS_DEBUG_UTIL); + + /* Print Defaults type and binding (if present) */ + switch (d->type) { + case DEFAULTS_HOST: + sudo_lbuf_append(lbuf, "Defaults@"); + alias_type = expand_aliases ? HOSTALIAS : UNSPEC; + break; + case DEFAULTS_USER: + sudo_lbuf_append(lbuf, "Defaults:"); + alias_type = expand_aliases ? USERALIAS : UNSPEC; + break; + case DEFAULTS_RUNAS: + sudo_lbuf_append(lbuf, "Defaults>"); + alias_type = expand_aliases ? RUNASALIAS : UNSPEC; + break; + case DEFAULTS_CMND: + sudo_lbuf_append(lbuf, "Defaults!"); + alias_type = expand_aliases ? CMNDALIAS : UNSPEC; + break; + default: + sudo_lbuf_append(lbuf, "Defaults"); + alias_type = UNSPEC; + break; + } + TAILQ_FOREACH(m, d->binding, entries) { + if (m != TAILQ_FIRST(d->binding)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, parse_tree, m, ", ", alias_type); + } + + sudo_lbuf_append(lbuf, " "); + sudoers_format_default(lbuf, d); + + if (next != NULL) { + /* Merge Defaults with the same binding, there may be multiple. */ + struct defaults *n; + while ((n = TAILQ_NEXT(d, entries)) && d->binding == n->binding) { + sudo_lbuf_append(lbuf, ", "); + sudoers_format_default(lbuf, n); + d = n; + } + *next = n; + } + sudo_lbuf_append(lbuf, "\n"); + + debug_return_bool(!sudo_lbuf_error(lbuf)); +}