Open event log at config time instead of open/close for each entry.

If logging via syslog, do the openlog() at config time instead.
We still lock the log file prior to writing to it but unlock
immediately after.
This commit is contained in:
Todd C. Miller
2020-02-22 16:13:56 -07:00
parent 7e5641bc76
commit f40b4c2887
3 changed files with 69 additions and 52 deletions

View File

@@ -397,26 +397,6 @@ bad:
debug_return_str(NULL); debug_return_str(NULL);
} }
/*
* We do an openlog(3)/closelog(3) for each message because some
* authentication methods (notably PAM) use syslog(3) for their
* own nefarious purposes and may call openlog(3) and closelog(3).
* XXX - no longer need openlog/closelog dance, move openlog call
*/
static void
mysyslog(int pri, const char *fmt, ...)
{
va_list ap;
debug_decl(mysyslog, SUDO_DEBUG_UTIL);
openlog("sudo", 0, logsrvd_conf_syslog_facility());
va_start(ap, fmt);
vsyslog(pri, fmt, ap);
va_end(ap);
closelog();
debug_return;
}
/* /*
* Log a message to syslog, pre-pending the username and splitting the * Log a message to syslog, pre-pending the username and splitting the
* message into parts if it is longer than syslog_maxlen. * message into parts if it is longer than syslog_maxlen.
@@ -457,7 +437,7 @@ do_syslog_sudo(int pri, const char *reason, const struct iolog_details *details)
save = *tmp; save = *tmp;
*tmp = '\0'; *tmp = '\0';
mysyslog(pri, fmt, details->submituser, p); syslog(pri, fmt, details->submituser, p);
*tmp = save; /* restore saved character */ *tmp = save; /* restore saved character */
@@ -465,7 +445,7 @@ do_syslog_sudo(int pri, const char *reason, const struct iolog_details *details)
for (p = tmp; *p == ' '; p++) for (p = tmp; *p == ' '; p++)
continue; continue;
} else { } else {
mysyslog(pri, fmt, details->submituser, p); syslog(pri, fmt, details->submituser, p);
p += len; p += len;
} }
fmt = _("%8s : (command continued) %s"); fmt = _("%8s : (command continued) %s");
@@ -496,7 +476,7 @@ do_syslog_json(int pri, ClientMessage__TypeCase event_type, const char *reason,
/* Syslog it with a @cee: prefix */ /* Syslog it with a @cee: prefix */
/* TODO: use logsrvd_conf_syslog_maxlen() to break up long messages. */ /* TODO: use logsrvd_conf_syslog_maxlen() to break up long messages. */
mysyslog(pri, "@cee:{%s }", json_str); syslog(pri, "@cee:{%s }", json_str);
free(json_str); free(json_str);
debug_return_bool(true); debug_return_bool(true);
} }
@@ -556,24 +536,16 @@ do_logfile_sudo(const char *reason, const struct iolog_details *details)
{ {
const char *timefmt = logsrvd_conf_logfile_time_format(); const char *timefmt = logsrvd_conf_logfile_time_format();
const char *logfile = logsrvd_conf_logfile_path(); const char *logfile = logsrvd_conf_logfile_path();
FILE *fp = logsrvd_conf_logfile_stream();
char *logline, timebuf[8192], *timestr = NULL; char *logline, timebuf[8192], *timestr = NULL;
struct tm *timeptr; struct tm *timeptr;
bool ret = false; bool ret = false;
mode_t oldmask;
FILE *fp;
debug_decl(do_logfile_sudo, SUDO_DEBUG_UTIL); debug_decl(do_logfile_sudo, SUDO_DEBUG_UTIL);
if ((logline = new_logline(reason, NULL, details)) == NULL) if ((logline = new_logline(reason, NULL, details)) == NULL)
debug_return_bool(false); debug_return_bool(false);
oldmask = umask(S_IRWXG|S_IRWXO);
fp = fopen(logfile, "a");
(void) umask(oldmask);
if (fp == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to open log file %s", logfile);
goto done;
}
if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) { if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to lock log file %s", logfile); "unable to lock log file %s", logfile);
@@ -599,9 +571,8 @@ do_logfile_sudo(const char *reason, const struct iolog_details *details)
ret = true; ret = true;
done: done:
if (fp != NULL)
(void) fclose(fp);
free(logline); free(logline);
(void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
debug_return_bool(ret); debug_return_bool(ret);
} }
@@ -610,11 +581,10 @@ do_logfile_json(ClientMessage__TypeCase event_type, const char *reason,
TimeSpec *event_time, InfoMessage **info_msgs, size_t infolen) TimeSpec *event_time, InfoMessage **info_msgs, size_t infolen)
{ {
const char *logfile = logsrvd_conf_logfile_path(); const char *logfile = logsrvd_conf_logfile_path();
FILE *fp = logsrvd_conf_logfile_stream();
struct stat sb; struct stat sb;
char *json_str; char *json_str;
mode_t oldmask; int ret = false;
FILE *fp = NULL;
int fd, ret = false;
debug_decl(do_logfile_json, SUDO_DEBUG_UTIL); debug_decl(do_logfile_json, SUDO_DEBUG_UTIL);
json_str = format_json(event_type, reason, event_time, info_msgs, json_str = format_json(event_type, reason, event_time, info_msgs,
@@ -622,16 +592,6 @@ do_logfile_json(ClientMessage__TypeCase event_type, const char *reason,
if (json_str == NULL) if (json_str == NULL)
goto done; goto done;
oldmask = umask(S_IRWXG|S_IRWXO);
fd = open(logfile, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
(void)umask(oldmask);
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to open log file %s", logfile);
if (fd != -1)
close(fd);
goto done;
}
if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) { if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to lock log file %s", logfile); "unable to lock log file %s", logfile);
@@ -657,15 +617,14 @@ do_logfile_json(ClientMessage__TypeCase event_type, const char *reason,
} }
fputs(json_str, fp); fputs(json_str, fp);
fputs("\n}\n", fp); /* close JSON */ fputs("\n}\n", fp); /* close JSON */
fclose(fp); fflush(fp);
/* XXX - check for file error and recover */ /* XXX - check for file error and recover */
ret = true; ret = true;
done: done:
free(json_str); free(json_str);
if (fp != NULL) (void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
fclose(fp);
debug_return_bool(ret); debug_return_bool(ret);
} }

View File

@@ -205,6 +205,7 @@ int logsrvd_conf_syslog_rejectpri(void);
int logsrvd_conf_syslog_alertpri(void); int logsrvd_conf_syslog_alertpri(void);
mode_t logsrvd_conf_iolog_mode(void); mode_t logsrvd_conf_iolog_mode(void);
const char *logsrvd_conf_logfile_path(void); const char *logsrvd_conf_logfile_path(void);
FILE *logsrvd_conf_logfile_stream(void);
const char *logsrvd_conf_logfile_time_format(void); const char *logsrvd_conf_logfile_time_format(void);
#endif /* SUDO_LOGSRVD_H */ #endif /* SUDO_LOGSRVD_H */

View File

@@ -34,6 +34,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
@@ -106,6 +107,7 @@ static struct logsrvd_config {
struct logsrvd_config_logfile { struct logsrvd_config_logfile {
char *path; char *path;
char *time_format; char *time_format;
FILE *stream;
} logfile; } logfile;
} *logsrvd_config; } *logsrvd_config;
@@ -221,6 +223,12 @@ logsrvd_conf_logfile_path(void)
return logsrvd_config->logfile.path; return logsrvd_config->logfile.path;
} }
FILE *
logsrvd_conf_logfile_stream(void)
{
return logsrvd_config->logfile.stream;
}
const char * const char *
logsrvd_conf_logfile_time_format(void) logsrvd_conf_logfile_time_format(void)
{ {
@@ -685,7 +693,6 @@ cb_logfile_path(struct logsrvd_config *config, const char *str)
debug_return_bool(false); debug_return_bool(false);
} }
/* TODO: open log file */
free(config->logfile.path); free(config->logfile.path);
config->logfile.path = copy; config->logfile.path = copy;
@@ -850,6 +857,36 @@ done:
debug_return_bool(ret); debug_return_bool(ret);
} }
static FILE *
logsrvd_open_eventlog(struct logsrvd_config *config)
{
mode_t oldmask;
FILE *fp = NULL;
const char *omode;
int fd, flags;
debug_decl(logsrvd_open_eventlog, SUDO_DEBUG_UTIL);
/* Cannot append to a JSON file. */
if (config->eventlog.log_format == EVLOG_JSON) {
flags = O_RDWR|O_CREAT;
omode = "w";
} else {
flags = O_WRONLY|O_APPEND|O_CREAT;
omode = "a";
}
oldmask = umask(S_IRWXG|S_IRWXO);
fd = open(config->logfile.path, flags, S_IRUSR|S_IWUSR);
(void)umask(oldmask);
if (fd == -1 || (fp = fdopen(fd, omode)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to open log file %s", config->logfile.path);
if (fd != -1)
close(fd);
}
debug_return_ptr(fp);
}
/* Free the specified struct logsrvd_config and its contents. */ /* Free the specified struct logsrvd_config and its contents. */
void void
logsrvd_conf_free(struct logsrvd_config *config) logsrvd_conf_free(struct logsrvd_config *config)
@@ -873,6 +910,8 @@ logsrvd_conf_free(struct logsrvd_config *config)
/* struct logsrvd_config_logfile */ /* struct logsrvd_config_logfile */
free(config->logfile.path); free(config->logfile.path);
free(config->logfile.time_format); free(config->logfile.time_format);
if (config->logfile.stream != NULL)
fclose(config->logfile.stream);
#if defined(HAVE_OPENSSL) #if defined(HAVE_OPENSSL)
free(config->server.tls_config.pkey_path); free(config->server.tls_config.pkey_path);
@@ -974,6 +1013,24 @@ logsrvd_conf_apply(struct logsrvd_config *config)
debug_return_bool(false); debug_return_bool(false);
} }
/* Open event log if specified. */
switch (config->eventlog.log_type) {
case EVLOG_SYSLOG:
openlog("sudo", 0, config->syslog.facility);
break;
case EVLOG_FILE:
config->logfile.stream = logsrvd_open_eventlog(config);
if (config->logfile.stream == NULL)
debug_return_bool(false);
break;
case EVLOG_NONE:
break;
default:
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"cannot open unknown log type %d", config->eventlog.log_type);
break;
}
/* Set I/O log library settings */ /* Set I/O log library settings */
iolog_set_defaults(); iolog_set_defaults();
iolog_set_compress(config->iolog.compress); iolog_set_compress(config->iolog.compress);