diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index e5ec0d836..193870be7 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -589,6 +589,14 @@ iolog_deserialize_info(struct log_details *details, char * const user_info[], continue; } break; + case 's': + if (strncmp(*cur, "source=", sizeof("source=") - 1) == 0) { + free(evlog->source); + evlog->source = strdup(*cur + sizeof("source=") - 1); + if (evlog->source == NULL) + goto oom; + continue; + } } } diff --git a/plugins/sudoers/log_client.c b/plugins/sudoers/log_client.c index 78a78290b..9c109a305 100644 --- a/plugins/sudoers/log_client.c +++ b/plugins/sudoers/log_client.c @@ -906,6 +906,9 @@ fmt_info_messages(struct client_closure *closure, struct eventlog *evlog, /* TODO - rungroups */ fill_num("runuid", evlog->runuid); fill_str("runuser", evlog->runuser); + if (evlog->source != NULL) { + fill_str("source", evlog->source); + } if (evlog->cwd != NULL) { fill_str("submitcwd", evlog->cwd); } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 23537ae5b..649983d8c 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -974,6 +974,7 @@ sudoers_to_eventlog(struct eventlog *evlog, const char *cmnd, evlog->runcwd = user_cwd; } evlog->rungroup = runas_gr ? runas_gr->gr_name : sudo_user.runas_group; + evlog->source = sudo_user.source; evlog->submithost = user_host; evlog->submituser = user_name; if (grp != NULL) diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index 9f011d9c7..8ffabc91e 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -668,7 +668,7 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[], } /* Increase the length of command_info as needed, it is *not* checked. */ - command_info = calloc(73, sizeof(char *)); + command_info = calloc(74, sizeof(char *)); if (command_info == NULL) goto oom; @@ -1002,6 +1002,11 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[], if ((command_info[info_len++] = sudo_new_key_val("rlimit_stack", def_rlimit_stack)) == NULL) goto oom; } + if (sudo_user.source != NULL) { + command_info[info_len] = sudo_new_key_val("source", sudo_user.source); + if (command_info[info_len++] == NULL) + goto oom; + } #ifdef HAVE_LOGIN_CAP_H if (def_use_loginclass) { if ((command_info[info_len++] = sudo_new_key_val("login_class", login_class)) == NULL) diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 70dc56418..f9351a923 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -325,6 +325,26 @@ done: debug_return_str(iolog_path); } +struct sudoers_match_info { + struct privilege *priv; /* matching privilege */ + struct userspec *us; /* matching userspec */ + struct cmndspec *cs; /* matching cmndspec */ +}; + +static void +cb_lookup(struct userspec *us, int user_match, struct privilege *priv, + int host_match, struct cmndspec *cs, int date_match, int runas_match, + int cmnd_match, void *closure) +{ + struct sudoers_match_info *info = closure; + + if (cmnd_match != UNSPEC) { + info->us = us; + info->priv = priv; + info->cs = cs; + } +} + /* * Find the command, perform a sudoers lookup, ask for a password as * needed, and perform post-lokup checks. Logs success/failure. @@ -336,6 +356,7 @@ done: static int sudoers_check_common(int pwflag) { + struct sudoers_match_info match_info = { NULL }; int oldlocale, ret = -1; unsigned int validated; time_t now; @@ -375,7 +396,7 @@ sudoers_check_common(int pwflag) */ time(&now); sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); - validated = sudoers_lookup(snl, sudo_user.pw, now, NULL, NULL, + validated = sudoers_lookup(snl, sudo_user.pw, now, cb_lookup, &match_info, &cmnd_status, pwflag); sudoers_setlocale(oldlocale, NULL); if (ISSET(validated, VALIDATE_ERROR)) { @@ -383,6 +404,21 @@ sudoers_check_common(int pwflag) goto done; } + if (match_info.us != NULL && match_info.us->file != NULL) { + free(sudo_user.source); + if (match_info.us->line != 0) { + if (asprintf(&sudo_user.source, "%s:%d:%d", match_info.us->file, + match_info.us->line, match_info.us->column) == -1) + sudo_user.source = NULL; + } else { + sudo_user.source = strdup(match_info.us->file); + } + if (sudo_user.source == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + goto done; + } + } + if (safe_cmnd == NULL) { if ((safe_cmnd = strdup(user_cmnd)) == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); @@ -2049,6 +2085,7 @@ sudo_user_free(void) free(list_cmnd); free(safe_cmnd); free(saved_cmnd); + free(sudo_user.source); free(user_stat); #ifdef HAVE_SELINUX free(user_role); diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 91809d408..255cc6205 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -108,6 +108,7 @@ struct sudo_user { char *cmnd_saved; char *class_name; char *krb5_ccname; + char *source; struct gid_list *gid_list; char * const * env_vars; #ifdef HAVE_SELINUX