diff --git a/MANIFEST b/MANIFEST index ab6b14472..342b9c2af 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1149,6 +1149,7 @@ plugins/sudoers/regress/visudo/test9.out.ok plugins/sudoers/regress/visudo/test9.sh plugins/sudoers/serialize_list.c plugins/sudoers/set_perms.c +plugins/sudoers/sethost.c plugins/sudoers/solaris_audit.c plugins/sudoers/solaris_audit.h plugins/sudoers/sssd.c diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 75e616c2a..e36f413dc 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -189,22 +189,23 @@ SUDOERS_OBJS = $(AUTH_OBJS) audit.lo boottime.lo callbacks.lo check.lo \ gc.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \ iolog_path_escapes.lo locale.lo log_client.lo logging.lo \ lookup.lo pivot.lo policy.lo prompt.lo serialize_list.lo \ - set_perms.lo starttime.lo strlcpy_unesc.lo strvec_join.lo \ - sudo_nss.lo sudoers.lo sudoers_ctx_free.lo timestamp.lo \ - unesc_str.lo @SUDOERS_OBJS@ + set_perms.lo sethost.lo starttime.lo strlcpy_unesc.lo \ + strvec_join.lo sudo_nss.lo sudoers.lo sudoers_ctx_free.lo \ + timestamp.lo unesc_str.lo @SUDOERS_OBJS@ SUDOERS_IOBJS = $(SUDOERS_OBJS:.lo=.i) VISUDO_OBJS = check_aliases.o editor.lo find_path.lo gc.lo goodpath.lo \ - locale.lo stubs.o sudo_printf.o sudoers_ctx_free.lo visudo.o + locale.lo sethost.lo stubs.o sudo_printf.o sudoers_ctx_free.lo \ + visudo.o VISUDO_IOBJS = sudo_printf.i visudo.i CVTSUDOERS_OBJS = b64_encode.o cvtsudoers.o cvtsudoers_json.o cvtsudoers_csv.o \ cvtsudoers_ldif.o cvtsudoers_merge.o cvtsudoers_pwutil.o \ fmtsudoers.lo fmtsudoers_cvt.lo locale.lo parse_ldif.o \ - stubs.o sudo_printf.o sudoers_ctx_free.lo ldap_util.lo \ - testsudoers_pwutil.o tsgetgrpw.o + sethost.lo stubs.o sudo_printf.o sudoers_ctx_free.lo \ + ldap_util.lo testsudoers_pwutil.o tsgetgrpw.o CVTSUDOERS_IOBJS = cvtsudoers.i cvtsudoers_csv.i cvtsudoers_json.i \ cvtsudoers_ldif.i cvtsudoers_merge.i cvtsudoers_pwutil.i @@ -215,8 +216,8 @@ REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i) TEST_OBJS = check_util.lo fmtsudoers.lo fmtsudoers_cvt.lo group_plugin.lo \ interfaces.lo ldap_util.lo locale.lo lookup.lo net_ifs.o \ - parse_ldif.o sudo_printf.o sudoers_ctx_free.lo testsudoers.o \ - testsudoers_pwutil.o tsgetgrpw.o + parse_ldif.o sethost.lo sudo_printf.o sudoers_ctx_free.lo \ + testsudoers.o testsudoers_pwutil.o tsgetgrpw.o IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \ $(CVTSUDOERS_IOBJS) $(REPLAY_IOBJS) @@ -258,7 +259,7 @@ CHECK_SERIALIZE_LIST_OBJS = check_serialize_list.lo serialize_list.lo \ FUZZ_POLICY_OBJS = callbacks.lo editor.lo env.lo env_pattern.lo fuzz_policy.o \ fuzz_stubs.o gc.lo iolog_path_escapes.lo locale.lo \ - policy.lo serialize_list.lo strlcpy_unesc.lo \ + policy.lo sethost.lo serialize_list.lo strlcpy_unesc.lo \ strvec_join.lo sudoers.lo sudoers_ctx_free.lo \ sudoers_hooks.lo @@ -2771,6 +2772,28 @@ set_perms.i: $(srcdir)/set_perms.c $(devdir)/def_data.h \ $(CC) -E -o $@ $(CPPFLAGS) $< set_perms.plog: set_perms.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/set_perms.c --i-file $< --output-file $@ +sethost.lo: $(srcdir)/sethost.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) $(HARDENING_CFLAGS) $(srcdir)/sethost.c +sethost.i: $(srcdir)/sethost.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) $< +sethost.plog: sethost.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sethost.c --i-file $< --output-file $@ sia.lo: $(authdir)/sia.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \ diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c index 0df53f456..c4b4707f2 100644 --- a/plugins/sudoers/cvtsudoers.c +++ b/plugins/sudoers/cvtsudoers.c @@ -357,7 +357,8 @@ main(int argc, char *argv[]) } /* We may need the hostname to resolve %h escapes in include files. */ - get_hostname(&ctx); + if (!sudoers_sethost(&ctx, NULL, NULL)) + goto done; do { char *lhost = NULL, *shost = NULL; diff --git a/plugins/sudoers/cvtsudoers.h b/plugins/sudoers/cvtsudoers.h index f2991b05f..02c6bd236 100644 --- a/plugins/sudoers/cvtsudoers.h +++ b/plugins/sudoers/cvtsudoers.h @@ -107,7 +107,4 @@ struct cache_item *cvtsudoers_make_gritem(gid_t gid, const char *name); struct cache_item *cvtsudoers_make_gidlist_item(const struct passwd *pw, int unusued1, GETGROUPS_T *unused2, char * const *unused3, unsigned int type); struct cache_item *cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1); -/* stubs.c */ -void get_hostname(struct sudoers_context *ctx); - #endif /* SUDOERS_CVTSUDOERS_H */ diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index 5f5a8d431..fba133f83 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -98,6 +98,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, const char *p, *errstr, *groups = NULL; struct sudoers_open_info *info = v; unsigned int flags = MODE_UPDATE_TICKET; + const char *host = NULL; const char *remhost = NULL; unsigned char uuid[16]; char * const *cur; @@ -464,18 +465,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, } if (MATCHES(*cur, "host=")) { CHECK(*cur, "host="); - if (ctx->user.shost != ctx->user.host) - free(ctx->user.shost); - free(ctx->user.host); - if ((ctx->user.host = strdup(*cur + sizeof("host=") - 1)) == NULL) - goto oom; - if ((p = strchr(ctx->user.host, '.')) != NULL) { - ctx->user.shost = strndup(ctx->user.host, (size_t)(p - ctx->user.host)); - if (ctx->user.shost == NULL) - goto oom; - } else { - ctx->user.shost = ctx->user.host; - } + host = *cur + sizeof("host=") - 1; continue; } if (MATCHES(*cur, "lines=")) { @@ -538,26 +528,14 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, sudo_warnx("%s", U_("group-ID not set by sudo front-end")); goto bad; } - if (ctx->user.host == NULL) { + if (host == NULL) { sudo_warnx("%s", U_("host name not set by sudo front-end")); goto bad; } - if (ctx->runas.shost != ctx->runas.host) - free(ctx->runas.shost); - free(ctx->runas.host); - if ((ctx->runas.host = strdup(remhost ? remhost : ctx->user.host)) == NULL) - goto oom; - if ((p = strchr(ctx->runas.host, '.')) != NULL) { - ctx->runas.shost = strndup(ctx->runas.host, (size_t)(p - ctx->runas.host)); - if (ctx->runas.shost == NULL) - goto oom; - } else { - ctx->runas.shost = ctx->runas.host; - } - if (ctx->user.cwd == NULL) { - if ((ctx->user.cwd = strdup("unknown")) == NULL) - goto oom; + if (!sudoers_sethost(ctx, host, remhost)) { + /* sudoers_sethost() will print a warning on error. */ + goto bad; } if (ctx->user.tty == NULL) { if ((ctx->user.tty = strdup("unknown")) == NULL) diff --git a/plugins/sudoers/sethost.c b/plugins/sudoers/sethost.c new file mode 100644 index 000000000..17c402a7a --- /dev/null +++ b/plugins/sudoers/sethost.c @@ -0,0 +1,87 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2018-2023 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 "sudoers.h" + +/* + * Set ctx->user.host. ctx->user.shost, ctx->runas.host and ctx->runas.shost + * based on the local and remote host names. If host is NULL, the local + * host name is used. If remhost is NULL, the same value as host is used. + */ +bool +sudoers_sethost(struct sudoers_context *ctx, const char *host, + const char *remhost) +{ + char *cp; + debug_decl(sudoers_sethost, SUDOERS_DEBUG_UTIL); + + if (ctx->user.shost != ctx->user.host) + free(ctx->user.shost); + free(ctx->user.host); + ctx->user.host = NULL; + ctx->user.shost = NULL; + + if (host == NULL) + ctx->user.host = sudo_gethostname(); + else + ctx->user.host = strdup(host); + if (ctx->user.host == NULL) + goto oom; + if ((cp = strchr(ctx->user.host, '.')) != NULL) { + ctx->user.shost = strndup(ctx->user.host, + (size_t)(cp - ctx->user.host)); + if (ctx->user.shost == NULL) + goto oom; + } else { + ctx->user.shost = ctx->user.host; + } + + if (ctx->runas.shost != ctx->runas.host) + free(ctx->runas.shost); + free(ctx->runas.host); + ctx->runas.host = NULL; + ctx->runas.shost = NULL; + + ctx->runas.host = strdup(remhost ? remhost : ctx->user.host); + if (ctx->runas.host == NULL) + goto oom; + if ((cp = strchr(ctx->runas.host, '.')) != NULL) { + ctx->runas.shost = strndup(ctx->runas.host, + (size_t)(cp - ctx->runas.host)); + if (ctx->runas.shost == NULL) + goto oom; + } else { + ctx->runas.shost = ctx->runas.host; + } + + debug_return_bool(true); +oom: + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_bool(false); +} diff --git a/plugins/sudoers/stubs.c b/plugins/sudoers/stubs.c index 82d69d5a8..850ccf43d 100644 --- a/plugins/sudoers/stubs.c +++ b/plugins/sudoers/stubs.c @@ -109,42 +109,3 @@ unpivot_root(int fds[2]) { return true; } - -/* - * Look up the hostname and set ctx->user.host and ctx->user.shost. - */ -void -get_hostname(struct sudoers_context *ctx) -{ - char *cp; - debug_decl(get_hostname, SUDOERS_DEBUG_UTIL); - - if ((ctx->user.host = sudo_gethostname()) != NULL) { - if ((cp = strchr(ctx->user.host, '.'))) { - *cp = '\0'; - if ((ctx->user.shost = strdup(ctx->user.host)) == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - *cp = '.'; - } else { - ctx->user.shost = ctx->user.host; - } - } else { - ctx->user.host = ctx->user.shost = strdup("localhost"); - if (ctx->user.host == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - } - - ctx->runas.host = strdup(ctx->user.host); - if (ctx->runas.host == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - if ((cp = strchr(ctx->runas.host, '.'))) { - *cp = '\0'; - if ((ctx->runas.shost = strdup(ctx->runas.host)) == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - *cp = '.'; - } else { - ctx->runas.shost = ctx->runas.host; - } - - debug_return; -} diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index fd07f0287..9b9865e64 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -490,4 +490,7 @@ char *serialize_list(const char *varname, struct list_members *members); bool pivot_root(const char *new_root, int fds[2]); bool unpivot_root(int fds[2]); +/* sethost.c */ +bool sudoers_sethost(struct sudoers_context *ctx, const char *host, const char *remhost); + #endif /* SUDOERS_SUDOERS_H */ diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 2f10c4c8c..e9df453f5 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -96,6 +96,7 @@ main(int argc, char *argv[]) enum sudoers_formats input_format = format_sudoers; struct sudo_nss testsudoers_nss; char *p, *grfile, *pwfile; + const char *host = NULL; const char *errstr; int ch, dflag, exitcode = EXIT_FAILURE; unsigned int validated; @@ -150,11 +151,7 @@ main(int argc, char *argv[]) SET(test_ctx.settings.flags, RUNAS_GROUP_SPECIFIED); break; case 'h': - test_ctx.user.host = strdup(optarg); - if (test_ctx.user.host == NULL) { - sudo_fatalx(U_("%s: %s"), __func__, - U_("unable to allocate memory")); - } + host = optarg; break; case 'i': if (strcasecmp(optarg, "ldif") == 0) { @@ -284,28 +281,8 @@ main(int argc, char *argv[]) test_ctx.user.uid = test_ctx.user.pw->pw_uid; test_ctx.user.gid = test_ctx.user.pw->pw_gid; - if (test_ctx.user.host == NULL) { - if ((test_ctx.user.host = sudo_gethostname()) == NULL) - sudo_fatal("gethostname"); - } - if ((p = strchr(test_ctx.user.host, '.'))) { - *p = '\0'; - if ((test_ctx.user.shost = strdup(test_ctx.user.host)) == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - *p = '.'; - } else { - test_ctx.user.shost = test_ctx.user.host; - } - if ((test_ctx.runas.host = strdup(test_ctx.user.host)) == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - if ((p = strchr(test_ctx.runas.host, '.'))) { - *p = '\0'; - if ((test_ctx.runas.shost = strdup(test_ctx.runas.host)) == NULL) - sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - *p = '.'; - } else { - test_ctx.runas.shost = test_ctx.runas.host; - } + if (!sudoers_sethost(&test_ctx, host, NULL)) + goto done; /* Fill in test_ctx.user.cmnd_args from argv. */ if (argc > 0) { diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index ce2192b3c..038fedf7d 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -103,8 +103,6 @@ sudo_noreturn static void export_sudoers(const char *infile, const char *outfile sudo_noreturn static void help(void); sudo_noreturn static void usage(void); -extern void get_hostname(struct sudoers_context *ctx); - /* * Globals */ @@ -269,7 +267,8 @@ main(int argc, char *argv[]) if ((ctx.user.pw = sudo_getpwuid(getuid())) == NULL) sudo_fatalx(U_("you do not exist in the %s database"), "passwd"); } - get_hostname(&ctx); + if (!sudoers_sethost(&ctx, NULL, NULL)) + return EXIT_FAILURE; /* Hook the sudoers parser to track files with parse errors. */ sudoers_error_hook = visudo_track_error;