diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h index 1f7a4cbd9..998586b6c 100644 --- a/include/sudo_eventlog.h +++ b/include/sudo_eventlog.h @@ -91,6 +91,7 @@ bool eventlog_accept(const struct eventlog *details, eventlog_json_callback_t in bool eventlog_alert(const struct eventlog *details, struct timespec *alert_time, const char *reason, const char *errstr); bool eventlog_reject(const struct eventlog *details, const char *reason, eventlog_json_callback_t info_cb, void *info); bool eventlog_setconf(struct eventlog_config *conf); +bool eventlog_store_json(struct json_container *json, const struct eventlog *evlog); void eventlog_free(struct eventlog *evlog); #endif /* SUDO_EVENTLOG_H */ diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c index 1cd6e7b18..f6daebc6e 100644 --- a/lib/eventlog/eventlog.c +++ b/lib/eventlog/eventlog.c @@ -293,6 +293,146 @@ oom: debug_return_bool(false); } +/* + * Store the contents of struct eventlog as JSON. + * The submit_time and iolog_path members are not stored, they should + * be stored and formatted by the caller. + */ +bool +eventlog_store_json(struct json_container *json, const struct eventlog *evlog) +{ + struct json_value json_value; + size_t i; + char *cp; + debug_decl(eventlog_store_json, SUDO_DEBUG_UTIL); + + /* Required settings. */ + if (evlog->command == NULL || evlog->submituser == NULL || + evlog->runuser == NULL) + debug_return_bool(false); + + /* Note: submit_time and iolog_path must be stored by caller. */ + + json_value.type = JSON_NUMBER; + json_value.u.number = evlog->columns; + if (!sudo_json_add_value(json, "columns", &json_value)) + goto oom; + + json_value.type = JSON_STRING; + json_value.u.string = evlog->command; + if (!sudo_json_add_value(json, "command", &json_value)) + goto oom; + + json_value.type = JSON_NUMBER; + json_value.u.number = evlog->lines; + if (!sudo_json_add_value(json, "lines", &json_value)) + goto oom; + + if (evlog->argv != NULL) { + if (!sudo_json_open_array(json, "runargv")) + goto oom; + for (i = 0; (cp = evlog->argv[i]) != NULL; i++) { + json_value.type = JSON_STRING; + json_value.u.string = cp; + if (!sudo_json_add_value(json, NULL, &json_value)) + goto oom; + } + if (!sudo_json_close_array(json)) + goto oom; + } + + if (evlog->envp != NULL) { + if (!sudo_json_open_array(json, "runenv")) + goto oom; + for (i = 0; (cp = evlog->envp[i]) != NULL; i++) { + json_value.type = JSON_STRING; + json_value.u.string = cp; + if (!sudo_json_add_value(json, NULL, &json_value)) + goto oom; + } + if (!sudo_json_close_array(json)) + goto oom; + } + + if (evlog->rungroup!= NULL) { + if (evlog->rungid != (gid_t)-1) { + json_value.type = JSON_ID; + json_value.u.id = evlog->rungid; + if (!sudo_json_add_value(json, "rungid", &json_value)) + goto oom; + } + + json_value.type = JSON_STRING; + json_value.u.string = evlog->rungroup; + if (!sudo_json_add_value(json, "rungroup", &json_value)) + goto oom; + } + + if (evlog->runuid != (uid_t)-1) { + json_value.type = JSON_ID; + json_value.u.id = evlog->runuid; + if (!sudo_json_add_value(json, "runuid", &json_value)) + goto oom; + } + + if (evlog->runchroot != NULL) { + json_value.type = JSON_STRING; + json_value.u.string = evlog->runchroot; + if (!sudo_json_add_value(json, "runchroot", &json_value)) + goto oom; + } + + if (evlog->runcwd != NULL) { + json_value.type = JSON_STRING; + json_value.u.string = evlog->runcwd; + if (!sudo_json_add_value(json, "runcwd", &json_value)) + goto oom; + } + + json_value.type = JSON_STRING; + json_value.u.string = evlog->runuser; + if (!sudo_json_add_value(json, "runuser", &json_value)) + goto oom; + + if (evlog->cwd != NULL) { + json_value.type = JSON_STRING; + json_value.u.string = evlog->cwd; + if (!sudo_json_add_value(json, "submitcwd", &json_value)) + goto oom; + } + + if (evlog->submithost != NULL) { + json_value.type = JSON_STRING; + json_value.u.string = evlog->submithost; + if (!sudo_json_add_value(json, "submithost", &json_value)) + goto oom; + } + + json_value.type = JSON_STRING; + json_value.u.string = evlog->submituser; + if (!sudo_json_add_value(json, "submituser", &json_value)) + goto oom; + + if (evlog->ttyname != NULL) { + json_value.type = JSON_STRING; + json_value.u.string = evlog->ttyname; + if (!sudo_json_add_value(json, "ttyname", &json_value)) + goto oom; + } + + debug_return_bool(true); + +oom: + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_bool(false); +} + +static bool +default_json_cb(struct json_container *json, void *v) +{ + return eventlog_store_json(json, v); +} + static char * format_json(int event_type, const char *reason, const char *errstr, const struct eventlog *details, const struct timespec *event_time, @@ -305,6 +445,11 @@ format_json(int event_type, const char *reason, const char *errstr, struct timespec now; debug_decl(format_json, SUDO_DEBUG_UTIL); + if (info_cb == NULL) { + info_cb = default_json_cb; + info = (void *)details; + } + if (sudo_gettime_real(&now) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "unable to read the clock"); @@ -372,11 +517,9 @@ format_json(int event_type, const char *reason, const char *errstr, goto bad; } - /* Dump details if present. */ - if (info_cb != NULL) { - if (!info_cb(&json, info)) - goto bad; - } + /* Write log details. */ + if (!info_cb(&json, info)) + goto bad; if (!sudo_json_close_object(&json)) goto bad; diff --git a/lib/iolog/iolog_fileio.c b/lib/iolog/iolog_fileio.c index 9d5c88dbb..85db9193d 100644 --- a/lib/iolog/iolog_fileio.c +++ b/lib/iolog/iolog_fileio.c @@ -944,14 +944,8 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog) bool ret = false; FILE *fp = NULL; int fd = -1; - size_t i; - char *cp; debug_decl(iolog_write_info_file_json, SUDO_DEBUG_UTIL); - if (evlog->command == NULL || evlog->submituser == NULL || - evlog->submituser == NULL) - debug_return_bool(false); - if (!sudo_json_init(&json, 4, false, false)) debug_return_bool(false); @@ -972,115 +966,8 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog) if (!sudo_json_close_object(&json)) goto oom; - json_value.type = JSON_NUMBER; - json_value.u.number = evlog->columns; - if (!sudo_json_add_value(&json, "columns", &json_value)) - goto oom; - - /* Required */ - json_value.type = JSON_STRING; - json_value.u.string = evlog->command; - if (!sudo_json_add_value(&json, "command", &json_value)) - goto oom; - - json_value.type = JSON_NUMBER; - json_value.u.number = evlog->lines; - if (!sudo_json_add_value(&json, "lines", &json_value)) - goto oom; - - if (evlog->argv != NULL) { - if (!sudo_json_open_array(&json, "runargv")) - goto oom; - for (i = 0; (cp = evlog->argv[i]) != NULL; i++) { - json_value.type = JSON_STRING; - json_value.u.string = cp; - if (!sudo_json_add_value(&json, NULL, &json_value)) - goto oom; - } - if (!sudo_json_close_array(&json)) - goto oom; - } - - if (evlog->envp != NULL) { - if (!sudo_json_open_array(&json, "runenv")) - goto oom; - for (i = 0; (cp = evlog->envp[i]) != NULL; i++) { - json_value.type = JSON_STRING; - json_value.u.string = cp; - if (!sudo_json_add_value(&json, NULL, &json_value)) - goto oom; - } - if (!sudo_json_close_array(&json)) - goto oom; - } - - if (evlog->rungroup!= NULL) { - if (evlog->rungid != (gid_t)-1) { - json_value.type = JSON_ID; - json_value.u.id = evlog->rungid; - if (!sudo_json_add_value(&json, "rungid", &json_value)) - goto oom; - } - - json_value.type = JSON_STRING; - json_value.u.string = evlog->rungroup; - if (!sudo_json_add_value(&json, "rungroup", &json_value)) - goto oom; - } - - if (evlog->runuid != (uid_t)-1) { - json_value.type = JSON_ID; - json_value.u.id = evlog->runuid; - if (!sudo_json_add_value(&json, "runuid", &json_value)) - goto oom; - } - - if (evlog->runchroot != NULL) { - json_value.type = JSON_STRING; - json_value.u.string = evlog->runchroot; - if (!sudo_json_add_value(&json, "runchroot", &json_value)) - goto oom; - } - - if (evlog->runcwd != NULL) { - json_value.type = JSON_STRING; - json_value.u.string = evlog->runcwd; - if (!sudo_json_add_value(&json, "runcwd", &json_value)) - goto oom; - } - - /* Required */ - json_value.type = JSON_STRING; - json_value.u.string = evlog->runuser; - if (!sudo_json_add_value(&json, "runuser", &json_value)) - goto oom; - - if (evlog->cwd != NULL) { - json_value.type = JSON_STRING; - json_value.u.string = evlog->cwd; - if (!sudo_json_add_value(&json, "submitcwd", &json_value)) - goto oom; - } - - if (evlog->submithost != NULL) { - json_value.type = JSON_STRING; - json_value.u.string = evlog->submithost; - if (!sudo_json_add_value(&json, "submithost", &json_value)) - goto oom; - } - - /* Required */ - json_value.type = JSON_STRING; - json_value.u.string = evlog->submituser; - if (!sudo_json_add_value(&json, "submituser", &json_value)) - goto oom; - - if (evlog->ttyname != NULL) { - json_value.type = JSON_STRING; - json_value.u.string = evlog->ttyname; - if (!sudo_json_add_value(&json, "ttyname", &json_value)) - goto oom; - } + if (!eventlog_store_json(&json, evlog)) + goto done; fd = iolog_openat(dfd, "log.json", O_CREAT|O_TRUNC|O_WRONLY); if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {