From: Todd C. Miller Date: Sat, 10 Feb 2018 01:22:04 +0000 (-0700) Subject: Move sudoers formatting code into fmtsudoers. X-Git-Tag: SUDO_1_8_23^2~142 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=64e99328e3fc2e5a913c236f9e6398334c92ed01;p=sudo Move sudoers formatting code into fmtsudoers. --- diff --git a/MANIFEST b/MANIFEST index d4ec2d6d7..a0f1471db 100644 --- a/MANIFEST +++ b/MANIFEST @@ -280,6 +280,7 @@ plugins/sudoers/filedigest.c plugins/sudoers/filedigest_gcrypt.c plugins/sudoers/filedigest_openssl.c plugins/sudoers/find_path.c +plugins/sudoers/fmtsudoers.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 f6ea6f40c..fb73b82a3 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -153,16 +153,16 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo digestname.lo \ timestr.lo toke.lo toke_util.lo SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo \ - env_pattern.lo find_path.lo gc.lo goodpath.lo group_plugin.lo \ - interfaces.lo iolog.lo iolog_path.lo locale.lo logging.lo \ - logwrap.lo mkdir_parents.lo parse.lo policy.lo prompt.lo \ - set_perms.lo starttime.lo sudo_nss.lo sudoers.lo \ + env_pattern.lo find_path.lo fmtsudoers.lo gc.lo goodpath.lo \ + group_plugin.lo interfaces.lo iolog.lo iolog_path.lo locale.lo \ + logging.lo logwrap.lo mkdir_parents.lo parse.lo policy.lo \ + prompt.lo set_perms.lo starttime.lo sudo_nss.lo sudoers.lo \ timestamp.lo @SUDOERS_OBJS@ VISUDO_OBJS = editor.o find_path.o goodpath.o locale.o stubs.o sudo_printf.o visudo.o CVTSUDOERS_OBJS = cvtsudoers.o cvtsudoers_json.o cvtsudoers_ldif.o \ - locale.o stubs.o sudo_printf.o + fmtsudoers.o locale.o stubs.o sudo_printf.o REPLAY_OBJS = getdate.o sudoreplay.o @@ -836,6 +836,18 @@ find_path.lo: $(srcdir)/find_path.c $(devdir)/def_data.h \ $(top_builddir)/pathnames.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/find_path.c find_path.o: find_path.lo +fmtsudoers.lo: $(srcdir)/fmtsudoers.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_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.c +fmtsudoers.o: fmtsudoers.lo fwtk.lo: $(authdir)/fwtk.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 ae0c477a6..ae96b3e85 100644 --- a/plugins/sudoers/cvtsudoers.c +++ b/plugins/sudoers/cvtsudoers.c @@ -232,52 +232,6 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen) return fopen(sudoers, "r"); } -/* - * Write the contents of a struct member to lbuf - */ -static bool -print_member_sudoers(struct sudo_lbuf *lbuf, struct member *m) -{ - struct sudo_command *c; - debug_decl(print_member_sudoers, SUDOERS_DEBUG_UTIL) - - switch (m->type) { - case ALL: - sudo_lbuf_append(lbuf, "%sALL", m->negated ? "!" : ""); - break; - case MYSELF: - /* nothing to print */ - break; - case COMMAND: - c = (struct sudo_command *)m->name; - if (m->negated) - sudo_lbuf_append(lbuf, "!"); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s", c->cmnd); - if (c->args) { - sudo_lbuf_append(lbuf, " "); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args); - } - break; - default: - /* Do not quote UID/GID, all others get quoted. */ - if (m->name[0] == '#' && - m->name[strspn(m->name + 1, "0123456789") + 1] == '\0') { - sudo_lbuf_append(lbuf, "%s%s", m->negated ? "!" : "", m->name); - } else { - if (strpbrk(m->name, " \t") != NULL) { - sudo_lbuf_append(lbuf, "%s\"", m->negated ? "!" : ""); - sudo_lbuf_append_quoted(lbuf, "\"", "%s", m->name); - sudo_lbuf_append(lbuf, "\""); - } else { - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s%s", - m->negated ? "!" : "", m->name); - } - } - break; - } - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - /* * Display Defaults entries */ @@ -310,25 +264,14 @@ print_defaults_sudoers(struct sudo_lbuf *lbuf) TAILQ_FOREACH(m, def->binding, entries) { if (m != TAILQ_FIRST(def->binding)) sudo_lbuf_append(lbuf, ", "); - print_member_sudoers(lbuf, m); + sudoers_format_member(lbuf, m, NULL, UNSPEC); } /* Print Defaults with the same binding, there may be multiple. */ for (;;) { + sudo_lbuf_append(lbuf, " "); + sudoers_format_default(lbuf, def); next = TAILQ_NEXT(def, entries); - if (def->val != NULL) { - sudo_lbuf_append(lbuf, " %s%s", def->var, - def->op == '+' ? "+=" : def->op == '-' ? "-=" : "="); - if (strpbrk(def->val, " \t") != NULL) { - sudo_lbuf_append(lbuf, "\""); - sudo_lbuf_append_quoted(lbuf, "\"", "%s", def->val); - sudo_lbuf_append(lbuf, "\""); - } else - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", def->val); - } else { - sudo_lbuf_append(lbuf, " %s%s", - def->op == false ? "!" : "", def->var); - } if (next == NULL || def->binding != next->binding) break; def = next; @@ -352,7 +295,7 @@ print_alias_sudoers(void *v1, void *v2) TAILQ_FOREACH(m, &a->members, entries) { if (m != TAILQ_FIRST(&a->members)) sudo_lbuf_append(lbuf, ", "); - print_member_sudoers(lbuf, m); + sudoers_format_member(lbuf, m, NULL, UNSPEC); } sudo_lbuf_append(lbuf, "\n"); @@ -372,155 +315,6 @@ print_aliases_sudoers(struct sudo_lbuf *lbuf) debug_return_bool(!sudo_lbuf_error(lbuf)); } -#define TAG_CHANGED(ocs, ncs, tt) \ - (TAG_SET((ncs)->tags.tt) && \ - ((ocs) == NULL || (ncs)->tags.tt != (ocs)->tags.tt)) - -/* - * XXX - same as parse.c:sudo_file_append_cmnd() - */ -static bool -print_cmndspec_sudoers(struct cmndspec *cs, struct cmndspec *prev_cs, - struct sudo_lbuf *lbuf) -{ - debug_decl(print_cmndspec_sudoers, SUDOERS_DEBUG_UTIL) - -#ifdef HAVE_PRIV_SET - if (cs->privs != NULL && cs->privs != prev_cs->privs) - sudo_lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs); - if (cs->limitprivs != NULL && cs->limitprivs != prev_cs->limitprivs) - sudo_lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs); -#endif /* HAVE_PRIV_SET */ -#ifdef HAVE_SELINUX - if (cs->role != NULL && cs->role != prev_cs->role) - sudo_lbuf_append(lbuf, "ROLE=%s ", cs->role); - if (cs->type != NULL && cs->type != prev_cs->type) - sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type); -#endif /* HAVE_SELINUX */ - if (cs->timeout > 0 && cs->timeout != prev_cs->timeout) { - char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2]; - snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout); - sudo_lbuf_append(lbuf, "TIMEOUT=%s ", numbuf); - } - if (cs->notbefore != UNSPEC && cs->notbefore != prev_cs->notbefore) { - char buf[sizeof("CCYYMMDDHHMMSSZ")]; - struct tm *tm = gmtime(&cs->notbefore); - snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf); - } - if (cs->notafter != UNSPEC && cs->notafter != prev_cs->notafter) { - char buf[sizeof("CCYYMMDDHHMMSSZ")]; - struct tm *tm = gmtime(&cs->notafter); - snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf); - } - if (TAG_CHANGED(prev_cs, cs, setenv)) - sudo_lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : "NOSETENV: "); - if (TAG_CHANGED(prev_cs, cs, noexec)) - sudo_lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : "EXEC: "); - if (TAG_CHANGED(prev_cs, cs, nopasswd)) - sudo_lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: "); - if (TAG_CHANGED(prev_cs, cs, log_input)) - sudo_lbuf_append(lbuf, cs->tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: "); - if (TAG_CHANGED(prev_cs, cs, log_output)) - sudo_lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); - if (TAG_CHANGED(prev_cs, cs, send_mail)) - sudo_lbuf_append(lbuf, cs->tags.send_mail ? "MAIL: " : "NOMAIL: "); - if (TAG_CHANGED(prev_cs, cs, follow)) - sudo_lbuf_append(lbuf, cs->tags.follow ? "FOLLOW: " : "NOFOLLOW: "); - print_member_sudoers(lbuf, cs->cmnd); - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - -/* - * Derived from parse.c:sudo_file_display_priv_short() - */ -static bool -print_userspec_sudoers(struct sudo_lbuf *lbuf, struct userspec *us) -{ - struct cmndspec *cs, *prev_cs; - struct privilege *priv; - struct member *m; - debug_decl(print_userspec_sudoers, SUDOERS_DEBUG_UTIL) - - /* Print users list. */ - TAILQ_FOREACH(m, &us->users, entries) { - if (m != TAILQ_FIRST(&us->users)) - sudo_lbuf_append(lbuf, ", "); - print_member_sudoers(lbuf, m); - } - - TAILQ_FOREACH(priv, &us->privileges, entries) { - /* Print hosts list. */ - if (priv != TAILQ_FIRST(&us->privileges)) - sudo_lbuf_append(lbuf, " : "); - else - sudo_lbuf_append(lbuf, " "); - TAILQ_FOREACH(m, &priv->hostlist, entries) { - if (m != TAILQ_FIRST(&priv->hostlist)) - sudo_lbuf_append(lbuf, ", "); - print_member_sudoers(lbuf, m); - } - - /* 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, ", "); - print_member_sudoers(lbuf, m); - } - } - if (cs->runasgrouplist != NULL) { - sudo_lbuf_append(lbuf, " : "); - TAILQ_FOREACH(m, cs->runasgrouplist, entries) { - if (m != TAILQ_FIRST(cs->runasgrouplist)) - sudo_lbuf_append(lbuf, ", "); - print_member_sudoers(lbuf, m); - } - } - if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) - sudo_lbuf_append(lbuf, ") "); - } else if (cs != TAILQ_FIRST(&priv->cmndlist)) { - sudo_lbuf_append(lbuf, ", "); - } - print_cmndspec_sudoers(cs, prev_cs, lbuf); - prev_cs = cs; - } - } - sudo_lbuf_append(lbuf, "\n"); - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - -/* - * Display User_Specs - */ -static bool -print_userspecs_sudoers(struct sudo_lbuf *lbuf) -{ - struct userspec *us; - debug_decl(print_userspecs_sudoers, SUDOERS_DEBUG_UTIL) - - TAILQ_FOREACH(us, &userspecs, entries) { - if (!print_userspec_sudoers(lbuf, us)) - break; - } - - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - static FILE *output_fp; /* global for convert_sudoers_output */ static int @@ -566,7 +360,7 @@ convert_sudoers_sudoers(const char *output_file) } /* Print User_Specs */ - if (!print_userspecs_sudoers(&lbuf)) + if (!sudoers_format_userspecs(&lbuf, &userspecs, false)) goto done; if (lbuf.len > 1) { sudo_lbuf_print(&lbuf); diff --git a/plugins/sudoers/fmtsudoers.c b/plugins/sudoers/fmtsudoers.c new file mode 100644 index 000000000..b57605e69 --- /dev/null +++ b/plugins/sudoers/fmtsudoers.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2004-2005, 2007-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 + +#include "sudoers.h" +#include "parse.h" +#include "sudo_lbuf.h" +#include + +/* + * Write the contents of a struct member to the lbuf. + * If alias_type is not UNSPEC, expand aliases using that type with + * the specified separator (which must not be NULL in the UNSPEC case). + */ +static bool +sudoers_format_member_int(struct sudo_lbuf *lbuf, char *name, int type, + int negated, const char *separator, int alias_type) +{ + struct alias *a; + struct member *m; + struct sudo_command *c; + debug_decl(sudoers_format_member_int, SUDOERS_DEBUG_UTIL) + + switch (type) { + case ALL: + sudo_lbuf_append(lbuf, "%sALL", negated ? "!" : ""); + break; + case MYSELF: + sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", user_name); + break; + case COMMAND: + c = (struct sudo_command *) name; + if (negated) + sudo_lbuf_append(lbuf, "!"); + sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s", c->cmnd); + if (c->args) { + sudo_lbuf_append(lbuf, " "); + sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args); + } + break; + case ALIAS: + if (alias_type != UNSPEC) { + if ((a = alias_get(name, alias_type)) != NULL) { + TAILQ_FOREACH(m, &a->members, entries) { + if (m != TAILQ_FIRST(&a->members)) + sudo_lbuf_append(lbuf, "%s", separator); + sudoers_format_member_int(lbuf, m->name, m->type, + negated ? !m->negated : m->negated, separator, + alias_type); + } + alias_put(a); + break; + } + } + /* FALLTHROUGH */ + default: + /* Do not quote UID/GID, all others get quoted. */ + if (name[0] == '#' && + name[strspn(name + 1, "0123456789") + 1] == '\0') { + sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", name); + } else { + if (strpbrk(name, " \t") != NULL) { + sudo_lbuf_append(lbuf, "%s\"", negated ? "!" : ""); + sudo_lbuf_append_quoted(lbuf, "\"", "%s", name); + sudo_lbuf_append(lbuf, "\""); + } else { + sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s%s", + negated ? "!" : "", name); + } + } + break; + } + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +bool +sudoers_format_member(struct sudo_lbuf *lbuf, struct member *m, + const char *separator, int alias_type) +{ + return sudoers_format_member_int(lbuf, m->name, m->type, m->negated, + separator, alias_type); +} + +#define FIELD_CHANGED(ocs, ncs, fld) \ + ((ocs) == NULL || (ncs)->fld != (ocs)->fld) + +#define TAG_CHANGED(ocs, ncs, tt) \ + (TAG_SET((ncs)->tags.tt) && FIELD_CHANGED(ocs, ncs, tags.tt)) + +/* + * Write a cmndspec to lbuf in sudoers format. + */ +bool +sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs, + struct cmndspec *prev_cs, bool expand_aliases) +{ + debug_decl(sudoers_format_cmndspec, SUDOERS_DEBUG_UTIL) + +#ifdef HAVE_PRIV_SET + if (cs->privs != NULL && FIELD_CHANGED(prev_cs, cs, privs)) + sudo_lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs); + if (cs->limitprivs != NULL && FIELD_CHANGED(prev_cs, cs, limitprivs)) + sudo_lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs); +#endif /* HAVE_PRIV_SET */ +#ifdef HAVE_SELINUX + if (cs->role != NULL && FIELD_CHANGED(prev_cs, cs, role)) + sudo_lbuf_append(lbuf, "ROLE=%s ", cs->role); + if (cs->type != NULL && FIELD_CHANGED(prev_cs, cs, type)) + sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type); +#endif /* HAVE_SELINUX */ + if (cs->timeout > 0 && FIELD_CHANGED(prev_cs, cs, timeout)) { + char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2]; + snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout); + sudo_lbuf_append(lbuf, "TIMEOUT=%s ", numbuf); + } + if (cs->notbefore != UNSPEC && FIELD_CHANGED(prev_cs, cs, notbefore)) { + char buf[sizeof("CCYYMMDDHHMMSSZ")]; + struct tm *tm = gmtime(&cs->notbefore); + snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf); + } + if (cs->notafter != UNSPEC && FIELD_CHANGED(prev_cs, cs, notafter)) { + char buf[sizeof("CCYYMMDDHHMMSSZ")]; + struct tm *tm = gmtime(&cs->notafter); + snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf); + } + if (TAG_CHANGED(prev_cs, cs, setenv)) + sudo_lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : "NOSETENV: "); + if (TAG_CHANGED(prev_cs, cs, noexec)) + sudo_lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : "EXEC: "); + if (TAG_CHANGED(prev_cs, cs, nopasswd)) + sudo_lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: "); + if (TAG_CHANGED(prev_cs, cs, log_input)) + sudo_lbuf_append(lbuf, cs->tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: "); + if (TAG_CHANGED(prev_cs, cs, log_output)) + sudo_lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); + if (TAG_CHANGED(prev_cs, cs, send_mail)) + sudo_lbuf_append(lbuf, cs->tags.send_mail ? "MAIL: " : "NOMAIL: "); + if (TAG_CHANGED(prev_cs, cs, follow)) + sudo_lbuf_append(lbuf, cs->tags.follow ? "FOLLOW: " : "NOFOLLOW: "); + sudoers_format_member(lbuf, cs->cmnd, ", ", + expand_aliases ? CMNDALIAS : UNSPEC); + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +/* + * Write a privilege to lbuf in sudoers format. + */ +bool +sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv, + bool expand_aliases) +{ + struct cmndspec *cs, *prev_cs; + struct member *m; + debug_decl(sudoers_format_userspec, SUDOERS_DEBUG_UTIL) + + /* Print hosts list. */ + TAILQ_FOREACH(m, &priv->hostlist, entries) { + if (m != TAILQ_FIRST(&priv->hostlist)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, 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, 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, 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, cs, prev_cs, 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 userspec *us, + bool expand_aliases) +{ + struct privilege *priv; + struct member *m; + debug_decl(sudoers_format_userspec, SUDOERS_DEBUG_UTIL) + + /* Print users list. */ + TAILQ_FOREACH(m, &us->users, entries) { + if (m != TAILQ_FIRST(&us->users)) + sudo_lbuf_append(lbuf, ", "); + sudoers_format_member(lbuf, m, NULL, 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, 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 userspec_list *usl, + bool expand_aliases) +{ + struct userspec *us; + debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL) + + TAILQ_FOREACH(us, usl, entries) { + if (!sudoers_format_userspec(lbuf, us, expand_aliases)) + break; + } + + debug_return_bool(!sudo_lbuf_error(lbuf)); +} + +/* + * Format and append a defaults entry to the specified lbuf. + */ +bool +sudoers_format_default(struct sudo_lbuf *lbuf, struct defaults *d) +{ + debug_decl(sudoers_format_default, SUDOERS_DEBUG_UTIL) + + if (d->val != NULL) { + sudo_lbuf_append(lbuf, "%s%s", d->var, + d->op == '+' ? "+=" : d->op == '-' ? "-=" : "="); + if (strpbrk(d->val, " \t") != NULL) { + sudo_lbuf_append(lbuf, "\""); + sudo_lbuf_append_quoted(lbuf, "\"", "%s", d->val); + sudo_lbuf_append(lbuf, "\""); + } else + sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); + } else { + sudo_lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var); + } + debug_return_bool(!sudo_lbuf_error(lbuf)); +} diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index fc6773f03..a781635aa 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -2284,7 +2284,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw, sudo_lbuf_append(lbuf, "%s", prefix); d.op = sudo_ldap_parse_option((*p)->bv_val, &d.var, &d.val); - sudo_lbuf_append_default(lbuf, &d); + sudoers_format_default(lbuf, &d); prefix = ", "; count++; } diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index 9d3682b29..9ff707dbd 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -51,8 +51,6 @@ static int sudo_file_lookup(struct sudo_nss *, int, int); static int sudo_file_open(struct sudo_nss *); static int sudo_file_parse(struct sudo_nss *); static int sudo_file_setdefs(struct sudo_nss *); -static void print_member(struct sudo_lbuf *lbuf, struct member *m, int alias_type); -static void print_member_sep(struct sudo_lbuf *lbuf, struct member *m, const char *separator, int alias_type); /* sudo_nss implementation */ struct sudo_nss sudo_nss_file = { @@ -364,90 +362,6 @@ done: debug_return_int(validated); } -#define TAG_CHANGED(ocs, ncs, tt) \ - (TAG_SET((ncs)->tags.tt) && \ - ((ocs) == NULL || (ncs)->tags.tt != (ocs)->tags.tt)) - -static bool -sudo_file_append_cmnd(struct cmndspec *cs, struct cmndspec *prev_cs, - struct sudo_lbuf *lbuf) -{ - debug_decl(sudo_file_append_cmnd, SUDOERS_DEBUG_NSS) - -#ifdef HAVE_PRIV_SET - if (cs->privs != NULL && cs->privs != prev_cs->privs) - sudo_lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs); - if (cs->limitprivs != NULL && cs->limitprivs != prev_cs->limitprivs) - sudo_lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs); -#endif /* HAVE_PRIV_SET */ -#ifdef HAVE_SELINUX - if (cs->role != NULL && cs->role != prev_cs->role) - sudo_lbuf_append(lbuf, "ROLE=%s ", cs->role); - if (cs->type != NULL && cs->type != prev_cs->type) - sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type); -#endif /* HAVE_SELINUX */ - if (cs->timeout > 0 && cs->timeout != prev_cs->timeout) { - char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2]; - snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout); - sudo_lbuf_append(lbuf, "TIMEOUT=%s ", numbuf); - } - if (cs->notbefore != UNSPEC && cs->notbefore != prev_cs->notbefore) { - char buf[sizeof("CCYYMMDDHHMMSSZ")]; - struct tm *tm = gmtime(&cs->notbefore); - snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf); - } - if (cs->notafter != UNSPEC && cs->notafter != prev_cs->notafter) { - char buf[sizeof("CCYYMMDDHHMMSSZ")]; - struct tm *tm = gmtime(&cs->notafter); - snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf); - } - if (TAG_CHANGED(prev_cs, cs, setenv)) - sudo_lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : "NOSETENV: "); - if (TAG_CHANGED(prev_cs, cs, noexec)) - sudo_lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : "EXEC: "); - if (TAG_CHANGED(prev_cs, cs, nopasswd)) - sudo_lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: "); - if (TAG_CHANGED(prev_cs, cs, log_input)) - sudo_lbuf_append(lbuf, cs->tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: "); - if (TAG_CHANGED(prev_cs, cs, log_output)) - sudo_lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); - if (TAG_CHANGED(prev_cs, cs, send_mail)) - sudo_lbuf_append(lbuf, cs->tags.send_mail ? "MAIL: " : "NOMAIL: "); - if (TAG_CHANGED(prev_cs, cs, follow)) - sudo_lbuf_append(lbuf, cs->tags.follow ? "FOLLOW: " : "NOFOLLOW: "); - print_member(lbuf, cs->cmnd, CMNDALIAS); - debug_return_bool(!sudo_lbuf_error(lbuf)); -} - -/* - * Format and append a defaults entry to the specified lbuf. - */ -void -sudo_lbuf_append_default(struct sudo_lbuf *lbuf, struct defaults *d) -{ - debug_decl(sudo_lbuf_append_default, SUDOERS_DEBUG_NSS) - - if (d->val != NULL) { - sudo_lbuf_append(lbuf, "%s%s", d->var, - d->op == '+' ? "+=" : d->op == '-' ? "-=" : "="); - if (strpbrk(d->val, " \t") != NULL) { - sudo_lbuf_append(lbuf, "\""); - sudo_lbuf_append_quoted(lbuf, "\"", "%s", d->val); - sudo_lbuf_append(lbuf, "\""); - } else - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); - } else { - sudo_lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var); - } - debug_return; -} - static int sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, struct sudo_lbuf *lbuf) @@ -472,7 +386,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, TAILQ_FOREACH(m, cs->runasuserlist, entries) { if (m != TAILQ_FIRST(cs->runasuserlist)) sudo_lbuf_append(lbuf, ", "); - print_member(lbuf, m, RUNASALIAS); + sudoers_format_member(lbuf, m, ", ", RUNASALIAS); } } else if (cs->runasgrouplist == NULL) { sudo_lbuf_append(lbuf, "%s", def_runas_default); @@ -484,14 +398,14 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, TAILQ_FOREACH(m, cs->runasgrouplist, entries) { if (m != TAILQ_FIRST(cs->runasgrouplist)) sudo_lbuf_append(lbuf, ", "); - print_member(lbuf, m, RUNASALIAS); + sudoers_format_member(lbuf, m, ", ", RUNASALIAS); } } sudo_lbuf_append(lbuf, ") "); } else if (cs != TAILQ_FIRST(&priv->cmndlist)) { sudo_lbuf_append(lbuf, ", "); } - sudo_file_append_cmnd(cs, prev_cs, lbuf); + sudoers_format_cmndspec(lbuf, cs, prev_cs, true); prev_cs = cs; nfound++; } @@ -539,8 +453,6 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, { struct cmndspec *cs, *prev_cs; struct privilege *priv; - struct defaults *def; - struct member *m; int nfound = 0, olen; debug_decl(sudo_file_display_priv_long, SUDOERS_DEBUG_NSS) @@ -549,6 +461,9 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, continue; prev_cs = NULL; TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + struct defaults *d; + struct member *m; + if (new_long_entry(cs, prev_cs)) { if (priv->ldap_role != NULL) { sudo_lbuf_append(lbuf, _("\nLDAP Role: %s\n"), @@ -561,7 +476,7 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, TAILQ_FOREACH(m, cs->runasuserlist, entries) { if (m != TAILQ_FIRST(cs->runasuserlist)) sudo_lbuf_append(lbuf, ", "); - print_member(lbuf, m, RUNASALIAS); + sudoers_format_member(lbuf, m, ", ", RUNASALIAS); } } else if (cs->runasgrouplist == NULL) { sudo_lbuf_append(lbuf, "%s", def_runas_default); @@ -574,14 +489,14 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, TAILQ_FOREACH(m, cs->runasgrouplist, entries) { if (m != TAILQ_FIRST(cs->runasgrouplist)) sudo_lbuf_append(lbuf, ", "); - print_member(lbuf, m, RUNASALIAS); + sudoers_format_member(lbuf, m, ", ", RUNASALIAS); } sudo_lbuf_append(lbuf, "\n"); } olen = lbuf->len; sudo_lbuf_append(lbuf, _(" Options: ")); - TAILQ_FOREACH(def, &priv->defaults, entries) { - sudo_lbuf_append_default(lbuf, def); + TAILQ_FOREACH(d, &priv->defaults, entries) { + sudoers_format_default(lbuf, d); sudo_lbuf_append(lbuf, ", "); } if (TAG_SET(cs->tags.setenv)) @@ -636,7 +551,7 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, sudo_lbuf_append(lbuf, _(" Commands:\n")); } sudo_lbuf_append(lbuf, "\t"); - print_member_sep(lbuf, cs->cmnd, "\n\t", CMNDALIAS); + sudoers_format_member(lbuf, cs->cmnd, "\n\t", CMNDALIAS); sudo_lbuf_append(lbuf, "\n"); prev_cs = cs; nfound++; @@ -718,7 +633,7 @@ sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw, continue; } sudo_lbuf_append(lbuf, "%s", prefix); - sudo_lbuf_append_default(lbuf, d); + sudoers_format_default(lbuf, d); prefix = ", "; nfound++; } @@ -793,12 +708,12 @@ display_bound_defaults(int deftype, struct sudo_lbuf *lbuf) TAILQ_FOREACH(m, binding, entries) { if (m != TAILQ_FIRST(binding)) sudo_lbuf_append(lbuf, ","); - print_member(lbuf, m, atype); + sudoers_format_member(lbuf, m, ", ", atype); sudo_lbuf_append(lbuf, " "); } } else sudo_lbuf_append(lbuf, ", "); - sudo_lbuf_append_default(lbuf, d); + sudoers_format_default(lbuf, d); } if (sudo_lbuf_error(lbuf)) @@ -855,78 +770,3 @@ sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw) done: debug_return_int(ret); } - -/* - * Write the contents of a struct member to the lbuf - */ -static void -print_member_int(struct sudo_lbuf *lbuf, char *name, int type, int negated, - const char *separator, int alias_type) -{ - struct alias *a; - struct member *m; - struct sudo_command *c; - debug_decl(print_member_int, SUDOERS_DEBUG_NSS) - - switch (type) { - case ALL: - sudo_lbuf_append(lbuf, "%sALL", negated ? "!" : ""); - break; - case MYSELF: - sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", user_name); - break; - case COMMAND: - c = (struct sudo_command *) name; - if (negated) - sudo_lbuf_append(lbuf, "!"); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s", c->cmnd); - if (c->args) { - sudo_lbuf_append(lbuf, " "); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args); - } - break; - case ALIAS: - if ((a = alias_get(name, alias_type)) != NULL) { - TAILQ_FOREACH(m, &a->members, entries) { - if (m != TAILQ_FIRST(&a->members)) - sudo_lbuf_append(lbuf, "%s", separator); - print_member_int(lbuf, m->name, m->type, - negated ? !m->negated : m->negated, separator, - alias_type); - } - alias_put(a); - break; - } - /* FALLTHROUGH */ - default: - /* Do not quote UID/GID, all others get quoted. */ - if (name[0] == '#' && - name[strspn(name + 1, "0123456789") + 1] == '\0') { - sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", name); - } else { - if (strpbrk(name, " \t") != NULL) { - sudo_lbuf_append(lbuf, "%s\"", negated ? "!" : ""); - sudo_lbuf_append_quoted(lbuf, "\"", "%s", name); - sudo_lbuf_append(lbuf, "\""); - } else { - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s%s", - negated ? "!" : "", name); - } - } - break; - } - debug_return; -} - -static void -print_member(struct sudo_lbuf *lbuf, struct member *m, int alias_type) -{ - print_member_int(lbuf, m->name, m->type, m->negated, ", ", alias_type); -} - -static void -print_member_sep(struct sudo_lbuf *lbuf, struct member *m, - const char *separator, int alias_type) -{ - print_member_int(lbuf, m->name, m->type, m->negated, separator, alias_type); -} diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index a725c86e2..e903adba5 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -308,6 +308,13 @@ const char *digest_type_to_name(int digest_type); /* parse.c */ struct sudo_lbuf; int sudo_display_userspecs(struct userspec_list *usl, struct passwd *pw, struct sudo_lbuf *lbuf); -void sudo_lbuf_append_default(struct sudo_lbuf *lbuf, struct defaults *d); + +/* fmtsudoers.c */ +bool sudoers_format_cmndspec(struct sudo_lbuf *lbuf, struct cmndspec *cs, struct cmndspec *prev_cs, bool expand_aliases); +bool sudoers_format_default(struct sudo_lbuf *lbuf, struct defaults *d); +bool sudoers_format_member(struct sudo_lbuf *lbuf, struct member *m, const char *separator, int alias_type); +bool sudoers_format_privilege(struct sudo_lbuf *lbuf, struct privilege *priv, bool expand_aliases); +bool sudoers_format_userspec(struct sudo_lbuf *lbuf, struct userspec *us, bool expand_aliases); +bool sudoers_format_userspecs(struct sudo_lbuf *lbuf, struct userspec_list *usl, bool expand_aliases); #endif /* SUDOERS_PARSE_H */ diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c index d2cc79d7f..c1fd1ec97 100644 --- a/plugins/sudoers/sssd.c +++ b/plugins/sudoers/sssd.c @@ -1383,7 +1383,7 @@ sudo_sss_display_defaults(struct sudo_nss *nss, struct passwd *pw, sudo_lbuf_append(lbuf, "%s", prefix); d.op = sudo_ldap_parse_option(val_array[j], &d.var, &d.val); - sudo_lbuf_append_default(lbuf, &d); + sudoers_format_default(lbuf, &d); prefix = ", "; count++; }