diff --git a/plugins/sudoers/audit.c b/plugins/sudoers/audit.c index d6e0f2962..fd0bc6b51 100644 --- a/plugins/sudoers/audit.c +++ b/plugins/sudoers/audit.c @@ -43,7 +43,6 @@ #endif #ifdef SUDOERS_LOG_CLIENT -static struct client_closure *client_closure = NULL; static struct log_details audit_details; #endif char *audit_msg = NULL; @@ -251,10 +250,19 @@ log_server_accept(char * const command_info[], char * const run_argv[], bool ret = false; debug_decl(log_server_accept, SUDOERS_DEBUG_PLUGIN); - /* Only send accept event to log server if I/O log plugin did not. */ - if (SLIST_EMPTY(&def_log_servers) || def_log_input || def_log_output) + if (SLIST_EMPTY(&def_log_servers)) debug_return_bool(true); + if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + /* Older servers don't support multiple commands per session. */ + if (!client_closure->subcommands) + debug_return_bool(true); + } else { + /* Only send accept event to log server if I/O log plugin did not. */ + if (def_log_input || def_log_output) + debug_return_bool(true); + } + if (sudo_gettime_real(&now) == -1) { sudo_warn("%s", U_("unable to get time of day")); goto done; @@ -263,16 +271,29 @@ log_server_accept(char * const command_info[], char * const run_argv[], sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); goto done; } - audit_to_eventlog(evlog, command_info, run_argv, run_envp); - if (!init_log_details(&audit_details, evlog)) - goto done; - /* Open connection to log server, send hello and accept messages. */ - client_closure = log_server_open(&audit_details, &now, false, - SEND_ACCEPT, NULL, sudoers_audit.event_alloc); - if (client_closure != NULL) - ret = true; + if (client_closure != NULL) { + /* Use existing client closure. */ + if (fmt_accept_message(client_closure, evlog)) { + if (client_closure->write_ev->add(client_closure->write_ev, + &client_closure->log_details->server_timeout) == -1) { + sudo_warn("%s", U_("unable to add event to queue")); + goto done; + } + ret = true; + } + } else { + if (!init_log_details(&audit_details, evlog)) + goto done; + + /* Open connection to log server, send hello and accept messages. */ + client_closure = log_server_open(&audit_details, &now, false, + SEND_ACCEPT, NULL, sudoers_audit.event_alloc); + if (client_closure != NULL) + ret = true; + } + done: debug_return_bool(ret); } diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 252317717..45ea69f7a 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -64,9 +64,6 @@ static struct sudoers_io_operations { const char **errstr); } io_operations; -#ifdef SUDOERS_LOG_CLIENT -static struct client_closure *client_closure; -#endif static struct log_details iolog_details; static bool warned = false; static int iolog_dir_fd = -1; diff --git a/plugins/sudoers/log_client.c b/plugins/sudoers/log_client.c index c56e54606..c643bd08b 100644 --- a/plugins/sudoers/log_client.c +++ b/plugins/sudoers/log_client.c @@ -63,6 +63,9 @@ #include "hostcheck.h" #include "log_client.h" +/* Shared between iolog.c and audit.c */ +struct client_closure *client_closure; + /* Server callback may redirect to client callback for TLS. */ static void client_msg_cb(int fd, int what, void *v); static void server_msg_cb(int fd, int what, void *v); @@ -698,6 +701,9 @@ fmt_client_message(struct client_closure *closure, ClientMessage *msg) msg_len = htonl((uint32_t)len); len += sizeof(msg_len); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new ClientMessage, %zu bytes", + __func__, len); + /* Resize buffer as needed. */ if (len > buf->size) { free(buf->data); @@ -775,10 +781,9 @@ free_info_messages(InfoMessage **info_msgs, size_t n) } static InfoMessage ** -fmt_info_messages(struct client_closure *closure, size_t *n_info_msgs) +fmt_info_messages(struct client_closure *closure, struct eventlog *evlog, + size_t *n_info_msgs) { - struct log_details *details = closure->log_details; - struct eventlog *evlog = details->evlog; InfoMessage__StringList *runargv = NULL; InfoMessage__StringList *runenv = NULL; InfoMessage **info_msgs = NULL; @@ -945,8 +950,8 @@ bad: * Appends the wire format message to the closure's write queue. * Returns true on success, false on failure. */ -static bool -fmt_accept_message(struct client_closure *closure) +bool +fmt_accept_message(struct client_closure *closure, struct eventlog *evlog) { ClientMessage client_msg = CLIENT_MESSAGE__INIT; AcceptMessage accept_msg = ACCEPT_MESSAGE__INIT; @@ -969,7 +974,8 @@ fmt_accept_message(struct client_closure *closure) /* Client will send IoBuffer messages. */ accept_msg.expect_iobufs = closure->log_io; - accept_msg.info_msgs = fmt_info_messages(closure, &accept_msg.n_info_msgs); + accept_msg.info_msgs = fmt_info_messages(closure, evlog, + &accept_msg.n_info_msgs); if (accept_msg.info_msgs == NULL) goto done; @@ -993,8 +999,8 @@ done: * Appends the wire format message to the closure's write queue. * Returns true on success, false on failure. */ -static bool -fmt_reject_message(struct client_closure *closure) +bool +fmt_reject_message(struct client_closure *closure, struct eventlog *evlog) { ClientMessage client_msg = CLIENT_MESSAGE__INIT; RejectMessage reject_msg = REJECT_MESSAGE__INIT; @@ -1017,7 +1023,8 @@ fmt_reject_message(struct client_closure *closure) /* Reason for rejecting the request. */ reject_msg.reason = (char *)closure->reason; - reject_msg.info_msgs = fmt_info_messages(closure, &reject_msg.n_info_msgs); + reject_msg.info_msgs = fmt_info_messages(closure, evlog, + &reject_msg.n_info_msgs); if (reject_msg.info_msgs == NULL) goto done; @@ -1042,7 +1049,7 @@ done: * Returns true on success, false on failure. */ static bool -fmt_alert_message(struct client_closure *closure) +fmt_alert_message(struct client_closure *closure, struct eventlog *evlog) { ClientMessage client_msg = CLIENT_MESSAGE__INIT; AlertMessage alert_msg = ALERT_MESSAGE__INIT; @@ -1065,7 +1072,8 @@ fmt_alert_message(struct client_closure *closure) /* Reason for the alert. */ alert_msg.reason = (char *)closure->reason; - alert_msg.info_msgs = fmt_info_messages(closure, &alert_msg.n_info_msgs); + alert_msg.info_msgs = fmt_info_messages(closure, evlog, + &alert_msg.n_info_msgs); if (alert_msg.info_msgs == NULL) goto done; @@ -1100,7 +1108,7 @@ fmt_initial_message(struct client_closure *closure) switch (closure->state) { case SEND_ACCEPT: /* Format and schedule AcceptMessage. */ - if ((ret = fmt_accept_message(closure))) { + if ((ret = fmt_accept_message(closure, closure->log_details->evlog))) { /* * Move read/write events back to main sudo event loop. * Server messages may occur at any time, so no timeout. @@ -1116,11 +1124,11 @@ fmt_initial_message(struct client_closure *closure) break; case SEND_REJECT: /* Format and schedule RejectMessage. */ - ret = fmt_reject_message(closure); + ret = fmt_reject_message(closure, closure->log_details->evlog); break; case SEND_ALERT: /* Format and schedule AlertMessage. */ - ret = fmt_alert_message(closure); + ret = fmt_alert_message(closure, closure->log_details->evlog); break; default: sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state); @@ -1490,6 +1498,9 @@ handle_server_hello(ServerHello *msg, struct client_closure *closure) __func__, n + 1, msg->servers[n]); } + /* Does the server support logging sub-commands in a session? */ + closure->subcommands = msg->subcommands; + debug_return_bool(true); } diff --git a/plugins/sudoers/log_client.h b/plugins/sudoers/log_client.h index cb8a7a619..b956bd382 100644 --- a/plugins/sudoers/log_client.h +++ b/plugins/sudoers/log_client.h @@ -94,6 +94,7 @@ struct client_closure { SSL *ssl; bool ssl_initialized; #endif /* HAVE_OPENSSL */ + bool subcommands; enum client_state state; enum client_state initial_state; /* XXX - bad name */ struct connection_buffer_list write_bufs; @@ -113,6 +114,8 @@ struct client_closure { struct client_closure *log_server_open(struct log_details *details, struct timespec *now, bool log_io, enum client_state initial_state, const char *reason, struct sudo_plugin_event * (*event_alloc)(void)); bool log_server_close(struct client_closure *closure, int exit_status, int error); bool fmt_client_message(struct client_closure *closure, ClientMessage *msg); +bool fmt_accept_message(struct client_closure *closure, struct eventlog *evlog); +bool fmt_reject_message(struct client_closure *closure, struct eventlog *evlog); bool fmt_exit_message(struct client_closure *closure, int exit_status, int error); bool fmt_io_buf(struct client_closure *closure, int type, const char *buf, unsigned int len, struct timespec *delay); bool fmt_suspend(struct client_closure *closure, const char *signame, struct timespec *delay); @@ -120,5 +123,6 @@ bool fmt_winsize(struct client_closure *closure, unsigned int lines, unsigned in bool log_server_connect(struct client_closure *closure); void client_closure_free(struct client_closure *closure); bool read_server_hello(struct client_closure *closure); +extern struct client_closure *client_closure; #endif /* SUDOERS_LOG_CLIENT_H */ diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 6d0f6cc9a..787e4e21c 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -121,27 +121,45 @@ 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; + /* Older servers don't support multiple commands per session. */ + if (!client_closure->subcommands) + debug_return_bool(true); + + /* Use existing client closure. */ + if (fmt_reject_message(client_closure, evlog)) { + if (client_closure->write_ev->add(client_closure->write_ev, + &client_closure->log_details->server_timeout) == -1) { + sudo_warn("%s", U_("unable to add event to queue")); + goto done; + } + ret = true; + } + } else { + struct log_details details; + + 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); } - /* Only the log_servers string list is dynamically allocated. */ - str_list_free(details.log_servers); +done: debug_return_bool(ret); } @@ -150,7 +168,6 @@ 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; @@ -159,9 +176,6 @@ log_server_alert(struct eventlog *evlog, struct timespec *now, 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")); @@ -169,18 +183,38 @@ log_server_alert(struct eventlog *evlog, struct timespec *now, } } - /* 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; + /* Older servers don't support multiple commands per session. */ + if (!client_closure->subcommands) + debug_return_bool(true); + + /* Use existing client closure. */ + if (fmt_reject_message(client_closure, evlog)) { + if (client_closure->write_ev->add(client_closure->write_ev, + &client_closure->log_details->server_timeout) == -1) { + sudo_warn("%s", U_("unable to add event to queue")); + goto done; + } + ret = true; + } + } else { + if (!init_log_details(&details, evlog)) + 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; + } + + /* Only the log_servers string list is dynamically allocated. */ + str_list_free(details.log_servers); } done: - /* Only the log_servers string list is dynamically allocated. */ free(emessage); - str_list_free(details.log_servers); debug_return_bool(ret); } #else