Files
sudo/plugins/sudoers/audit.c
Todd C. Miller b519481912 Defer logging of the successful command until approval plugins have run.
This adds audit plugin support to the sudoers module, currently
only used for accept events.  As a result, the sudoers file is now
initially parsed as an audit plugin.
2020-06-02 09:07:46 -06:00

197 lines
5.3 KiB
C

/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-2015, 2019-2020 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sudoers.h"
#ifdef HAVE_BSM_AUDIT
# include "bsm_audit.h"
#endif
#ifdef HAVE_LINUX_AUDIT
# include "linux_audit.h"
#endif
#ifdef HAVE_SOLARIS_AUDIT
# include "solaris_audit.h"
#endif
char *audit_msg = NULL;
static int
audit_success(char *const argv[])
{
int rc = 0;
debug_decl(audit_success, SUDOERS_DEBUG_AUDIT);
if (argv != NULL) {
#ifdef HAVE_BSM_AUDIT
if (bsm_audit_success(argv) == -1)
rc = -1;
#endif
#ifdef HAVE_LINUX_AUDIT
if (linux_audit_command(argv, 1) == -1)
rc = -1;
#endif
#ifdef HAVE_SOLARIS_AUDIT
if (solaris_audit_success(argv) == -1)
rc = -1;
#endif
}
debug_return_int(rc);
}
int
audit_failure(char *const argv[], char const *const fmt, ...)
{
int oldlocale, rc = 0;
va_list ap;
debug_decl(audit_failure, SUDOERS_DEBUG_AUDIT);
/* Audit messages should be in the sudoers locale. */
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
/* Set audit_msg for audit plugin. */
free(audit_msg);
audit_msg = NULL;
va_start(ap, fmt);
if (vasprintf(&audit_msg, _(fmt), ap) == -1)
rc = -1;
va_end(ap);
#if defined(HAVE_BSM_AUDIT) || defined(HAVE_LINUX_AUDIT)
if (def_log_denied && argv != NULL) {
#ifdef HAVE_BSM_AUDIT
if (bsm_audit_failure(argv, audit_msg) == -1)
rc = -1;
#endif
#ifdef HAVE_LINUX_AUDIT
if (linux_audit_command(argv, 0) == -1)
rc = -1;
#endif
#ifdef HAVE_SOLARIS_AUDIT
if (solaris_audit_failure(argv, audit_msg) == -1)
rc = -1;
#endif
}
#endif /* HAVE_BSM_AUDIT || HAVE_LINUX_AUDIT */
sudoers_setlocale(oldlocale, NULL);
debug_return_int(rc);
}
static int
sudoers_audit_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], int submit_optind, char * const submit_argv[],
char * const submit_envp[], char * const plugin_options[],
const char **errstr)
{
struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
struct sudoers_open_info info;
const char *cp, *plugin_path = NULL;
char * const *cur;
int ret;
debug_decl(sudoers_audit_open, SUDOERS_DEBUG_PLUGIN);
/* Initialize the debug subsystem. */
for (cur = settings; (cp = *cur) != NULL; cur++) {
if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
cp += sizeof("debug_flags=") - 1;
if (!sudoers_debug_parse_flags(&debug_files, cp))
debug_return_int(-1);
continue;
}
if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
plugin_path = cp + sizeof("plugin_path=") - 1;
continue;
}
}
if (!sudoers_debug_register(plugin_path, &debug_files))
debug_return_int(-1);
/* Call the sudoers init function. */
info.settings = settings;
info.user_info = user_info;
info.plugin_args = plugin_options;
ret = sudoers_init(&info, submit_envp);
/* The audit functions set audit_msg on failure. */
if (ret != 1 && audit_msg != NULL)
*errstr = audit_msg;
debug_return_int(ret);
}
static int
sudoers_audit_accept(const char *plugin_name, unsigned int plugin_type,
char * const command_info[], char * const run_argv[],
char * const run_envp[], const char **errstr)
{
debug_decl(sudoers_audit_accept, SUDOERS_DEBUG_PLUGIN);
/* Only log the accept event from the sudo front-end */
if (plugin_type != SUDO_FRONT_END)
debug_return_bool(true);
if (!def_log_allowed)
debug_return_bool(true);
if (audit_success(run_argv) != 0 && !def_ignore_audit_errors)
debug_return_bool(false);
if (!log_allowed(VALIDATE_SUCCESS) && !def_ignore_logfile_errors)
debug_return_bool(false);
debug_return_bool(true);
}
static int
sudoers_audit_version(int verbose)
{
debug_decl(sudoers_audit_version, SUDOERS_DEBUG_PLUGIN);
sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers audit plugin version %s\n",
PACKAGE_VERSION);
debug_return_int(true);
}
__dso_public struct audit_plugin sudoers_audit = {
SUDO_AUDIT_PLUGIN,
SUDO_API_VERSION,
sudoers_audit_open,
NULL, /* audit_close */
sudoers_audit_accept,
NULL, /* audit_reject */
NULL, /* audit_error */
sudoers_audit_version,
NULL, /* register_hooks */
NULL /* deregister_hooks */
};