Add basic support for reject and error audit events to sudoers.
This is only used when logging events from plugins other than sudoers, such as an approval plugin. With this change, if an approval plugin rejects the command the denial will be logged in the sudoers log file using the message from the approval plugin.
This commit is contained in:
@@ -66,44 +66,59 @@ audit_success(char *const argv[])
|
||||
debug_return_int(rc);
|
||||
}
|
||||
|
||||
static int
|
||||
audit_failure_int(char *const argv[], const char *message)
|
||||
{
|
||||
int ret = 0;
|
||||
debug_decl(audit_failure_int, SUDOERS_DEBUG_AUDIT);
|
||||
|
||||
#if defined(HAVE_BSM_AUDIT) || defined(HAVE_LINUX_AUDIT)
|
||||
if (def_log_denied && argv != NULL) {
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
if (bsm_audit_failure(argv, message) == -1)
|
||||
ret = -1;
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_AUDIT
|
||||
if (linux_audit_command(argv, 0) == -1)
|
||||
ret = -1;
|
||||
#endif
|
||||
#ifdef HAVE_SOLARIS_AUDIT
|
||||
if (solaris_audit_failure(argv, message) == -1)
|
||||
ret = -1;
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_BSM_AUDIT || HAVE_LINUX_AUDIT */
|
||||
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
int
|
||||
audit_failure(char *const argv[], char const *const fmt, ...)
|
||||
{
|
||||
int oldlocale, rc = 0;
|
||||
int oldlocale, ret;
|
||||
char *message;
|
||||
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;
|
||||
if ((ret = vasprintf(&message, _(fmt), ap)) == -1)
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
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
|
||||
if (ret != -1) {
|
||||
/* Set audit_msg for audit plugins. */
|
||||
free(audit_msg);
|
||||
audit_msg = message;
|
||||
|
||||
ret = audit_failure_int(argv, audit_msg);
|
||||
}
|
||||
#endif /* HAVE_BSM_AUDIT || HAVE_LINUX_AUDIT */
|
||||
|
||||
sudoers_setlocale(oldlocale, NULL);
|
||||
|
||||
debug_return_int(rc);
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -154,21 +169,97 @@ 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)
|
||||
{
|
||||
int ret = true;
|
||||
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);
|
||||
debug_return_int(true);
|
||||
|
||||
if (!def_log_allowed)
|
||||
debug_return_bool(true);
|
||||
if (def_log_allowed) {
|
||||
if (audit_success(run_argv) != 0 && !def_ignore_audit_errors)
|
||||
ret = false;
|
||||
|
||||
if (audit_success(run_argv) != 0 && !def_ignore_audit_errors)
|
||||
debug_return_bool(false);
|
||||
if (!log_allowed(VALIDATE_SUCCESS) && !def_ignore_logfile_errors)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (!log_allowed(VALIDATE_SUCCESS) && !def_ignore_logfile_errors)
|
||||
debug_return_bool(false);
|
||||
debug_return_bool(true);
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
sudoers_audit_reject(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *message, char * const command_info[], const char **errstr)
|
||||
{
|
||||
int ret = true;
|
||||
char *logline;
|
||||
debug_decl(sudoers_audit_reject, SUDOERS_DEBUG_PLUGIN);
|
||||
|
||||
/* Skip reject events that sudoers generated itself. */
|
||||
if (strncmp(plugin_name, "sudoers_", 8) == 0)
|
||||
debug_return_int(true);
|
||||
|
||||
if (!def_log_denied)
|
||||
debug_return_int(true);
|
||||
|
||||
if (audit_failure_int(NewArgv, message) != 0) {
|
||||
if (!def_ignore_audit_errors)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
logline = new_logline(message, NULL);
|
||||
if (logline == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
if (def_syslog) {
|
||||
if (!do_syslog(def_syslog_badpri, logline)) {
|
||||
if (!def_ignore_logfile_errors)
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (def_logfile) {
|
||||
if (!do_logfile(logline)) {
|
||||
if (!def_ignore_logfile_errors)
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
free(logline);
|
||||
|
||||
done:
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
sudoers_audit_error(const char *plugin_name, unsigned int plugin_type,
|
||||
const char *message, char * const command_info[], const char **errstr)
|
||||
{
|
||||
int ret = true;
|
||||
debug_decl(sudoers_audit_error, SUDOERS_DEBUG_PLUGIN);
|
||||
|
||||
/* Skip error events that sudoers generated itself. */
|
||||
if (strncmp(plugin_name, "sudoers_", 8) == 0)
|
||||
debug_return_int(true);
|
||||
|
||||
if (audit_failure_int(NewArgv, message) != 0) {
|
||||
if (!def_ignore_audit_errors)
|
||||
ret = false;
|
||||
}
|
||||
if (def_syslog) {
|
||||
if (!do_syslog(def_syslog_badpri, message)) {
|
||||
if (!def_ignore_logfile_errors)
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (def_logfile) {
|
||||
if (!do_logfile(message)) {
|
||||
if (!def_ignore_logfile_errors)
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -188,8 +279,8 @@ __dso_public struct audit_plugin sudoers_audit = {
|
||||
sudoers_audit_open,
|
||||
NULL, /* audit_close */
|
||||
sudoers_audit_accept,
|
||||
NULL, /* audit_reject */
|
||||
NULL, /* audit_error */
|
||||
sudoers_audit_reject,
|
||||
sudoers_audit_error,
|
||||
sudoers_audit_version,
|
||||
NULL, /* register_hooks */
|
||||
NULL /* deregister_hooks */
|
||||
|
@@ -58,12 +58,9 @@
|
||||
/* Special message for log_warning() so we know to use ngettext() */
|
||||
#define INCORRECT_PASSWORD_ATTEMPT ((char *)0x01)
|
||||
|
||||
static void do_syslog(int, char *);
|
||||
static bool do_logfile(const char *);
|
||||
static bool send_mail(const char *fmt, ...);
|
||||
static bool should_mail(int);
|
||||
static void mysyslog(int, const char *, ...);
|
||||
static char *new_logline(const char *, const char *);
|
||||
|
||||
/*
|
||||
* We do an openlog(3)/closelog(3) for each message because some
|
||||
@@ -89,18 +86,23 @@ mysyslog(int pri, const char *fmt, ...)
|
||||
* Log a message to syslog, pre-pending the username and splitting the
|
||||
* message into parts if it is longer than syslog_maxlen.
|
||||
*/
|
||||
static void
|
||||
do_syslog(int pri, char *msg)
|
||||
bool
|
||||
do_syslog(int pri, const char *msg)
|
||||
{
|
||||
size_t len, maxlen;
|
||||
char *p, *tmp, save;
|
||||
size_t maxlen;
|
||||
char *copy, *cp, *ep;
|
||||
const char *fmt;
|
||||
int oldlocale;
|
||||
debug_decl(do_syslog, SUDOERS_DEBUG_LOGGING);
|
||||
|
||||
/* A priority of -1 corresponds to "none". */
|
||||
if (pri == -1)
|
||||
debug_return;
|
||||
debug_return_bool(true);
|
||||
|
||||
if ((copy = strdup(msg)) == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
|
||||
|
||||
@@ -109,42 +111,40 @@ do_syslog(int pri, char *msg)
|
||||
*/
|
||||
fmt = _("%8s : %s");
|
||||
maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
|
||||
for (p = msg; *p != '\0'; ) {
|
||||
len = strlen(p);
|
||||
for (cp = copy; *cp != '\0'; ) {
|
||||
size_t len = strlen(cp);
|
||||
if (len > maxlen) {
|
||||
/*
|
||||
* Break up the line into what will fit on one syslog(3) line
|
||||
* Try to avoid breaking words into several lines if possible.
|
||||
*/
|
||||
tmp = memrchr(p, ' ', maxlen);
|
||||
if (tmp == NULL)
|
||||
tmp = p + maxlen;
|
||||
ep = memrchr(cp, ' ', maxlen);
|
||||
if (ep != NULL)
|
||||
*ep++ = '\0';
|
||||
else
|
||||
ep = cp + maxlen;
|
||||
|
||||
/* NULL terminate line, but save the char to restore later */
|
||||
save = *tmp;
|
||||
*tmp = '\0';
|
||||
mysyslog(pri, fmt, user_name, cp);
|
||||
|
||||
mysyslog(pri, fmt, user_name, p);
|
||||
|
||||
*tmp = save; /* restore saved character */
|
||||
|
||||
/* Advance p and eliminate leading whitespace */
|
||||
for (p = tmp; *p == ' '; p++)
|
||||
/* Advance cp and eliminate leading whitespace */
|
||||
for (cp = ep; *cp == ' '; cp++)
|
||||
continue;
|
||||
} else {
|
||||
mysyslog(pri, fmt, user_name, p);
|
||||
p += len;
|
||||
mysyslog(pri, fmt, user_name, cp);
|
||||
cp += len;
|
||||
}
|
||||
fmt = _("%8s : (command continued) %s");
|
||||
maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
|
||||
}
|
||||
|
||||
free(copy);
|
||||
|
||||
sudoers_setlocale(oldlocale, NULL);
|
||||
|
||||
debug_return;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
do_logfile(const char *msg)
|
||||
{
|
||||
static bool warned = false;
|
||||
@@ -263,8 +263,8 @@ log_denial(int status, bool inform_user)
|
||||
|
||||
/* Log via syslog and/or a file. */
|
||||
if (def_log_denied) {
|
||||
if (def_syslog)
|
||||
do_syslog(def_syslog_badpri, logline);
|
||||
if (def_syslog && !do_syslog(def_syslog_badpri, logline))
|
||||
ret = false;
|
||||
if (def_logfile && !do_logfile(logline))
|
||||
ret = false;
|
||||
}
|
||||
@@ -414,8 +414,8 @@ log_allowed(int status)
|
||||
* Log via syslog and/or a file.
|
||||
*/
|
||||
if (def_log_allowed) {
|
||||
if (def_syslog)
|
||||
do_syslog(def_syslog_goodpri, logline);
|
||||
if (def_syslog && !do_syslog(def_syslog_goodpri, logline))
|
||||
ret = false;
|
||||
if (def_logfile && !do_logfile(logline))
|
||||
ret = false;
|
||||
}
|
||||
@@ -561,8 +561,8 @@ vlog_warning(int flags, int errnum, const char *fmt, va_list ap)
|
||||
* Log to syslog and/or a file.
|
||||
*/
|
||||
if (!ISSET(flags, SLOG_NO_LOG)) {
|
||||
if (def_syslog)
|
||||
do_syslog(def_syslog_badpri, logline);
|
||||
if (def_syslog && !do_syslog(def_syslog_badpri, logline))
|
||||
ret = false;
|
||||
if (def_logfile && !do_logfile(logline))
|
||||
ret = false;
|
||||
}
|
||||
@@ -942,7 +942,7 @@ should_mail(int status)
|
||||
/*
|
||||
* Allocate and fill in a new logline.
|
||||
*/
|
||||
static char *
|
||||
char *
|
||||
new_logline(const char *message, const char *errstr)
|
||||
{
|
||||
char *line = NULL, *evstr = NULL;
|
||||
|
@@ -67,6 +67,9 @@ extern char *audit_msg;
|
||||
|
||||
union sudo_defs_val;
|
||||
|
||||
bool do_logfile(const char *msg);
|
||||
bool do_syslog(int pri, const char *msg);
|
||||
char *new_logline(const char *, const char *);
|
||||
bool sudoers_warn_setlocale(bool restore, int *cookie);
|
||||
bool sudoers_setlocale(int newlocale, int *prevlocale);
|
||||
int sudoers_getlocale(void);
|
||||
|
Reference in New Issue
Block a user