diff --git a/doc/sudo_logsrvd.man.in b/doc/sudo_logsrvd.man.in index a6a4af21b..20adc9b34 100644 --- a/doc/sudo_logsrvd.man.in +++ b/doc/sudo_logsrvd.man.in @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.TH "SUDO_LOGSRVD" "@mansectsu@" "October 3, 2019" "Sudo @PACKAGE_VERSION@" "System Manager's Manual" +.TH "SUDO_LOGSRVD" "@mansectsu@" "October 16, 2019" "Sudo @PACKAGE_VERSION@" "System Manager's Manual" .nh .if n .ad l .SH "NAME" @@ -46,6 +46,16 @@ utility in the same way as logs generated directly by the \fBsudoers\fR plugin. .PP +The server also supports restarting interrupted log transfers. +To distinguish completed I/O logs from incomplete ones, the +I/O log timing file is set to be read-only when the log is complete. +.PP +Configuration parameters for +\fBsudo_logsrvd\fR +may be specified in the +sudo_logsrvd.conf(@mansectform@) +file. +.PP The options are as follows: .TP 12n \fB\-f\fR, \fB\--file\fR @@ -60,7 +70,7 @@ Display a short help message to the standard output and exit. \fB\-n\fR, \fB\--no-fork\fR Run \fBsudo_logsrvd\fR -in the the foreground instead of detaching from the terminal and becoming +in the foreground instead of detaching from the terminal and becoming a daemon. .TP 12n \fB\-R\fR, \fB\--random-drop\fR @@ -74,12 +84,6 @@ client to restart a connection. Print the \fBsudo_logsrvd\fR version and exit. -.PP -Configuration parameters for -\fBsudo_logsrvd\fR -may be set in the -sudo_logsrvd.conf(@mansectform@) -file. .SS "Debugging sudo_logsrvd" \fBsudo_logsrvd\fR supports a flexible debugging framework that is configured via @@ -98,8 +102,12 @@ Sudo front end configuration .TP 26n \fI@sysconfdir@/sudo_logsrvd.conf\fR Sudo log server configuration file +.TP 26n +\fI@iolog_dir@\fR +Default I/O log file location .SH "SEE ALSO" sudo.conf(@mansectform@), +sudo_logsrvd.conf(@mansectform@), sudoers(@mansectform@), sudo(@mansectsu@), sudo_sendlog(@mansectsu@), diff --git a/doc/sudo_logsrvd.mdoc.in b/doc/sudo_logsrvd.mdoc.in index c2baa6cae..2431c75b5 100644 --- a/doc/sudo_logsrvd.mdoc.in +++ b/doc/sudo_logsrvd.mdoc.in @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd October 3, 2019 +.Dd October 16, 2019 .Dt SUDO_LOGSRVD @mansectsu@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -44,6 +44,16 @@ utility in the same way as logs generated directly by the .Nm sudoers plugin. .Pp +The server also supports restarting interrupted log transfers. +To distinguish completed I/O logs from incomplete ones, the +I/O log timing file is set to be read-only when the log is complete. +.Pp +Configuration parameters for +.Nm +may be specified in the +.Xr sudo_logsrvd.conf @mansectform@ +file. +.Pp The options are as follows: .Bl -tag -width Fl .It Fl f , -file @@ -69,12 +79,6 @@ Print the .Nm version and exit. .El -.Pp -Configuration parameters for -.Nm -may be set in the -.Xr sudo_logsrvd.conf @mansectform@ -file. .Ss Debugging sudo_logsrvd .Nm supports a flexible debugging framework that is configured via @@ -92,9 +96,12 @@ please refer to its manual. Sudo front end configuration .It Pa @sysconfdir@/sudo_logsrvd.conf Sudo log server configuration file +.It Pa @iolog_dir@ +Default I/O log file location .El .Sh SEE ALSO .Xr sudo.conf @mansectform@ , +.Xr sudo_logsrvd.conf @mansectform@ , .Xr sudoers @mansectform@ , .Xr sudo @mansectsu@ , .Xr sudo_sendlog @mansectsu@ , diff --git a/logsrvd/iolog_writer.c b/logsrvd/iolog_writer.c index b10717d60..296f37261 100644 --- a/logsrvd/iolog_writer.c +++ b/logsrvd/iolog_writer.c @@ -37,6 +37,7 @@ #include #include "log_server.pb-c.h" +#include "sudo_gettext.h" /* must be included before sudo_compat.h */ #include "sudo_compat.h" #include "sudo_queue.h" #include "sudo_debug.h" @@ -809,6 +810,7 @@ bool iolog_restart(RestartMessage *msg, struct connection_closure *closure) { struct timespec target; + struct stat sb; int iofd; debug_decl(iolog_restart, SUDO_DEBUG_UTIL) @@ -830,6 +832,19 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure) goto bad; } + /* If the timing file write bit is clear, log is already complete. */ + if (fstatat(closure->iolog_dir_fd, "timing", &sb, 0) == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to stat %s/timing", closure->details.iolog_path); + goto bad; + } + if (!ISSET(sb.st_mode, S_IWUSR)) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "%s already complete", closure->details.iolog_path); + closure->errstr = _("log is already complete, cannot be restarted"); + goto bad; + } + /* Open existing I/O log files. */ if (!iolog_open_all(closure->iolog_dir_fd, closure->details.iolog_path, closure->iolog_files, "r+")) @@ -856,6 +871,8 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure) /* Ready to log I/O buffers. */ debug_return_bool(true); bad: + if (closure->errstr == NULL) + closure->errstr = _("unable to restart log"); debug_return_bool(false); } diff --git a/logsrvd/logsrvd.c b/logsrvd/logsrvd.c index 9b822428a..313ec74e8 100644 --- a/logsrvd/logsrvd.c +++ b/logsrvd/logsrvd.c @@ -236,7 +236,7 @@ handle_accept(AcceptMessage *msg, struct connection_closure *closure) debug_return_bool(true); } - /* Send log ID to client for restarting connectoins. */ + /* Send log ID to client for restarting connections. */ if (!fmt_log_id_message(closure->details.iolog_path, &closure->write_buf)) debug_return_bool(false); if (sudo_ev_add(NULL, closure->write_ev, NULL, false) == -1) { @@ -297,6 +297,7 @@ static bool handle_exit(ExitMessage *msg, struct connection_closure *closure) { struct timespec tv = { 0, 0 }; + mode_t mode; debug_decl(handle_exit, SUDO_DEBUG_UTIL) if (closure->state != RUNNING) { @@ -325,6 +326,14 @@ handle_exit(ExitMessage *msg, struct connection_closure *closure) __func__, (long long)closure->elapsed_time.tv_sec, closure->elapsed_time.tv_nsec); + /* Clear write bits from I/O timing file to indicate completion. */ + mode = logsrvd_conf_iolog_mode(); + CLR(mode, S_IWUSR|S_IWGRP|S_IWOTH); + if (fchmodat(closure->iolog_dir_fd, "timing", mode, 0) == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to fchmodat timing file"); + } + /* Schedule the final commit point event immediately. */ if (sudo_ev_add(NULL, closure->commit_ev, &tv, false) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, @@ -352,7 +361,7 @@ handle_restart(RestartMessage *msg, struct connection_closure *closure) if (!iolog_restart(msg, closure)) { sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unable to restart I/O log", __func__); /* XXX - structured error message so client can send from beginning */ - if (!fmt_error_message("unable to restart log", &closure->write_buf)) + if (!fmt_error_message(closure->errstr, &closure->write_buf)) debug_return_bool(false); sudo_ev_del(NULL, closure->read_ev); if (sudo_ev_add(NULL, closure->write_ev, NULL, false) == -1) { diff --git a/logsrvd/logsrvd.h b/logsrvd/logsrvd.h index 652976ad5..1f59ee3fb 100644 --- a/logsrvd/logsrvd.h +++ b/logsrvd/logsrvd.h @@ -145,6 +145,7 @@ int logsrvd_conf_syslog_facility(void); int logsrvd_conf_syslog_acceptpri(void); int logsrvd_conf_syslog_rejectpri(void); int logsrvd_conf_syslog_alertpri(void); +mode_t logsrvd_conf_iolog_mode(void); const char *logsrvd_conf_logfile_path(void); const char *logsrvd_conf_logfile_time_format(void); diff --git a/logsrvd/logsrvd_conf.c b/logsrvd/logsrvd_conf.c index 467d34207..dd603bacb 100644 --- a/logsrvd/logsrvd_conf.c +++ b/logsrvd/logsrvd_conf.c @@ -98,6 +98,12 @@ static struct logsrvd_config { } *logsrvd_config; /* iolog getters */ +mode_t +logsrvd_conf_iolog_mode(void) +{ + return logsrvd_config->iolog.mode; +} + const char * logsrvd_conf_iolog_dir(void) {