diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h index aa3ddedf0..d19a095dd 100644 --- a/include/sudo_eventlog.h +++ b/include/sudo_eventlog.h @@ -109,6 +109,7 @@ struct eventlog { char *submithost; char *submituser; char *submitgroup; + char **submitenv; char *ttyname; char **runargv; char **runenv; diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c index 281ac31a4..ab2722772 100644 --- a/lib/eventlog/eventlog.c +++ b/lib/eventlog/eventlog.c @@ -759,6 +759,19 @@ eventlog_store_json(struct json_container *jsonc, const struct eventlog *evlog) goto oom; } + if (evlog->submitenv != NULL) { + if (!sudo_json_open_array(jsonc, "submitenv")) + goto oom; + for (i = 0; (cp = evlog->submitenv[i]) != NULL; i++) { + json_value.type = JSON_STRING; + json_value.u.string = cp; + if (!sudo_json_add_value(jsonc, NULL, &json_value)) + goto oom; + } + if (!sudo_json_close_array(jsonc)) + goto oom; + } + debug_return_bool(true); oom: diff --git a/lib/eventlog/eventlog_free.c b/lib/eventlog/eventlog_free.c index 11c3bd12f..7643f5292 100644 --- a/lib/eventlog/eventlog_free.c +++ b/lib/eventlog/eventlog_free.c @@ -55,6 +55,11 @@ eventlog_free(struct eventlog *evlog) free(evlog->peeraddr); free(evlog->signal_name); free(evlog->source); + if (evlog->submitenv != NULL) { + for (i = 0; evlog->submitenv[i] != NULL; i++) + free(evlog->submitenv[i]); + free(evlog->submitenv); + } free(evlog->submithost); free(evlog->submituser); free(evlog->submitgroup); diff --git a/lib/eventlog/parse_json.c b/lib/eventlog/parse_json.c index 7f2ce3ec3..9b5a1683a 100644 --- a/lib/eventlog/parse_json.c +++ b/lib/eventlog/parse_json.c @@ -195,6 +195,22 @@ json_array_to_strvec(struct eventlog_json_object *array) debug_return_ptr(ret); } +static bool +json_store_submitenv(struct json_item *item, struct eventlog *evlog) +{ + size_t i; + debug_decl(json_store_submitenv, SUDO_DEBUG_UTIL); + + if (evlog->submitenv != NULL) { + for (i = 0; evlog->submitenv[i] != NULL; i++) + free(evlog->submitenv[i]); + free(evlog->submitenv); + } + evlog->submitenv = json_array_to_strvec(&item->u.child); + + debug_return_bool(evlog->submitenv != NULL); +} + static bool json_store_runargv(struct json_item *item, struct eventlog *evlog) { @@ -464,6 +480,7 @@ static struct evlog_json_key { { "source", JSON_STRING, json_store_source }, { "signal", JSON_STRING, json_store_signal }, { "submitcwd", JSON_STRING, json_store_submitcwd }, + { "submitenv", JSON_ARRAY, json_store_submitenv }, { "submithost", JSON_STRING, json_store_submithost }, { "submitgroup", JSON_STRING, json_store_submitgroup }, { "submituser", JSON_STRING, json_store_submituser }, diff --git a/logsrvd/iolog_writer.c b/logsrvd/iolog_writer.c index 91b9547a1..940bd48b0 100644 --- a/logsrvd/iolog_writer.c +++ b/logsrvd/iolog_writer.c @@ -303,6 +303,14 @@ evlog_new(TimeSpec *submit_time, InfoMessage **info_msgs, size_t infolen, } continue; } + if (strcmp(key, "submitenv") == 0) { + if (type_matches(info, source, INFO_MESSAGE__VALUE_STRLISTVAL)) { + evlog->submitenv = strlist_copy(info->u.strlistval); + if (evlog->submitenv == NULL) + goto bad; + } + continue; + } if (strcmp(key, "submitgroup") == 0) { if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) { if ((evlog->submitgroup = strdup(info->u.strval)) == NULL) { diff --git a/logsrvd/sendlog.c b/logsrvd/sendlog.c index 005efbdb9..f734cbba0 100644 --- a/logsrvd/sendlog.c +++ b/logsrvd/sendlog.c @@ -539,6 +539,21 @@ fmt_runenv(const struct eventlog *evlog) debug_return_ptr(vec_to_stringlist(evlog->runenv)); } +/* + * Build submitenv StringList from env in evlog, if present. + */ +static InfoMessage__StringList * +fmt_submitenv(const struct eventlog *evlog) +{ + debug_decl(fmt_submitenv, SUDO_DEBUG_UTIL); + + /* Only present in log.json. */ + if (evlog->submitenv == NULL || evlog->submitenv[0] == NULL) + debug_return_ptr(NULL); + + debug_return_ptr(vec_to_stringlist(evlog->submitenv)); +} + static InfoMessage ** fmt_info_messages(const struct eventlog *evlog, char *hostname, size_t *n_info_msgs) @@ -546,6 +561,7 @@ fmt_info_messages(const struct eventlog *evlog, char *hostname, InfoMessage **info_msgs = NULL; InfoMessage__StringList *runargv = NULL; InfoMessage__StringList *runenv = NULL; + InfoMessage__StringList *submitenv = NULL; size_t info_msgs_size, n = 0; debug_decl(fmt_info_messages, SUDO_DEBUG_UTIL); @@ -553,8 +569,9 @@ fmt_info_messages(const struct eventlog *evlog, char *hostname, if (runargv == NULL) goto oom; - /* runenv is only present in log.json */ + /* runenv and submitenv are only present in log.json */ runenv = fmt_runenv(evlog); + submitenv = fmt_submitenv(evlog); /* The sudo I/O log info file has limited info. */ info_msgs_size = 14; @@ -596,6 +613,10 @@ fmt_info_messages(const struct eventlog *evlog, char *hostname, fill_num("lines", evlog->lines); fill_strlist("runargv", runargv); runargv = NULL; + if (submitenv != NULL) { + fill_strlist("submitenv", submitenv); + submitenv = NULL; + } if (runenv != NULL) { fill_strlist("runenv", runenv); runenv = NULL; @@ -637,6 +658,10 @@ oom: free(runenv->strings); free(runenv); } + if (submitenv != NULL) { + free(submitenv->strings); + free(submitenv); + } *n_info_msgs = 0; debug_return_ptr(NULL); } diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 1c4335f1a..51afd3434 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -201,6 +201,8 @@ free_iolog_details(void) iolog_details.evlog->runargv = NULL; free(iolog_details.evlog->runenv); iolog_details.evlog->runenv = NULL; + free(iolog_details.evlog->submitenv); + iolog_details.evlog->submitenv = NULL; eventlog_free(iolog_details.evlog); } str_list_free(iolog_details.log_servers); @@ -292,6 +294,7 @@ static int iolog_deserialize_info(struct log_details *details, char * const user_info[], char * const command_info[], char * const argv[], char * const user_env[]) { + const struct sudoers_context *ctx = sudoers_get_context(); struct eventlog *evlog; const char *runas_uid_str = "0", *runas_euid_str = NULL; const char *runas_gid_str = "0", *runas_egid_str = NULL; @@ -610,6 +613,11 @@ iolog_deserialize_info(struct log_details *details, char * const user_info[], if (evlog->runenv == NULL) goto oom; } + if (ctx->user.envp != NULL) { + evlog->submitenv = copy_vector_shallow(ctx->user.envp); + if (evlog->submitenv == NULL) + goto oom; + } /* * Lookup runas user and group, preferring effective over real uid/gid. diff --git a/plugins/sudoers/log_client.c b/plugins/sudoers/log_client.c index 6ee080657..94f3b0bb4 100644 --- a/plugins/sudoers/log_client.c +++ b/plugins/sudoers/log_client.c @@ -818,11 +818,21 @@ fmt_info_messages(struct client_closure *closure, struct eventlog *evlog, { InfoMessage__StringList *runargv = NULL; InfoMessage__StringList *runenv = NULL; + InfoMessage__StringList *submitenv = NULL; InfoMessage **info_msgs = NULL; size_t info_msgs_size, n = 0; debug_decl(fmt_info_messages, SUDOERS_DEBUG_UTIL); /* Convert NULL-terminated vectors to StringList. */ + if (evlog->submitenv != NULL) { + if ((submitenv = malloc(sizeof(*submitenv))) == NULL) + goto bad; + info_message__string_list__init(submitenv); + submitenv->strings = evlog->submitenv; + while (submitenv->strings[submitenv->n_strings] != NULL) + submitenv->n_strings++; + } + if (evlog->runargv != NULL) { if ((runargv = malloc(sizeof(*runargv))) == NULL) goto bad; @@ -912,7 +922,10 @@ fmt_info_messages(struct client_closure *closure, struct eventlog *evlog, if (evlog->cwd != NULL) { fill_str("submitcwd", evlog->cwd); } - /* TODO - submitenv */ + if (submitenv != NULL) { + fill_strlist("submitenv", submitenv); + submitenv = NULL; + } /* TODO - submitgid */ /* TODO - submitgids */ /* TODO - submitgroup */ @@ -935,6 +948,7 @@ bad: free_info_messages(info_msgs, n); free(runargv); free(runenv); + free(submitenv); *n_info_msgs = 0; debug_return_ptr(NULL); diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 353a7faf3..8e68624d5 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -969,7 +969,7 @@ should_mail(const struct sudoers_context *ctx, unsigned int status) */ void sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, - const char *cmnd, char * const argv[], char * const envp[], + const char *cmnd, char * const runargv[], char * const runenv[], const char *uuid_str) { struct group *grp; @@ -982,7 +982,7 @@ sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, memset(evlog, 0, sizeof(*evlog)); evlog->iolog_file = ctx->iolog_file; evlog->iolog_path = ctx->iolog_path; - evlog->command = cmnd ? (char *)cmnd : (argv ? argv[0] : NULL); + evlog->command = cmnd ? (char *)cmnd : (runargv ? runargv[0] : NULL); evlog->cwd = ctx->user.cwd; if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) { evlog->runchroot = def_runchroot; @@ -1001,9 +1001,10 @@ sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, if (grp != NULL) evlog->submitgroup = grp->gr_name; evlog->ttyname = ctx->user.ttypath; - evlog->runargv = (char **)argv; + evlog->runargv = (char **)runargv; evlog->env_add = (char **)ctx->user.env_add; - evlog->runenv = (char **)envp; + evlog->runenv = (char **)runenv; + evlog->submitenv = (char **)ctx->user.envp; evlog->submit_time = ctx->submit_time; evlog->lines = ctx->user.lines; evlog->columns = ctx->user.cols; diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index 3a61e4c70..647fd282d 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/logging.h @@ -85,7 +85,7 @@ bool log_warningx(const struct sudoers_context *ctx, unsigned int flags, const c bool gai_log_warning(const struct sudoers_context *ctx, unsigned int flags, int errnum, const char * restrict fmt, ...) sudo_printflike(4, 5); bool sudoers_initlocale(const char *ulocale, const char *slocale); bool sudoers_locale_callback(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op); -void sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, const char *cmnd, char * const argv[], char *const envp[], const char *uuid_str); +void sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, const char *cmnd, char * const runargv[], char *const runenv[], const char *uuid_str); void init_eventlog_config(void); bool init_log_details(struct log_details *details, struct eventlog *evlog); bool log_parse_error(const struct sudoers_context *ctx, const char *file, int line, int column, const char * restrict fmt, va_list ap) sudo_printf0like(5, 0);