diff options
Diffstat (limited to '')
-rw-r--r-- | plugins/sudoers/logging.c | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c new file mode 100644 index 0000000..776f881 --- /dev/null +++ b/plugins/sudoers/logging.c @@ -0,0 +1,821 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1994-1996, 1998-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. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* + * 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 + */ + +#ifdef __TANDEM +# include <floss.h> +#endif + +#include <config.h> + +#include <sys/stat.h> +#include <sys/wait.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_NL_LANGINFO +# include <langinfo.h> +#endif /* HAVE_NL_LANGINFO */ +#include <netdb.h> +#include <pwd.h> +#include <grp.h> +#include <time.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <syslog.h> +#ifndef HAVE_GETADDRINFO +# include "compat/getaddrinfo.h" +#endif + +#include "sudoers.h" +#include "log_client.h" + +static bool should_mail(int); +static bool warned = false; + +extern struct policy_plugin sudoers_policy; /* XXX */ + +#ifdef SUDOERS_LOG_CLIENT +/* + * Convert a defaults-style list to a stringlist. + */ +static struct sudoers_str_list * +list_to_strlist(struct list_members *list) +{ + struct sudoers_str_list *strlist; + struct sudoers_string *str; + struct list_member *item; + debug_decl(slist_to_strlist, SUDOERS_DEBUG_LOGGING); + + if ((strlist = str_list_alloc()) == NULL) + goto oom; + + SLIST_FOREACH(item, list, entries) { + if ((str = sudoers_string_alloc(item->value)) == NULL) + goto oom; + /* List is in reverse order, insert at head to fix that. */ + STAILQ_INSERT_HEAD(strlist, str, entries); + } + + debug_return_ptr(strlist); +oom: + str_list_free(strlist); + debug_return_ptr(NULL); +} + +bool +init_log_details(struct log_details *details, struct eventlog *evlog) +{ + struct sudoers_str_list *log_servers = NULL; + debug_decl(init_log_details, SUDOERS_DEBUG_LOGGING); + + memset(details, 0, sizeof(*details)); + + if ((log_servers = list_to_strlist(&def_log_servers)) == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_bool(false); + } + + details->evlog = evlog; + details->ignore_log_errors = def_ignore_logfile_errors; + details->log_servers = log_servers; + details->server_timeout.tv_sec = def_log_server_timeout; + details->keepalive = def_log_server_keepalive; +#if defined(HAVE_OPENSSL) + details->ca_bundle = def_log_server_cabundle; + details->cert_file = def_log_server_peer_cert; + details->key_file = def_log_server_peer_key; + details->verify_server = def_log_server_verify; +#endif /* HAVE_OPENSSL */ + + debug_return_bool(true); +} + +bool +log_server_reject(struct eventlog *evlog, const char *message, + struct sudo_plugin_event * (*event_alloc)(void)) +{ + struct client_closure *client_closure; + struct log_details details; + bool ret = false; + debug_decl(log_server_reject, SUDOERS_DEBUG_LOGGING); + + if (SLIST_EMPTY(&def_log_servers)) + debug_return_bool(true); + + if (!init_log_details(&details, evlog)) + debug_return_bool(false); + + /* Open connection to log server, send hello and reject messages. */ + client_closure = log_server_open(&details, &sudo_user.submit_time, false, + SEND_REJECT, message, event_alloc); + if (client_closure != NULL) { + client_closure_free(client_closure); + ret = true; + } + + /* Only the log_servers string list is dynamically allocated. */ + str_list_free(details.log_servers); + debug_return_bool(ret); +} + +bool +log_server_alert(struct eventlog *evlog, struct timespec *now, + const char *message, const char *errstr, + struct sudo_plugin_event * (*event_alloc)(void)) +{ + struct client_closure *client_closure; + struct log_details details; + char *emessage = NULL; + bool ret = false; + debug_decl(log_server_alert, SUDOERS_DEBUG_LOGGING); + + if (SLIST_EMPTY(&def_log_servers)) + debug_return_bool(true); + + if (!init_log_details(&details, evlog)) + goto done; + + if (errstr != NULL) { + if (asprintf(&emessage, _("%s: %s"), message, errstr) == -1) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + goto done; + } + } + + /* Open connection to log server, send hello and alert messages. */ + client_closure = log_server_open(&details, now, false, + SEND_ALERT, emessage ? emessage : message, event_alloc); + if (client_closure != NULL) { + client_closure_free(client_closure); + ret = true; + } + +done: + /* Only the log_servers string list is dynamically allocated. */ + free(emessage); + str_list_free(details.log_servers); + debug_return_bool(ret); +} +#else +bool +log_server_reject(struct eventlog *evlog, const char *message, + struct sudo_plugin_event * (*event_alloc)(void)) +{ + return true; +} + +bool +log_server_alert(struct eventlog *evlog, struct timespec *now, + const char *message, const char *errstr, + struct sudo_plugin_event * (*event_alloc)(void)) +{ + return true; +} +#endif /* SUDOERS_LOG_CLIENT */ + +/* + * Log a reject event to syslog, a log file, sudo_logsrvd and/or email. + */ +static bool +log_reject(const char *message, bool logit, bool mailit) +{ + int evl_flags = 0; + struct eventlog evlog; + bool ret = true; + debug_decl(log_reject, SUDOERS_DEBUG_LOGGING); + + if (mailit) { + SET(evl_flags, EVLOG_MAIL); + if (!logit) + SET(evl_flags, EVLOG_MAIL_ONLY); + } + sudoers_to_eventlog(&evlog, NewArgv, env_get()); + if (!eventlog_reject(&evlog, evl_flags, message, NULL, NULL)) + ret = false; + + if (!log_server_reject(&evlog, message, sudoers_policy.event_alloc)) + ret = false; + + debug_return_bool(ret); +} + +/* + * Log, audit and mail the denial message, optionally informing the user. + */ +bool +log_denial(int status, bool inform_user) +{ + const char *message; + int oldlocale; + bool mailit, ret = true; + debug_decl(log_denial, SUDOERS_DEBUG_LOGGING); + + /* Send mail based on status. */ + mailit = should_mail(status); + + /* Set error message. */ + if (ISSET(status, FLAG_NO_USER)) + message = N_("user NOT in sudoers"); + else if (ISSET(status, FLAG_NO_HOST)) + message = N_("user NOT authorized on host"); + else + message = N_("command not allowed"); + + /* Do auditing first (audit_failure() handles the locale itself). */ + audit_failure(NewArgv, "%s", message); + + if (def_log_denied || mailit) { + /* Log and mail messages should be in the sudoers locale. */ + sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); + + if (!log_reject(message, def_log_denied, mailit)) + ret = false; + + /* Restore locale. */ + sudoers_setlocale(oldlocale, NULL); + } + + /* Inform the user of the failure (in their locale). */ + if (inform_user) { + sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale); + + if (ISSET(status, FLAG_NO_USER)) { + sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not in the sudoers " + "file. This incident will be reported.\n"), user_name); + } else if (ISSET(status, FLAG_NO_HOST)) { + sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not allowed to run sudo " + "on %s. This incident will be reported.\n"), + user_name, user_srunhost); + } else if (ISSET(status, FLAG_NO_CHECK)) { + sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s may not run " + "sudo on %s.\n"), user_name, user_srunhost); + } else { + sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s is not allowed " + "to execute '%s%s%s' as %s%s%s on %s.\n"), + user_name, user_cmnd, user_args ? " " : "", + user_args ? user_args : "", + list_pw ? list_pw->pw_name : runas_pw ? + runas_pw->pw_name : user_name, runas_gr ? ":" : "", + runas_gr ? runas_gr->gr_name : "", user_host); + } + sudoers_setlocale(oldlocale, NULL); + } + debug_return_bool(ret); +} + +/* + * Log and audit that user was not allowed to run the command. + */ +bool +log_failure(int status, int flags) +{ + bool ret, inform_user = true; + debug_decl(log_failure, SUDOERS_DEBUG_LOGGING); + + /* The user doesn't always get to see the log message (path info). */ + if (!ISSET(status, FLAG_NO_USER | FLAG_NO_HOST) && def_path_info && + (flags == NOT_FOUND_DOT || flags == NOT_FOUND)) + inform_user = false; + ret = log_denial(status, inform_user); + + if (!inform_user) { + /* + * We'd like to not leak path info at all here, but that can + * *really* confuse the users. To really close the leak we'd + * have to say "not allowed to run foo" even when the problem + * is just "no foo in path" since the user can trivially set + * their path to just contain a single dir. + */ + if (flags == NOT_FOUND) + sudo_warnx(U_("%s: command not found"), user_cmnd); + else if (flags == NOT_FOUND_DOT) + sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), user_cmnd, user_cmnd, user_cmnd); + } + + debug_return_bool(ret); +} + +/* + * Format an authentication failure message, using either + * authfail_message from sudoers or a locale-specific message. + */ +static int +fmt_authfail_message(char **str, unsigned int tries) +{ + char *src, *dst0, *dst, *dst_end; + size_t size; + int len; + debug_decl(fmt_authfail_message, SUDOERS_DEBUG_LOGGING); + + if (def_authfail_message == NULL) { + debug_return_int(asprintf(str, ngettext("%u incorrect password attempt", + "%u incorrect password attempts", tries), tries)); + } + + src = def_authfail_message; + size = strlen(src) + 33; + if ((dst0 = dst = malloc(size)) == NULL) + debug_return_int(-1); + dst_end = dst + size; + + /* Always leave space for the terminating NUL. */ + while (*src != '\0' && dst + 1 < dst_end) { + if (src[0] == '%') { + switch (src[1]) { + case '%': + src++; + break; + case 'd': + len = snprintf(dst, dst_end - dst, "%u", tries); + if (len < 0 || len >= (int)(dst_end - dst)) + goto done; + dst += len; + src += 2; + continue; + default: + break; + } + } + *dst++ = *src++; + } +done: + *dst = '\0'; + + *str = dst0; +#ifdef __clang_analyzer__ + /* clang analyzer false positive */ + if (__builtin_expect(dst < dst0, 0)) + __builtin_trap(); +#endif + debug_return_int(dst - dst0); +} + +/* + * Log and audit that user was not able to authenticate themselves. + */ +bool +log_auth_failure(int status, unsigned int tries) +{ + char *message = NULL; + int oldlocale; + bool ret = true; + bool mailit = false; + bool logit = true; + debug_decl(log_auth_failure, SUDOERS_DEBUG_LOGGING); + + /* Do auditing first (audit_failure() handles the locale itself). */ + audit_failure(NewArgv, "%s", N_("authentication failure")); + + /* If sudoers denied the command we'll log that separately. */ + if (!ISSET(status, FLAG_BAD_PASSWORD|FLAG_NON_INTERACTIVE)) + logit = false; + + /* + * Do we need to send mail? + * We want to avoid sending multiple messages for the same command + * so if we are going to send an email about the denial, that takes + * precedence. + */ + if (ISSET(status, VALIDATE_SUCCESS)) { + /* Command allowed, auth failed; do we need to send mail? */ + if (def_mail_badpass || def_mail_always) + mailit = true; + if (!def_log_denied) + logit = false; + } else { + /* Command denied, auth failed; make sure we don't send mail twice. */ + if (def_mail_badpass && !should_mail(status)) + mailit = true; + /* Don't log the bad password message, we'll log a denial instead. */ + logit = false; + } + + if (logit || mailit) { + /* Log and mail messages should be in the sudoers locale. */ + sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); + + if (ISSET(status, FLAG_BAD_PASSWORD)) { + if (fmt_authfail_message(&message, tries) == -1) { + sudo_warnx(U_("%s: %s"), __func__, + U_("unable to allocate memory")); + ret = false; + } else { + ret = log_reject(message, logit, mailit); + free(message); + } + } else { + ret = log_reject(_("a password is required"), logit, mailit); + } + + /* Restore locale. */ + sudoers_setlocale(oldlocale, NULL); + } + + /* Inform the user if they failed to authenticate (in their locale). */ + sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale); + + if (ISSET(status, FLAG_BAD_PASSWORD)) { + if (fmt_authfail_message(&message, tries) == -1) { + sudo_warnx(U_("%s: %s"), __func__, + U_("unable to allocate memory")); + ret = false; + } else { + sudo_warnx("%s", message); + free(message); + } + } else { + sudo_warnx("%s", _("a password is required")); + } + + sudoers_setlocale(oldlocale, NULL); + + debug_return_bool(ret); +} + +/* + * Log and potentially mail the allowed command. + */ +bool +log_allowed(void) +{ + struct eventlog evlog; + int oldlocale; + int evl_flags = 0; + bool mailit, ret = true; + debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING); + + /* Send mail based on status. */ + mailit = should_mail(VALIDATE_SUCCESS); + + if (def_log_allowed || mailit) { + /* Log and mail messages should be in the sudoers locale. */ + sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); + + sudoers_to_eventlog(&evlog, NewArgv, env_get()); + if (mailit) { + SET(evl_flags, EVLOG_MAIL); + if (!def_log_allowed) + SET(evl_flags, EVLOG_MAIL_ONLY); + } + if (!eventlog_accept(&evlog, evl_flags, NULL, NULL)) + ret = false; + + sudoers_setlocale(oldlocale, NULL); + } + + debug_return_bool(ret); +} + +/* + * Perform logging for log_warning()/log_warningx(). + */ +static bool +vlog_warning(int flags, int errnum, const char *fmt, va_list ap) +{ + struct eventlog evlog; + struct timespec now; + const char *errstr = NULL; + char *message; + bool ret = true; + int len, oldlocale; + int evl_flags = 0; + va_list ap2; + debug_decl(vlog_warning, SUDOERS_DEBUG_LOGGING); + + /* Do auditing first (audit_failure() handles the locale itself). */ + if (ISSET(flags, SLOG_AUDIT)) { + va_copy(ap2, ap); + vaudit_failure(NewArgv, fmt, ap2); + va_end(ap2); + } + + /* Need extra copy of ap for sudo_vwarn()/sudo_vwarnx() below. */ + va_copy(ap2, ap); + + /* Log messages should be in the sudoers locale. */ + sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); + + /* Expand printf-style format + args. */ + len = vasprintf(&message, _(fmt), ap); + if (len == -1) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + ret = false; + goto done; + } + + if (ISSET(flags, SLOG_USE_ERRNO)) + errstr = strerror(errnum); + else if (ISSET(flags, SLOG_GAI_ERRNO)) + errstr = gai_strerror(errnum); + + /* Log to debug file. */ + if (errstr != NULL) { + sudo_debug_printf2(NULL, NULL, 0, + SUDO_DEBUG_WARN|sudo_debug_subsys, "%s: %s", message, errstr); + } else { + sudo_debug_printf2(NULL, NULL, 0, + SUDO_DEBUG_WARN|sudo_debug_subsys, "%s", message); + } + + if (ISSET(flags, SLOG_SEND_MAIL) || !ISSET(flags, SLOG_NO_LOG)) { + if (sudo_gettime_real(&now) == -1) { + sudo_warn("%s", U_("unable to get time of day")); + goto done; + } + if (ISSET(flags, SLOG_RAW_MSG)) + SET(evl_flags, EVLOG_RAW); + if (ISSET(flags, SLOG_SEND_MAIL)) { + SET(evl_flags, EVLOG_MAIL); + if (ISSET(flags, SLOG_NO_LOG)) + SET(evl_flags, EVLOG_MAIL_ONLY); + } + sudoers_to_eventlog(&evlog, NewArgv, env_get()); + eventlog_alert(&evlog, evl_flags, &now, message, errstr); + + log_server_alert(&evlog, &now, message, errstr, + sudoers_policy.event_alloc); + } + + /* + * Tell the user (in their locale). + */ + if (!ISSET(flags, SLOG_NO_STDERR)) { + sudoers_setlocale(SUDOERS_LOCALE_USER, NULL); + if (ISSET(flags, SLOG_USE_ERRNO)) { + errno = errnum; + sudo_vwarn_nodebug(_(fmt), ap2); + } else if (ISSET(flags, SLOG_GAI_ERRNO)) { + sudo_gai_vwarn_nodebug(errnum, _(fmt), ap2); + } else { + sudo_vwarnx_nodebug(_(fmt), ap2); + } + } + +done: + va_end(ap2); + sudoers_setlocale(oldlocale, NULL); + + debug_return_bool(ret); +} + +bool +log_warning(int flags, const char *fmt, ...) +{ + va_list ap; + bool ret; + debug_decl(log_warning, SUDOERS_DEBUG_LOGGING); + + /* Log the error. */ + va_start(ap, fmt); + ret = vlog_warning(flags|SLOG_USE_ERRNO, errno, fmt, ap); + va_end(ap); + + debug_return_bool(ret); +} + +bool +log_warningx(int flags, const char *fmt, ...) +{ + va_list ap; + bool ret; + debug_decl(log_warningx, SUDOERS_DEBUG_LOGGING); + + /* Log the error. */ + va_start(ap, fmt); + ret = vlog_warning(flags, 0, fmt, ap); + va_end(ap); + + debug_return_bool(ret); +} + +bool +gai_log_warning(int flags, int errnum, const char *fmt, ...) +{ + va_list ap; + bool ret; + debug_decl(gai_log_warning, SUDOERS_DEBUG_LOGGING); + + /* Log the error. */ + va_start(ap, fmt); + ret = vlog_warning(flags|SLOG_GAI_ERRNO, errnum, fmt, ap); + va_end(ap); + + debug_return_bool(ret); +} + +/* + * Determine whether we should send mail based on "status" and defaults options. + */ +static bool +should_mail(int status) +{ + debug_decl(should_mail, SUDOERS_DEBUG_LOGGING); + + debug_return_bool(def_mail_always || ISSET(status, VALIDATE_ERROR) || + (def_mail_all_cmnds && ISSET(sudo_mode, (MODE_RUN|MODE_EDIT))) || + (def_mail_no_user && ISSET(status, FLAG_NO_USER)) || + (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) || + (def_mail_no_perms && !ISSET(status, VALIDATE_SUCCESS))); +} + +/* + * Build a struct eventlog from sudoers data. + * The values in the resulting eventlog struct should not be freed. + */ +void +sudoers_to_eventlog(struct eventlog *evlog, char * const argv[], + char * const envp[]) +{ + struct group *grp; + debug_decl(sudoers_to_eventlog, SUDOERS_DEBUG_LOGGING); + + /* We rely on the reference held by the group cache. */ + if ((grp = sudo_getgrgid(sudo_user.pw->pw_gid)) != NULL) + sudo_gr_delref(grp); + + memset(evlog, 0, sizeof(*evlog)); + evlog->iolog_file = sudo_user.iolog_file; + evlog->iolog_path = sudo_user.iolog_path; + evlog->command = safe_cmnd ? safe_cmnd : (argv ? argv[0] : NULL); + evlog->cwd = user_cwd; + if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) { + evlog->runchroot = def_runchroot; + } + if (def_runcwd && strcmp(def_runcwd, "*") != 0) { + evlog->runcwd = def_runcwd; + } else if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL) { + evlog->runcwd = runas_pw->pw_dir; + } else { + evlog->runcwd = user_cwd; + } + evlog->rungroup = runas_gr ? runas_gr->gr_name : sudo_user.runas_group; + evlog->submithost = user_host; + evlog->submituser = user_name; + if (grp != NULL) + evlog->submitgroup = grp->gr_name; + evlog->ttyname = user_ttypath; + evlog->argv = (char **)argv; + evlog->env_add = (char **)sudo_user.env_vars; + evlog->envp = (char **)envp; + evlog->submit_time = sudo_user.submit_time; + evlog->lines = sudo_user.lines; + evlog->columns = sudo_user.cols; + if (runas_pw != NULL) { + evlog->rungid = runas_pw->pw_gid; + evlog->runuid = runas_pw->pw_uid; + evlog->runuser = runas_pw->pw_name; + } else { + evlog->rungid = (gid_t)-1; + evlog->runuid = (uid_t)-1; + evlog->runuser = sudo_user.runas_user; + } + + debug_return; +} + +static FILE * +sudoers_log_open(int type, const char *log_file) +{ + bool uid_changed; + FILE *fp = NULL; + mode_t oldmask; + int fd, flags; + char *omode; + debug_decl(sudoers_log_open, SUDOERS_DEBUG_LOGGING); + + switch (type) { + case EVLOG_SYSLOG: + openlog("sudo", def_syslog_pid ? LOG_PID : 0, def_syslog); + break; + case EVLOG_FILE: + /* Open log file as root, mode 0600 (cannot append to JSON). */ + if (def_log_format == json) { + flags = O_RDWR|O_CREAT; + omode = "w"; + } else { + flags = O_WRONLY|O_APPEND|O_CREAT; + omode = "a"; + } + oldmask = umask(S_IRWXG|S_IRWXO); + uid_changed = set_perms(PERM_ROOT); + fd = open(log_file, flags, S_IRUSR|S_IWUSR); + if (uid_changed && !restore_perms()) { + if (fd != -1) { + close(fd); + fd = -1; + } + } + (void) umask(oldmask); + if (fd == -1 || (fp = fdopen(fd, omode)) == NULL) { + if (!warned) { + warned = true; + log_warning(SLOG_SEND_MAIL|SLOG_NO_LOG, + N_("unable to open log file: %s"), log_file); + } + if (fd != -1) + close(fd); + } + break; + default: + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "unsupported log type %d", type); + break; + } + + debug_return_ptr(fp); +} + +static void +sudoers_log_close(int type, FILE *fp) +{ + debug_decl(sudoers_log_close, SUDOERS_DEBUG_LOGGING); + + switch (type) { + case EVLOG_SYSLOG: + break; + case EVLOG_FILE: + if (fp == NULL) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "tried to close NULL log stream"); + break; + } + (void)fflush(fp); + if (ferror(fp) && !warned) { + warned = true; + log_warning(SLOG_SEND_MAIL|SLOG_NO_LOG, + N_("unable to write log file: %s"), def_logfile); + } + fclose(fp); + break; + default: + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "unsupported log type %d", type); + break; + } + + debug_return; +} + +void +init_eventlog_config(void) +{ + int logtype = 0; +#ifdef NO_ROOT_MAILER + uid_t mailuid = user_uid; +#else + uid_t mailuid = ROOT_UID; +#endif + debug_decl(init_eventlog_config, SUDOERS_DEBUG_LOGGING); + + if (def_syslog) + logtype |= EVLOG_SYSLOG; + if (def_logfile) + logtype |= EVLOG_FILE; + + eventlog_set_type(logtype); + eventlog_set_format(def_log_format == sudo ? EVLOG_SUDO : EVLOG_JSON); + eventlog_set_syslog_acceptpri(def_syslog_goodpri); + eventlog_set_syslog_rejectpri(def_syslog_badpri); + eventlog_set_syslog_alertpri(def_syslog_badpri); + eventlog_set_syslog_maxlen(def_syslog_maxlen); + eventlog_set_file_maxlen(def_loglinelen); + eventlog_set_mailuid(mailuid); + eventlog_set_omit_hostname(!def_log_host); + eventlog_set_logpath(def_logfile); + eventlog_set_time_fmt(def_log_year ? "%h %e %T %Y" : "%h %e %T"); + eventlog_set_mailerpath(def_mailerpath); + eventlog_set_mailerflags(def_mailerflags); + eventlog_set_mailfrom(def_mailfrom); + eventlog_set_mailto(def_mailto); + eventlog_set_mailsub(def_mailsub); + eventlog_set_open_log(sudoers_log_open); + eventlog_set_close_log(sudoers_log_close); + + debug_return; +} |