diff --git a/plugins/sudoers/audit.c b/plugins/sudoers/audit.c index c3bfbd37e..78855aadf 100644 --- a/plugins/sudoers/audit.c +++ b/plugins/sudoers/audit.c @@ -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 */ diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 0cb9f010a..88e3cd3d2 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -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; diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index 4c09bc9be..71aaa0bb9 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/logging.h @@ -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);