From 5635c22f6b1f007adffbbdc5cabf5ed30b72e914 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 26 Feb 2020 13:17:40 -0700 Subject: [PATCH] Add --disable-log-server and --disable-log-client configure options. These can be used to optionally disable building sudo_logsrvd and support for remote I/O logging in the sudoers plugin respectively. --- INSTALL | 11 +++ Makefile.in | 7 +- config.h.in | 4 + configure | 57 ++++++++++++++ configure.ac | 39 ++++++++++ lib/iolog/iolog_fileio.c | 2 + plugins/sudoers/Makefile.in | 2 +- plugins/sudoers/iolog.c | 138 +++++++++++++++++++++++---------- plugins/sudoers/iolog_client.c | 11 ++- plugins/sudoers/iolog_plugin.h | 2 +- plugins/sudoers/sudoers.c | 8 +- 11 files changed, 230 insertions(+), 51 deletions(-) diff --git a/INSTALL b/INSTALL index bc6be1c62..fe57f918a 100644 --- a/INSTALL +++ b/INSTALL @@ -370,6 +370,17 @@ Optional features: platform type. The "pvs-studio" Makefile target can then be used if PVS-Studio is installed. + --enable-python + Enable support for sudo plugins written in Python 3. + This requires a Python 3 development environment (including + Python 3 header files). + + --disable-log-server + Disable building the sudo_logsrvd log server. + + --disable-log-client + Disable sudoers support for using the sudo_logsrvd log server. + Operating system-specific options: --disable-setreuid Disable use of the setreuid() function for operating systems diff --git a/Makefile.in b/Makefile.in index 52038e384..9a2921bb8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -53,9 +53,10 @@ sudoers_gid = @SUDOERS_GID@ sudoers_mode = @SUDOERS_MODE@ shlib_mode = @SHLIB_MODE@ -SUBDIRS = lib/util @ZLIB_SRC@ lib/iolog lib/logsrv logsrvd plugins/audit_json \ - plugins/group_file plugins/sample_approval plugins/sudoers \ - plugins/system_group @PYTHON_PLUGIN_SRC@ src include doc examples +SUBDIRS = lib/util @ZLIB_SRC@ lib/iolog @LOGSRV@ @LOGSRVD@ \ + plugins/audit_json plugins/group_file plugins/sample_approval \ + plugins/sudoers plugins/system_group @PYTHON_PLUGIN_SRC@ src \ + include doc examples SAMPLES = plugins/sample diff --git a/config.h.in b/config.h.in index cd7f677cd..8275de097 100644 --- a/config.h.in +++ b/config.h.in @@ -1149,6 +1149,10 @@ /* Define to 1 if the code in interfaces.c does not compile for you. */ #undef STUB_LOAD_INTERFACES +/* Define to 1 to compile support for sudo_logsrvd in the sudoers I/O log + plugin. */ +#undef SUDOERS_IOLOG_CLIENT + /* An instance string to append to the username (separated by a slash) for Kerberos V authentication. */ #undef SUDO_KRB5_INSTANCE diff --git a/configure b/configure index 81f4d0bf9..1433e27e2 100755 --- a/configure +++ b/configure @@ -736,6 +736,9 @@ rundir logpath log_dir iolog_dir +LOGSRVD +LIBLOGSRV +LOGSRV PYTHON_PLUGIN_SRC SIGNAME devsearch @@ -987,6 +990,8 @@ enable_offensive_insults enable_package_build enable_gss_krb5_ccache_name enable_pvs_studio +enable_log_server +enable_log_client enable_shared enable_static with_pic @@ -1682,6 +1687,9 @@ Optional Features: --enable-gss-krb5-ccache-name Use GSS-API to set the Kerberos V cred cache name --enable-pvs-studio Create a PVS-Studio.cfg file. + --disable-log-server Disable building the sudo_logsrvd log server. + --disable-log-client Disable sudoers support for using the sudo_logsrvd + log server. --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] @@ -3108,6 +3116,9 @@ $as_echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} + + + @@ -3207,6 +3218,9 @@ shadow_funcs= shadow_libs= TMPFILES_D= CONFIGURE_ARGS="$@" +LOGSRVD=logsrvd +LOGSRV=lib/logsrv +LIBLOGSRV='$(top_builddir)/lib/logsrv/liblogsrv.la' RTLD_PRELOAD_VAR="LD_PRELOAD" RTLD_PRELOAD_ENABLE_VAR= @@ -6921,6 +6935,48 @@ if test "${enable_pvs_studio+set}" = set; then : fi +# Check whether --enable-log-server was given. +if test "${enable_log_server+set}" = set; then : + enableval=$enable_log_server; case "$enableval" in + yes) + ;; + no) + LOGSRVD= + ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring unknown argument to --enable-log-server: $enableval" >&5 +$as_echo "$as_me: WARNING: Ignoring unknown argument to --enable-log-server: $enableval" >&2;} + ;; + esac + +fi + + +# Check whether --enable-log-client was given. +if test "${enable_log_client+set}" = set; then : + enableval=$enable_log_client; case "$enableval" in + yes) + $as_echo "#define SUDOERS_IOLOG_CLIENT 1" >>confdefs.h + + ;; + no) + ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring unknown argument to --enable-log-client: $enableval" >&5 +$as_echo "$as_me: WARNING: Ignoring unknown argument to --enable-log-client: $enableval" >&2;} + ;; + esac + +else + $as_echo "#define SUDOERS_IOLOG_CLIENT 1" >>confdefs.h + +fi + + +if test X"$enable_log_server" = X"no" -a X"$enable_log_client" = X"no"; then + # No need for liblogsrv.la + LOGSRV= + LIBLOGSRV= +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 $as_echo_n "checking for library containing strerror... " >&6; } if ${ac_cv_search_strerror+:} false; then : @@ -30040,5 +30096,6 @@ fi + diff --git a/configure.ac b/configure.ac index da42e7700..286c990b6 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,9 @@ AC_SUBST([DIGEST]) AC_SUBST([devsearch]) AC_SUBST([SIGNAME]) AC_SUBST([PYTHON_PLUGIN_SRC]) +AC_SUBST([LOGSRV]) +AC_SUBST([LIBLOGSRV]) +AC_SUBST([LOGSRVD]) dnl dnl Variables that get substituted in docs (not overridden by environment) @@ -264,6 +267,9 @@ shadow_funcs= shadow_libs= TMPFILES_D= CONFIGURE_ARGS="$@" +LOGSRVD=logsrvd +LOGSRV=lib/logsrv +LIBLOGSRV='$(top_builddir)/lib/logsrv/liblogsrv.la' dnl dnl LD_PRELOAD equivalents @@ -1644,6 +1650,38 @@ AC_ARG_ENABLE(gss_krb5_ccache_name, AC_ARG_ENABLE(pvs-studio, [AS_HELP_STRING([--enable-pvs-studio], [Create a PVS-Studio.cfg file.])]) +AC_ARG_ENABLE(log-server, +[AS_HELP_STRING([--disable-log-server], [Disable building the sudo_logsrvd log server.])], +[ case "$enableval" in + yes) + ;; + no) + LOGSRVD= + ;; + *) AC_MSG_WARN([Ignoring unknown argument to --enable-log-server: $enableval]) + ;; + esac +]) + +AC_ARG_ENABLE(log-client, +[AS_HELP_STRING([--disable-log-client], [Disable sudoers support for using the sudo_logsrvd log server.])], +[ case "$enableval" in + yes) + AC_DEFINE([SUDOERS_IOLOG_CLIENT]) + ;; + no) + ;; + *) AC_MSG_WARN([Ignoring unknown argument to --enable-log-client: $enableval]) + ;; + esac +], [AC_DEFINE([SUDOERS_IOLOG_CLIENT])]) + +if test X"$enable_log_server" = X"no" -a X"$enable_log_client" = X"no"; then + # No need for liblogsrv.la + LOGSRV= + LIBLOGSRV= +fi + dnl dnl C compiler checks dnl @@ -4755,6 +4793,7 @@ AH_TEMPLATE(HAVE_KINFO_PROC_OPENBSD, [Define to 1 if your system has an OpenBSD- AH_TEMPLATE(HAVE_OPENSSL, [Define to 1 if you are using OpenSSL's TLS and sha2 functions.]) AH_TEMPLATE(HAVE_GCRYPT, [Define to 1 if you are using gcrypt's sha2 functions.]) AH_TEMPLATE(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION, [Define to 1 if you have the `SSL_CTX_set_min_proto_version' function or macro.]) +AH_TEMPLATE(SUDOERS_IOLOG_CLIENT, [Define to 1 to compile support for sudo_logsrvd in the sudoers I/O log plugin.]) dnl dnl Bits to copy verbatim into config.h.in diff --git a/lib/iolog/iolog_fileio.c b/lib/iolog/iolog_fileio.c index 62fb7c0c8..918375d94 100644 --- a/lib/iolog/iolog_fileio.c +++ b/lib/iolog/iolog_fileio.c @@ -542,6 +542,8 @@ iolog_mkpath(char *path) else ret = iolog_mkdirs(path); + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "iolog path %s", path); + debug_return_bool(ret); } diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 27e9caf48..5c3281780 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -58,7 +58,7 @@ INSTALL_BACKUP = @INSTALL_BACKUP@ # Libraries LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la LIBIOLOG = $(top_builddir)/lib/iolog/libsudo_iolog.la -LIBLOGSRV = $(top_builddir)/lib/logsrv/liblogsrv.la +LIBLOGSRV = @LIBLOGSRV@ LIBS = $(LIBUTIL) NET_LIBS = @NET_LIBS@ SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ @LIBTLS@ $(NET_LIBS) $(LIBIOLOG) $(LIBLOGSRV) diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 6f7a5315f..a7b3c39ac 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2009-2019 Todd C. Miller + * Copyright (c) 2009-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 @@ -57,16 +57,28 @@ static struct iolog_file iolog_files[] = { { true, }, /* IOFD_TIMING */ }; +static struct sudoers_io_operations { + int (*open)(struct timespec *now); + void (*close)(int exit_status, int error, const char **errstr); + int (*log)(int event, const char *buf, unsigned int len, + struct timespec *delay, const char **errstr); + int (*change_winsize)(unsigned int lines, unsigned int cols, + struct timespec *delay, const char **errstr); + int (*suspend)(const char *signame, struct timespec *delay, + const char **errstr); +} io_operations; + +#ifdef SUDOERS_IOLOG_CLIENT static struct client_closure client_closure = CLIENT_CLOSURE_INITIALIZER(client_closure); +#endif static struct iolog_details iolog_details; static bool warned = false; static struct timespec last_time; +static void sudoers_io_setops(void); /* sudoers_io is declared at the end of this file. */ extern __dso_public struct io_plugin sudoers_io; -#define iolog_remote (client_closure.sock != -1) - /* * Sudoers callback for maxseq Defaults setting. */ @@ -522,7 +534,7 @@ copy_vector_shallow(char * const *vec) } static int -sudoers_io_open_local(void) +sudoers_io_open_local(struct timespec *now) { char iolog_path[PATH_MAX], sessid[7]; size_t len; @@ -594,12 +606,12 @@ done: debug_return_int(ret); } +#ifdef SUDOERS_IOLOG_CLIENT static int -sudoers_io_open_remote(void) +sudoers_io_open_remote(struct timespec *now) { int sock, ret = -1; struct sudoers_string *connected_server = NULL; - debug_decl(sudoers_io_open_remote, SUDOERS_DEBUG_PLUGIN); /* Connect to log server. */ @@ -611,7 +623,7 @@ sudoers_io_open_remote(void) goto done; } - if (!client_closure_fill(&client_closure, sock, connected_server, + if (!client_closure_fill(&client_closure, sock, connected_server, now, &iolog_details, &sudoers_io)) { close(sock); goto done; @@ -622,8 +634,11 @@ sudoers_io_open_remote(void) ret = 1; done: + if (ret != 1) + client_closure_free(&client_closure); debug_return_int(ret); } +#endif /* SUDOERS_IOLOG_CLIENT */ static int sudoers_io_open(unsigned int version, sudo_conv_t conversation, @@ -686,14 +701,17 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, } } + if (sudo_gettime_awake(&last_time) == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, + "%s: unable to get time of day", __func__); + goto done; + } + /* * Create local I/O log file or connect to remote log server. */ - if (sudoers_io.event_alloc != NULL && iolog_details.log_servers != NULL) - ret = sudoers_io_open_remote(); - else - ret = sudoers_io_open_local(); - if (ret != true) + sudoers_io_setops(); + if ((ret = io_operations.open(&last_time)) != true) goto done; /* @@ -710,17 +728,8 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, if (!iolog_files[IOFD_TTYOUT].enabled) sudoers_io.log_ttyout = NULL; - if (sudo_gettime_awake(&last_time) == -1) { - sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, - "%s: unable to get time of day", __func__); - goto done; - } - if (iolog_remote) - client_closure.start_time = last_time; - done: if (ret != true) { - client_closure_free(&client_closure); sudo_freepwcache(); sudo_freegrcache(); } @@ -732,22 +741,40 @@ done: debug_return_int(ret); } +static void +sudoers_io_close_local(int exit_status, int error, const char **errstr) +{ + int i; + debug_decl(sudoers_io_close_local, SUDOERS_DEBUG_PLUGIN); + + for (i = 0; i < IOFD_MAX; i++) { + if (iolog_files[i].fd.v == NULL) + continue; + iolog_close(&iolog_files[i], errstr); + } + + debug_return; +} + +#ifdef SUDOERS_IOLOG_CLIENT +static void +sudoers_io_close_remote(int exit_status, int error, const char **errstr) +{ + debug_decl(sudoers_io_close_remote, SUDOERS_DEBUG_PLUGIN); + + client_close(&client_closure, exit_status, error); + + debug_return; +} +#endif + static void sudoers_io_close(int exit_status, int error) { const char *errstr = NULL; - int i; debug_decl(sudoers_io_close, SUDOERS_DEBUG_PLUGIN); - if (iolog_remote) { - client_close(&client_closure, exit_status, error); - } else { - for (i = 0; i < IOFD_MAX; i++) { - if (iolog_files[i].fd.v == NULL) - continue; - iolog_close(&iolog_files[i], &errstr); - } - } + io_operations.close(exit_status, error, &errstr); sudo_freepwcache(); sudo_freegrcache(); @@ -824,6 +851,7 @@ done: debug_return_int(ret); } +#ifdef SUDOERS_IOLOG_CLIENT /* * Schedule an I/O log entry to be written to the log server. * Returns 1 on success and -1 on error. @@ -872,6 +900,7 @@ sudoers_io_log_remote(int event, const char *buf, unsigned int len, done: debug_return_int(ret); } +#endif /* SUDOERS_IOLOG_CLIENT */ /* * Generic I/O logging function. Called by the I/O logging entry points. @@ -893,10 +922,7 @@ sudoers_io_log(const char *buf, unsigned int len, int event, const char **errstr } sudo_timespecsub(&now, &last_time, &delay); - if (iolog_remote) - ret = sudoers_io_log_remote(event, buf, len, &delay, &ioerror); - else - ret = sudoers_io_log_local(event, buf, len, &delay, &ioerror); + ret = io_operations.log(event, buf, len, &delay, &ioerror); last_time.tv_sec = now.tv_sec; last_time.tv_nsec = now.tv_nsec; @@ -983,6 +1009,7 @@ done: debug_return_int(ret); } +#ifdef SUDOERS_IOLOG_CLIENT static int sudoers_io_change_winsize_remote(unsigned int lines, unsigned int cols, struct timespec *delay, const char **errstr) @@ -1005,6 +1032,7 @@ sudoers_io_change_winsize_remote(unsigned int lines, unsigned int cols, debug_return_int(ret); } +#endif /* SUDOERS_IOLOG_CLIENT */ static int sudoers_io_change_winsize(unsigned int lines, unsigned int cols, const char **errstr) @@ -1022,10 +1050,7 @@ sudoers_io_change_winsize(unsigned int lines, unsigned int cols, const char **er } sudo_timespecsub(&now, &last_time, &delay); - if (iolog_remote) - ret = sudoers_io_change_winsize_remote(lines, cols, &delay, &ioerror); - else - ret = sudoers_io_change_winsize_local(lines, cols, &delay, &ioerror); + ret = io_operations.change_winsize(lines, cols, &delay, &ioerror); last_time.tv_sec = now.tv_sec; last_time.tv_nsec = now.tv_nsec; @@ -1082,6 +1107,7 @@ done: debug_return_int(ret); } +#ifdef SUDOERS_IOLOG_CLIENT static int sudoers_io_suspend_remote(const char *signame, struct timespec *delay, const char **errstr) @@ -1104,6 +1130,7 @@ sudoers_io_suspend_remote(const char *signame, struct timespec *delay, debug_return_int(ret); } +#endif /* SUDOERS_IOLOG_CLIENT */ static int sudoers_io_suspend(int signo, const char **errstr) @@ -1129,10 +1156,7 @@ sudoers_io_suspend(int signo, const char **errstr) sudo_timespecsub(&now, &last_time, &delay); /* Write suspend event to the timing file. */ - if (iolog_remote) - ret = sudoers_io_suspend_remote(signame, &delay, &ioerror); - else - ret = sudoers_io_suspend_local(signame, &delay, &ioerror); + ret = io_operations.suspend(signame, &delay, &ioerror); last_time.tv_sec = now.tv_sec; last_time.tv_nsec = now.tv_nsec; @@ -1162,6 +1186,34 @@ bad: debug_return_int(ret); } +/* + * Fill in the contents of io_operations, either local or remote. + */ +static void +sudoers_io_setops(void) +{ + debug_decl(sudoers_io_setops, SUDOERS_DEBUG_PLUGIN); + +#ifdef SUDOERS_IOLOG_CLIENT + if (sudoers_io.event_alloc != NULL && iolog_details.log_servers != NULL) { + io_operations.open = sudoers_io_open_remote; + io_operations.close = sudoers_io_close_remote; + io_operations.log = sudoers_io_log_remote; + io_operations.change_winsize = sudoers_io_change_winsize_remote; + io_operations.suspend = sudoers_io_suspend_remote; + } else +#endif /* SUDOERS_IOLOG_CLIENT */ + { + io_operations.open = sudoers_io_open_local; + io_operations.close = sudoers_io_close_local; + io_operations.log = sudoers_io_log_local; + io_operations.change_winsize = sudoers_io_change_winsize_local; + io_operations.suspend = sudoers_io_suspend_local; + } + + debug_return; +} + __dso_public struct io_plugin sudoers_io = { SUDO_IO_PLUGIN, SUDO_API_VERSION, diff --git a/plugins/sudoers/iolog_client.c b/plugins/sudoers/iolog_client.c index 3a4fe4e2e..8fd5633e8 100644 --- a/plugins/sudoers/iolog_client.c +++ b/plugins/sudoers/iolog_client.c @@ -16,6 +16,8 @@ #include "config.h" +#ifdef SUDOERS_IOLOG_CLIENT + #include #include #include @@ -1536,8 +1538,8 @@ bad: */ bool client_closure_fill(struct client_closure *closure, int sock, - const struct sudoers_string *host, struct iolog_details *details, - struct io_plugin *sudoers_io) + const struct sudoers_string *host, struct timespec *now, + struct iolog_details *details, struct io_plugin *sudoers_io) { union { struct sockaddr sa; @@ -1552,6 +1554,9 @@ client_closure_fill(struct client_closure *closure, int sock, closure->sock = -1; closure->state = RECV_HELLO; + closure->start_time.tv_sec = now->tv_sec; + closure->start_time.tv_nsec = now->tv_nsec; + closure->read_buf.size = 64 * 1024; closure->read_buf.data = malloc(closure->read_buf.size); if (closure->read_buf.data == NULL) @@ -1674,3 +1679,5 @@ done: client_closure_free(closure); debug_return_bool(ret); } + +#endif /* SUDOERS_IOLOG_CLIENT */ diff --git a/plugins/sudoers/iolog_plugin.h b/plugins/sudoers/iolog_plugin.h index fad09f65c..c092b0e9b 100644 --- a/plugins/sudoers/iolog_plugin.h +++ b/plugins/sudoers/iolog_plugin.h @@ -149,7 +149,7 @@ struct client_closure { #endif /* HAVE_OPENSSL */ /* iolog_client.c */ -bool client_closure_fill(struct client_closure *closure, int sock, const struct sudoers_string *host, struct iolog_details *details, struct io_plugin *sudoers_io); +bool client_closure_fill(struct client_closure *closure, int sock, const struct sudoers_string *host, struct timespec *now, struct iolog_details *details, struct io_plugin *sudoers_io); bool client_close(struct client_closure *closure, int exit_status, int error); bool fmt_accept_message(struct client_closure *closure); bool fmt_client_message(struct client_closure *closure, ClientMessage *msg); diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 053591328..be33998e5 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -117,6 +117,12 @@ static struct rlimit nproclimit; int NewArgc; char **NewArgv; +#ifdef SUDOERS_IOLOG_CLIENT +# define remote_iologs (!SLIST_EMPTY(&def_log_servers)) +#else +# define remote_iologs 0 +#endif + /* * Unlimit the number of processes since Linux's setuid() will * apply resource limits when changing uid and return EAGAIN if @@ -541,7 +547,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], } } - if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && SLIST_EMPTY(&def_log_servers)) { + if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && !remote_iologs) { if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) { if ((iolog_path = format_iolog_path()) == NULL) { if (!def_ignore_iolog_errors)