diff --git a/plugins/sudoers/audit.c b/plugins/sudoers/audit.c index 623b6a712..afe2061ba 100644 --- a/plugins/sudoers/audit.c +++ b/plugins/sudoers/audit.c @@ -249,7 +249,7 @@ audit_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, #ifdef SUDOERS_LOG_CLIENT static bool -log_server_accept(struct eventlog *evlog) +log_server_accept(const struct sudoers_context *ctx, struct eventlog *evlog) { struct timespec now; bool ret = false; @@ -258,7 +258,7 @@ log_server_accept(struct eventlog *evlog) if (SLIST_EMPTY(&def_log_servers)) debug_return_bool(true); - if (client_closure != NULL && ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (client_closure != NULL && ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { /* Older servers don't support multiple commands per session. */ if (!client_closure->subcommands) debug_return_bool(true); @@ -325,7 +325,7 @@ log_server_exit(int status_type, int status) } #else static bool -log_server_accept(struct eventlog *evlog) +log_server_accept(struct sudoers_context *ctx, struct eventlog *evlog) { return true; } @@ -359,22 +359,26 @@ sudoers_audit_accept(const char *plugin_name, unsigned int plugin_type, if (audit_success(ctx, run_argv) != 0 && !def_ignore_audit_errors) ret = false; - if (!ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) + if (!ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) uuid_str = ctx->user.uuid_str; audit_to_eventlog(ctx, &evlog, command_info, run_argv, run_envp, uuid_str); - if (!log_allowed(&evlog) && !def_ignore_logfile_errors) + if (!log_allowed(ctx, &evlog) && !def_ignore_logfile_errors) ret = false; - if (!log_server_accept(&evlog)) { + if (!log_server_accept(ctx, &evlog)) { if (!def_ignore_logfile_errors) ret = false; } if (first) { /* log_subcmds doesn't go through sudo_policy_main again to set this. */ - if (def_log_subcmds) - SET(sudo_mode, MODE_POLICY_INTERCEPTED); + if (def_log_subcmds) { + if (!sudoers_set_mode(MODE_POLICY_INTERCEPTED, UINT_MAX)) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "unable to set 0x%x in ctx->mode", MODE_POLICY_INTERCEPTED); + } + } first = false; } @@ -407,7 +411,7 @@ sudoers_audit_reject(const char *plugin_name, unsigned int plugin_type, if (!eventlog_reject(&evlog, 0, message, NULL, NULL)) ret = false; - if (!log_server_reject(&evlog, message)) + if (!log_server_reject(ctx, &evlog, message)) ret = false; debug_return_int(ret); @@ -442,7 +446,7 @@ sudoers_audit_error(const char *plugin_name, unsigned int plugin_type, if (!eventlog_alert(&evlog, 0, &now, message, NULL)) ret = false; - if (!log_server_alert(&evlog, &now, message, NULL)) + if (!log_server_alert(ctx, &evlog, &now, message, NULL)) ret = false; debug_return_int(ret); diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index da3e46d27..2fc795bf6 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -102,7 +102,7 @@ static pam_handle_t *pamh; static struct conv_filter *conv_filter; static void -conv_filter_init(void) +conv_filter_init(const struct sudoers_context *ctx) { debug_decl(conv_filter_init, SUDOERS_DEBUG_AUTH); @@ -112,7 +112,7 @@ conv_filter_init(void) * management (in trusted mode) or session management (regular mode). * Filter those out in the conversation function unless running a shell. */ - if (!ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { + if (!ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL)) { int i, nfilt = 0, maxfilters = 0; struct conv_filter *newfilt; nl_catd catd; @@ -217,10 +217,10 @@ sudo_pam_init2(const struct sudoers_context *ctx, struct passwd *pw, pam_closure.ctx = ctx; /* Initialize PAM. */ - if (ISSET(sudo_mode, MODE_ASKPASS) && def_pam_askpass_service != NULL) { + if (ISSET(ctx->mode, MODE_ASKPASS) && def_pam_askpass_service != NULL) { pam_service = def_pam_askpass_service; } else { - pam_service = ISSET(sudo_mode, MODE_LOGIN_SHELL) ? + pam_service = ISSET(ctx->mode, MODE_LOGIN_SHELL) ? def_pam_login_service : def_pam_service; } pam_status = pam_start(pam_service, pw->pw_name, &pam_conv, &pamh); @@ -235,7 +235,7 @@ sudo_pam_init2(const struct sudoers_context *ctx, struct passwd *pw, } /* Initialize conversation function message filter. */ - conv_filter_init(); + conv_filter_init(ctx); /* * Set PAM_RUSER to the invoking user (the "from" user). @@ -498,7 +498,7 @@ sudo_pam_begin_session(const struct sudoers_context *ctx, struct passwd *pw, * We use PAM_SILENT to prevent pam_lastlog from printing last login * information except when explicitly running a shell. */ - const bool silent = !ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL); + const bool silent = !ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL); rc = pam_open_session(pamh, silent ? PAM_SILENT : 0); switch (rc) { case PAM_SUCCESS: @@ -538,7 +538,7 @@ sudo_pam_begin_session(const struct sudoers_context *ctx, struct passwd *pw, char **pam_envp = pam_getenvlist(pamh); if (pam_envp != NULL) { /* Merge pam env with user env. */ - if (!env_init(*user_envp) || !env_merge(pam_envp)) + if (!env_init(*user_envp) || !env_merge(ctx, pam_envp)) status = AUTH_FATAL; *user_envp = env_get(); free(pam_envp); diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c index ed6e4d28c..c1ee968ca 100644 --- a/plugins/sudoers/check.c +++ b/plugins/sudoers/check.c @@ -173,7 +173,7 @@ check_user(struct sudoers_context *ctx, unsigned int validated, * In intercept mode, only check the user if configured to do so. * We already have a session so no need to init the auth subsystem. */ - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { if (!def_intercept_authenticate) { debug_return_int(true); } diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c index 3ac20b760..3d1b096ae 100644 --- a/plugins/sudoers/env.c +++ b/plugins/sudoers/env.c @@ -703,13 +703,14 @@ matches_env_check(const char *var, bool *full_match) * Returns true if the variable is allowed else false. */ static bool -matches_env_keep(const char *var, bool *full_match) +matches_env_keep(const struct sudoers_context *ctx, const char *var, + bool *full_match) { bool keepit = false; debug_decl(matches_env_keep, SUDOERS_DEBUG_ENV); /* Preserve SHELL variable for "sudo -s". */ - if (ISSET(sudo_mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) { + if (ISSET(ctx->mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) { keepit = true; } else if (matches_env_list(var, &def_env_keep, full_match)) { keepit = true; @@ -742,7 +743,7 @@ env_should_delete(const char *var) * Returns true if the variable is allowed else false. */ static bool -env_should_keep(const char *var) +env_should_keep(const struct sudoers_context *ctx, const char *var) { int keepit; bool full_match = false; @@ -751,7 +752,7 @@ env_should_keep(const char *var) keepit = matches_env_check(var, &full_match); if (keepit == -1) - keepit = matches_env_keep(var, &full_match); + keepit = matches_env_keep(ctx, var, &full_match); /* Skip bash functions unless we matched on the value as well as name. */ if (keepit && !full_match) { @@ -773,7 +774,7 @@ env_should_keep(const char *var) * Returns true on success or false on failure. */ bool -env_merge(char * const envp[]) +env_merge(const struct sudoers_context *ctx, char * const envp[]) { char * const *ep; bool ret = true; @@ -781,7 +782,7 @@ env_merge(char * const envp[]) for (ep = envp; *ep != NULL; ep++) { /* XXX - avoid checking value here, should only check name */ - bool overwrite = def_env_reset ? !env_should_keep(*ep) : env_should_delete(*ep); + bool overwrite = def_env_reset ? !env_should_keep(ctx, *ep) : env_should_delete(*ep); if (sudo_putenv(*ep, true, overwrite) == -1) { /* XXX cannot undo on failure */ ret = false; @@ -884,21 +885,21 @@ rebuild_env(const struct sudoers_context *ctx) #endif /* Reset HOME based on target user if configured to. */ - if (ISSET(sudo_mode, MODE_RUN)) { + if (ISSET(ctx->mode, MODE_RUN)) { if (def_always_set_home || - ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || - (ISSET(sudo_mode, MODE_SHELL) && def_set_home)) + ISSET(ctx->mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || + (ISSET(ctx->mode, MODE_SHELL) && def_set_home)) reset_home = true; } - if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + if (def_env_reset || ISSET(ctx->mode, MODE_LOGIN_SHELL)) { /* * If starting with a fresh environment, initialize it based on * /etc/environment or login.conf. For "sudo -i" we want those * variables to override the invoking user's environment, so we * defer reading them until later. */ - if (!ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + if (!ISSET(ctx->mode, MODE_LOGIN_SHELL)) { #ifdef HAVE_LOGIN_CAP_H /* Insert login class environment variables. */ if (ctx->runas.class) { @@ -912,7 +913,7 @@ rebuild_env(const struct sudoers_context *ctx) #endif /* HAVE_LOGIN_CAP_H */ #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM)) /* Insert system-wide environment variables. */ - if (!read_env_file(_PATH_ENVIRONMENT, true, false)) + if (!read_env_file(ctx, _PATH_ENVIRONMENT, true, false)) sudo_warn("%s", _PATH_ENVIRONMENT); #endif for (ep = env.envp; *ep; ep++) @@ -927,7 +928,7 @@ rebuild_env(const struct sudoers_context *ctx) /* * Look up the variable in the env_check and env_keep lists. */ - keepit = env_should_keep(*ep); + keepit = env_should_keep(ctx, *ep); /* * Do SUDO_PS1 -> PS1 conversion. @@ -950,7 +951,7 @@ rebuild_env(const struct sudoers_context *ctx) * otherwise they may be from the user's environment (depends * on sudoers options). */ - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + if (ISSET(ctx->mode, MODE_LOGIN_SHELL)) { CHECK_SETENV2("SHELL", ctx->runas.pw->pw_shell, ISSET(didvar, DID_SHELL), true); #ifdef _AIX @@ -983,7 +984,7 @@ rebuild_env(const struct sudoers_context *ctx) * Set MAIL to target user in -i mode or if MAIL is not preserved * from user's environment. */ - if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) { + if (ISSET(ctx->mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) { if (_PATH_MAILDIR[sizeof(_PATH_MAILDIR) - 2] == '/') { len = asprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, ctx->runas.pw->pw_name); @@ -1032,7 +1033,7 @@ rebuild_env(const struct sudoers_context *ctx) * disabled. We skip this if we are running a login shell (because * they have already been set). */ - if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + if (def_set_logname && !ISSET(ctx->mode, MODE_LOGIN_SHELL)) { if ((didvar & KEPT_USER_VARIABLES) == 0) { /* Nothing preserved, set them all. */ #ifdef _AIX @@ -1172,7 +1173,7 @@ validate_env_vars(const struct sudoers_context *ctx, char * const env_vars[]) strncmp(*ep, "PATH=", 5) == 0) { okvar = false; } else if (def_env_reset) { - okvar = env_should_keep(*ep); + okvar = env_should_keep(ctx, *ep); } else { okvar = !env_should_delete(*ep); } @@ -1328,7 +1329,8 @@ register_env_file(void * (*ef_open)(const char *), void (*ef_close)(void *), } bool -read_env_file(const char *path, bool overwrite, bool restricted) +read_env_file(const struct sudoers_context *ctx, const char *path, + bool overwrite, bool restricted) { struct sudoers_env_file *ef; bool ret = true; @@ -1363,7 +1365,7 @@ read_env_file(const char *path, bool overwrite, bool restricted) * when env_reset is set or env_delete when it is not. */ if (restricted) { - if (def_env_reset ? !env_should_keep(envstr) : env_should_delete(envstr)) { + if (def_env_reset ? !env_should_keep(ctx, envstr) : env_should_delete(envstr)) { free(envstr); continue; } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 66e4a8bcb..69386580f 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -67,7 +67,7 @@ STAILQ_HEAD(parse_error_list, parse_error); static struct parse_error_list parse_error_list = STAILQ_HEAD_INITIALIZER(parse_error_list); -static bool should_mail(unsigned int); +static bool should_mail(const struct sudoers_context *ctx, unsigned int); static bool warned = false; #ifdef SUDOERS_LOG_CLIENT @@ -127,7 +127,8 @@ init_log_details(struct log_details *details, struct eventlog *evlog) } bool -log_server_reject(struct eventlog *evlog, const char *message) +log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog, + const char *message) { bool ret = false; debug_decl(log_server_reject, SUDOERS_DEBUG_LOGGING); @@ -135,7 +136,7 @@ log_server_reject(struct eventlog *evlog, const char *message) if (SLIST_EMPTY(&def_log_servers)) debug_return_bool(true); - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { /* Older servers don't support multiple commands per session. */ if (!client_closure->subcommands) debug_return_bool(true); @@ -173,8 +174,8 @@ done: } bool -log_server_alert(struct eventlog *evlog, struct timespec *now, - const char *message, const char *errstr) +log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog, + struct timespec *now, const char *message, const char *errstr) { struct log_details details; char *emessage = NULL; @@ -191,7 +192,7 @@ log_server_alert(struct eventlog *evlog, struct timespec *now, } } - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { /* Older servers don't support multiple commands per session. */ if (!client_closure->subcommands) { ret = true; @@ -230,14 +231,15 @@ done: } #else bool -log_server_reject(struct eventlog *evlog, const char *message) +log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog, + const char *message) { return true; } bool -log_server_alert(struct eventlog *evlog, struct timespec *now, - const char *message, const char *errstr) +log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog, + struct timespec *now, const char *message, const char *errstr) { return true; } @@ -256,7 +258,7 @@ log_reject(const struct sudoers_context *ctx, const char *message, bool ret; debug_decl(log_reject, SUDOERS_DEBUG_LOGGING); - if (!ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) + if (!ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) uuid_str = ctx->user.uuid_str; if (mailit) { @@ -267,7 +269,7 @@ log_reject(const struct sudoers_context *ctx, const char *message, sudoers_to_eventlog(ctx, &evlog, ctx->runas.cmnd, ctx->runas.argv, env_get(), uuid_str); ret = eventlog_reject(&evlog, evl_flags, message, NULL, NULL); - if (!log_server_reject(&evlog, message)) + if (!log_server_reject(ctx, &evlog, message)) ret = false; debug_return_bool(ret); @@ -286,7 +288,7 @@ log_denial(const struct sudoers_context *ctx, unsigned int status, debug_decl(log_denial, SUDOERS_DEBUG_LOGGING); /* Send mail based on status. */ - mailit = should_mail(status); + mailit = should_mail(ctx, status); /* Set error message. */ if (ISSET(status, FLAG_NO_USER)) @@ -329,7 +331,7 @@ log_denial(const struct sudoers_context *ctx, unsigned int status, const char *cmnd1 = ctx->user.cmnd; const char *cmnd2 = ""; - if (ISSET(sudo_mode, MODE_CHECK)) { + if (ISSET(ctx->mode, MODE_CHECK)) { /* For "sudo -l command" the command run is in runas.argv[1]. */ cmnd1 = "list "; cmnd2 = ctx->runas.argv[1]; @@ -371,7 +373,7 @@ log_failure(const struct sudoers_context *ctx, unsigned int status, if (!inform_user) { const char *cmnd = ctx->user.cmnd; - if (ISSET(sudo_mode, MODE_CHECK)) + if (ISSET(ctx->mode, MODE_CHECK)) cmnd = ctx->user.cmnd_list ? ctx->user.cmnd_list : ctx->runas.argv[1]; /* @@ -515,7 +517,7 @@ log_auth_failure(const struct sudoers_context *ctx, unsigned int status, logit = false; } else { /* Command denied, auth failed; make sure we don't send mail twice. */ - if (def_mail_badpass && !should_mail(status)) + if (def_mail_badpass && !should_mail(ctx, status)) mailit = true; /* Don't log the bad password message, we'll log a denial instead. */ logit = false; @@ -565,7 +567,7 @@ log_auth_failure(const struct sudoers_context *ctx, unsigned int status, * Log and potentially mail the allowed command. */ bool -log_allowed(struct eventlog *evlog) +log_allowed(const struct sudoers_context *ctx, struct eventlog *evlog) { int oldlocale; int evl_flags = 0; @@ -573,7 +575,7 @@ log_allowed(struct eventlog *evlog) debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING); /* Send mail based on status. */ - mailit = should_mail(VALIDATE_SUCCESS); + mailit = should_mail(ctx, VALIDATE_SUCCESS); if (def_log_allowed || mailit) { /* Log and mail messages should be in the sudoers locale. */ @@ -740,7 +742,7 @@ vlog_warning(const struct sudoers_context *ctx, unsigned int flags, env_get(), ctx->user.uuid_str); if (!eventlog_alert(&evlog, evl_flags, &now, message, errstr)) ret = false; - if (!log_server_alert(&evlog, &now, message, errstr)) + if (!log_server_alert(ctx, &evlog, &now, message, errstr)) ret = false; } @@ -941,7 +943,7 @@ log_parse_error(const struct sudoers_context *ctx, const char *file, * Determine whether we should send mail based on "status" and defaults options. */ static bool -should_mail(unsigned int status) +should_mail(const struct sudoers_context *ctx, unsigned int status) { debug_decl(should_mail, SUDOERS_DEBUG_LOGGING); @@ -949,7 +951,7 @@ should_mail(unsigned int status) debug_return_bool(false); debug_return_bool(def_mail_always || ISSET(status, VALIDATE_ERROR) || - (def_mail_all_cmnds && ISSET(sudo_mode, (MODE_RUN|MODE_EDIT))) || + (def_mail_all_cmnds && ISSET(ctx->mode, (MODE_RUN|MODE_EDIT))) || (def_mail_no_user && ISSET(status, FLAG_NO_USER)) || (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) || (def_mail_no_perms && !ISSET(status, VALIDATE_SUCCESS))); @@ -981,7 +983,7 @@ sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, } if (def_runcwd && strcmp(def_runcwd, "*") != 0) { evlog->runcwd = def_runcwd; - } else if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && ctx->runas.pw != NULL) { + } else if (ISSET(ctx->mode, MODE_LOGIN_SHELL) && ctx->runas.pw != NULL) { evlog->runcwd = ctx->runas.pw->pw_dir; } else { evlog->runcwd = ctx->user.cwd; @@ -1017,7 +1019,7 @@ sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, } else { strlcpy(evlog->uuid_str, uuid_str, sizeof(evlog->uuid_str)); } - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { struct timespec now; if (sudo_gettime_real(&now) == -1) { sudo_warn("%s", U_("unable to get time of day")); diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index 11a8f1386..3a61e4c70 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/logging.h @@ -73,13 +73,13 @@ bool sudoers_setlocale(int locale_type, int *prev_locale); int sudoers_getlocale(void); int audit_failure(const struct sudoers_context *ctx, char *const argv[], char const * restrict const fmt, ...) sudo_printflike(3, 4); int vaudit_failure(const struct sudoers_context *ctx, char *const argv[], char const * restrict const fmt, va_list ap) sudo_printflike(3, 0); -bool log_allowed(struct eventlog *evlog); +bool log_allowed(const struct sudoers_context *ctx, struct eventlog *evlog); bool log_exit_status(const struct sudoers_context *ctx, int exit_status); bool log_auth_failure(const struct sudoers_context *ctx, unsigned int status, unsigned int tries); bool log_denial(const struct sudoers_context *ctx, unsigned int status, bool inform_user); bool log_failure(const struct sudoers_context *ctx, unsigned int status, int flags); -bool log_server_alert(struct eventlog *evlog, struct timespec *now, const char *message, const char *errstr); -bool log_server_reject(struct eventlog *evlog, const char *message); +bool log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog, struct timespec *now, const char *message, const char *errstr); +bool log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog, const char *message); bool log_warning(const struct sudoers_context *ctx, unsigned int flags, const char * restrict fmt, ...) sudo_printflike(3, 4); bool log_warningx(const struct sudoers_context *ctx, unsigned int flags, const char * restrict fmt, ...) sudo_printflike(3, 4); bool gai_log_warning(const struct sudoers_context *ctx, unsigned int flags, int errnum, const char * restrict fmt, ...) sudo_printflike(4, 5); diff --git a/plugins/sudoers/lookup.c b/plugins/sudoers/lookup.c index 712fa9bb4..f23edcce9 100644 --- a/plugins/sudoers/lookup.c +++ b/plugins/sudoers/lookup.c @@ -221,10 +221,10 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct sudoers_context *ctx, } static void -init_cmnd_info(struct cmnd_info *info) +init_cmnd_info(struct sudoers_context *ctx, struct cmnd_info *info) { memset(info, 0, sizeof(*info)); - if (def_intercept || ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) + if (def_intercept || ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) info->intercepted = true; } @@ -240,7 +240,7 @@ sudoers_lookup_check(struct sudo_nss *nss, struct sudoers_context *ctx, struct member *matching_user; debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER); - init_cmnd_info(info); + init_cmnd_info(ctx, info); TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) { int user_match = userlist_matches(nss->parse_tree, ctx->user.pw, &us->users); @@ -310,7 +310,7 @@ sudoers_lookup_check(struct sudo_nss *nss, struct sudoers_context *ctx, debug_return_int(cmnd_match); } free(info->cmnd_path); - init_cmnd_info(info); + init_cmnd_info(ctx, info); } } } diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index 1ce2b0e80..0c0dbc7d6 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -184,7 +184,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, ctx->settings.flags = 0; ctx->user.closefrom = -1; sudoedit_nfiles = 0; - sudo_mode = 0; + ctx->mode = 0; for (cur = info->settings; *cur != NULL; cur++) { if (MATCHES(*cur, "closefrom=")) { p = *cur + sizeof("closefrom=") - 1; @@ -563,7 +563,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, * YP/NIS/NIS+/LDAP/etc daemon has died. * For all others we will log a proper error later on. */ - if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) { + if (ctx->mode == MODE_KILL || ctx->mode == MODE_INVALIDATE) { sudo_warnx(U_("unknown user %s"), ctx->user.name); goto bad; } @@ -721,7 +721,7 @@ sudoers_policy_store_result(struct sudoers_context *ctx, bool accepted, goto oom; } } - if (ISSET(sudo_mode, MODE_EDIT)) { + if (ISSET(ctx->mode, MODE_EDIT)) { if ((command_info[info_len++] = strdup("sudoedit=true")) == NULL) goto oom; if (sudoedit_nfiles > 0) { @@ -746,7 +746,7 @@ sudoers_policy_store_result(struct sudoers_context *ctx, bool accepted, } if ((command_info[info_len++] = sudo_new_key_val("cwd", def_runcwd)) == NULL) goto oom; - } else if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + } else if (ISSET(ctx->mode, MODE_LOGIN_SHELL)) { /* Set cwd to run user's homedir. */ if ((command_info[info_len++] = sudo_new_key_val("cwd", ctx->runas.pw->pw_dir)) == NULL) goto oom; @@ -1182,19 +1182,20 @@ sudoers_policy_check(int argc, char * const argv[], char *env_add[], char **command_infop[], char **argv_out[], char **user_env_out[], const char **errstr) { + const struct sudoers_context *ctx = sudoers_get_context(); unsigned int valid_flags = RUN_VALID_FLAGS; + unsigned int flags = MODE_RUN; struct sudoers_exec_args exec_args; int ret; debug_decl(sudoers_policy_check, SUDOERS_DEBUG_PLUGIN); - if (ISSET(sudo_mode, MODE_EDIT)) + if (ISSET(ctx->mode, MODE_EDIT)) { valid_flags = EDIT_VALID_FLAGS; - else - SET(sudo_mode, MODE_RUN); - - if ((sudo_mode & valid_flags) != sudo_mode) { + flags = 0; + } + if (!sudoers_set_mode(flags, valid_flags)) { sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"), - __func__, sudo_mode); + __func__, ctx->mode); debug_return_int(-1); } @@ -1223,13 +1224,13 @@ sudoers_policy_check(int argc, char * const argv[], char *env_add[], static int sudoers_policy_validate(const char **errstr) { + const struct sudoers_context *ctx = sudoers_get_context(); int ret; debug_decl(sudoers_policy_validate, SUDOERS_DEBUG_PLUGIN); - SET(sudo_mode, MODE_VALIDATE); - if ((sudo_mode & VALIDATE_VALID_FLAGS) != sudo_mode) { + if (!sudoers_set_mode(MODE_VALIDATE, VALIDATE_VALID_FLAGS)) { sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"), - __func__, sudo_mode); + __func__, ctx->mode); debug_return_int(-1); } @@ -1246,14 +1247,14 @@ sudoers_policy_validate(const char **errstr) static void sudoers_policy_invalidate(int unlinkit) { + const struct sudoers_context *ctx = sudoers_get_context(); debug_decl(sudoers_policy_invalidate, SUDOERS_DEBUG_PLUGIN); - SET(sudo_mode, MODE_INVALIDATE); - if ((sudo_mode & INVALIDATE_VALID_FLAGS) != sudo_mode) { + if (!sudoers_set_mode(MODE_INVALIDATE, INVALIDATE_VALID_FLAGS)) { sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"), - __func__, sudo_mode); + __func__, ctx->mode); } else { - timestamp_remove(sudoers_get_context(), unlinkit); + timestamp_remove(ctx, unlinkit); } debug_return; @@ -1263,17 +1264,13 @@ static int sudoers_policy_list(int argc, char * const argv[], int verbose, const char *list_user, const char **errstr) { + const struct sudoers_context *ctx = sudoers_get_context(); int ret; debug_decl(sudoers_policy_list, SUDOERS_DEBUG_PLUGIN); - if (argc == 0) - SET(sudo_mode, MODE_LIST); - else - SET(sudo_mode, MODE_CHECK); - - if ((sudo_mode & LIST_VALID_FLAGS) != sudo_mode) { + if (!sudoers_set_mode(argc ? MODE_CHECK : MODE_LIST, LIST_VALID_FLAGS)) { sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"), - __func__, sudo_mode); + __func__, ctx->mode); debug_return_int(-1); } diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers.c b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c index e86c2a21f..71eccaed0 100644 --- a/plugins/sudoers/regress/fuzz/fuzz_sudoers.c +++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c @@ -51,7 +51,6 @@ static const char *orig_cmnd; /* Required to link with parser. */ sudo_conv_t sudo_conv = fuzz_conversation; sudo_printf_t sudo_printf = fuzz_printf; -unsigned int sudo_mode; FILE * open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen) diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index fe5a3362a..407aef18f 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -79,8 +79,6 @@ static bool tty_present(struct sudoers_context *ctx); /* * Globals */ -unsigned int sudo_mode; - static char *prev_user; static struct sudoers_context sudoers_ctx = SUDOERS_CONTEXT_INITIALIZER; static struct sudo_nss_list *snl; @@ -176,7 +174,7 @@ sudoers_reinit_defaults(struct sudoers_context *ctx) sudoers_error_hook = logger; /* No need to check the admin flag file multiple times. */ - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) { + if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) { free(def_admin_flag); def_admin_flag = NULL; } @@ -215,9 +213,9 @@ sudoers_init(void *info, sudoers_logger_t logger, char * const envp[]) } /* Parse info from front-end. */ - sudo_mode = sudoers_policy_deserialize_info(&sudoers_ctx, info, + sudoers_ctx.mode = sudoers_policy_deserialize_info(&sudoers_ctx, info, &initial_defaults); - if (ISSET(sudo_mode, MODE_ERROR)) + if (ISSET(sudoers_ctx.mode, MODE_ERROR)) debug_return_int(-1); if (!init_vars(&sudoers_ctx, envp)) @@ -353,7 +351,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) debug_decl(sudoers_check_common, SUDOERS_DEBUG_PLUGIN); /* If given the -P option, set the "preserve_groups" flag. */ - if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) + if (ISSET(ctx->mode, MODE_PRESERVE_GROUPS)) def_preserve_groups = true; /* Find command in path and apply per-command Defaults. */ @@ -431,7 +429,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) } /* If no command line args and "shell_noargs" is not set, error out. */ - if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) { + if (ISSET(ctx->mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) { /* Not an audit event. */ ret = -2; /* usage error */ goto done; @@ -445,7 +443,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) } /* Check runas user's shell if running (or checking) a command. */ - if (ISSET(sudo_mode, MODE_RUN|MODE_CHECK)) { + if (ISSET(ctx->mode, MODE_RUN|MODE_CHECK)) { if (!check_user_shell(ctx->runas.pw)) { log_warningx(ctx, SLOG_RAW_MSG|SLOG_AUDIT, N_("invalid shell for user %s: %s"), @@ -458,8 +456,8 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) * We don't reset the environment for sudoedit or if the user * specified the -E command line flag and they have setenv privs. */ - if (ISSET(sudo_mode, MODE_EDIT) || - (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv)) + if (ISSET(ctx->mode, MODE_EDIT) || + (ISSET(ctx->mode, MODE_PRESERVE_ENV) && def_setenv)) def_env_reset = false; /* Build a new environment that avoids any nasty bits. */ @@ -467,7 +465,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) goto bad; /* Require a password if sudoers says so. */ - switch (check_user(ctx, validated, sudo_mode)) { + switch (check_user(ctx, validated, ctx->mode)) { case true: /* user authenticated successfully. */ break; @@ -515,7 +513,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) /* If run as root with SUDO_USER set, set ctx->user.pw to that user. */ /* XXX - causes confusion when root is not listed in sudoers */ - if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) { + if (ISSET(ctx->mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) { if (ctx->user.uid == 0 && strcmp(prev_user, "root") != 0) { struct passwd *pw; @@ -545,7 +543,7 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), ctx->user.cmnd, ctx->user.cmnd, ctx->user.cmnd); goto bad; } else if (cmnd_status == NOT_FOUND) { - if (ISSET(sudo_mode, MODE_CHECK)) { + if (ISSET(ctx->mode, MODE_CHECK)) { audit_failure(ctx, ctx->runas.argv, N_("%s: command not found"), ctx->runas.argv[1]); sudo_warnx(U_("%s: command not found"), ctx->runas.argv[1]); @@ -576,8 +574,8 @@ sudoers_check_common(struct sudoers_context *ctx, int pwflag) } /* If user specified env vars make sure sudoers allows it. */ - if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { - if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) { + if (ISSET(ctx->mode, MODE_RUN) && !def_setenv) { + if (ISSET(ctx->mode, MODE_PRESERVE_ENV)) { log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT, N_("user not allowed to preserve the environment")); sudo_warnx("%s", @@ -623,12 +621,12 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], if (need_reinit) { /* Was previous command intercepted? */ - if (ISSET(sudo_mode, MODE_RUN) && def_intercept) - SET(sudo_mode, MODE_POLICY_INTERCEPTED); + if (ISSET(sudoers_ctx.mode, MODE_RUN) && def_intercept) + SET(sudoers_ctx.mode, MODE_POLICY_INTERCEPTED); /* Only certain mode flags are legal for intercepted commands. */ - if (ISSET(sudo_mode, MODE_POLICY_INTERCEPTED)) - sudo_mode &= MODE_INTERCEPT_MASK; + if (ISSET(sudoers_ctx.mode, MODE_POLICY_INTERCEPTED)) + sudoers_ctx.mode &= MODE_INTERCEPT_MASK; /* Re-initialize defaults if we are called multiple times. */ if (!sudoers_reinit_defaults(&sudoers_ctx)) @@ -662,7 +660,7 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], memcpy(sudoers_ctx.runas.argv, argv, (size_t)argc * sizeof(char *)); sudoers_ctx.runas.argc = argc; sudoers_ctx.runas.argv[sudoers_ctx.runas.argc] = NULL; - if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && sudoers_ctx.runas.pw != NULL) { + if (ISSET(sudoers_ctx.mode, MODE_LOGIN_SHELL) && sudoers_ctx.runas.pw != NULL) { sudoers_ctx.runas.argv[0] = strdup(sudoers_ctx.runas.pw->pw_shell); if (sudoers_ctx.runas.argv[0] == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); @@ -703,7 +701,7 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], cmnd_umask |= sudoers_ctx.user.umask; } - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + if (ISSET(sudoers_ctx.mode, MODE_LOGIN_SHELL)) { char *p; /* Convert /bin/sh -> -sh so shell knows it is a login shell */ @@ -729,7 +727,7 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM)) /* Insert system-wide environment variables. */ - if (!read_env_file(_PATH_ENVIRONMENT, true, false)) + if (!read_env_file(&sudoers_ctx, _PATH_ENVIRONMENT, true, false)) sudo_warn("%s", _PATH_ENVIRONMENT); #endif #ifdef HAVE_LOGIN_CAP_H @@ -747,11 +745,11 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], /* Insert system-wide environment variables. */ if (def_restricted_env_file) { - if (!read_env_file(def_restricted_env_file, false, true)) + if (!read_env_file(&sudoers_ctx, def_restricted_env_file, false, true)) sudo_warn("%s", def_restricted_env_file); } if (def_env_file) { - if (!read_env_file(def_env_file, false, false)) + if (!read_env_file(&sudoers_ctx, def_env_file, false, false)) sudo_warn("%s", def_env_file); } @@ -763,7 +761,7 @@ sudoers_check_cmnd(int argc, char * const argv[], char *env_add[], } /* Note: must call audit before uid change. */ - if (ISSET(sudo_mode, MODE_EDIT)) { + if (ISSET(sudoers_ctx.mode, MODE_EDIT)) { const char *env_editor = NULL; char **edit_argv; int edit_argc; @@ -950,7 +948,7 @@ sudoers_list(int argc, char * const argv[], const char *list_user, bool verbose) goto done; pw = sudoers_ctx.runas.list_pw ? sudoers_ctx.runas.list_pw : sudoers_ctx.user.pw; - if (ISSET(sudo_mode, MODE_CHECK)) + if (ISSET(sudoers_ctx.mode, MODE_CHECK)) ret = display_cmnd(&sudoers_ctx, snl, pw, verbose); else ret = display_privs(&sudoers_ctx, snl, pw, verbose); @@ -1070,7 +1068,7 @@ set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) int ret, pivot_fds[2]; debug_decl(set_cmnd_path, SUDOERS_DEBUG_PLUGIN); - cmnd_in = ISSET(sudo_mode, MODE_CHECK) ? + cmnd_in = ISSET(ctx->mode, MODE_CHECK) ? ctx->runas.argv[1] : ctx->runas.argv[0]; free(ctx->user.cmnd_list); @@ -1115,7 +1113,7 @@ set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) } } - if (ISSET(sudo_mode, MODE_CHECK)) + if (ISSET(ctx->mode, MODE_CHECK)) ctx->user.cmnd_list = cmnd_out; else ctx->user.cmnd = cmnd_out; @@ -1165,8 +1163,8 @@ set_cmnd(struct sudoers_context *ctx) free(ctx->runas.cmnd); ctx->runas.cmnd = NULL; - if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) { - if (!ISSET(sudo_mode, MODE_EDIT)) { + if (ISSET(ctx->mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) { + if (!ISSET(ctx->mode, MODE_EDIT)) { const char *runchroot = ctx->runas.chroot; if (runchroot == NULL && def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) @@ -1185,7 +1183,7 @@ set_cmnd(struct sudoers_context *ctx) /* set ctx->user.cmnd_args */ free(ctx->user.cmnd_args); ctx->user.cmnd_args = NULL; - if (ISSET(sudo_mode, MODE_CHECK)) { + if (ISSET(ctx->mode, MODE_CHECK)) { if (ctx->runas.argc > 2) { /* Skip the command being listed in ctx->runas.argv[1]. */ ctx->user.cmnd_args = strvec_join(ctx->runas.argv + 2, ' ', NULL); @@ -1193,8 +1191,8 @@ set_cmnd(struct sudoers_context *ctx) debug_return_int(NOT_FOUND_ERROR); } } else if (ctx->runas.argc > 1) { - if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL) && - ISSET(sudo_mode, MODE_RUN)) { + if (ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL) && + ISSET(ctx->mode, MODE_RUN)) { /* * When running a command via a shell, the sudo front-end * escapes potential meta chars. We unescape non-spaces @@ -1219,11 +1217,11 @@ set_cmnd(struct sudoers_context *ctx) ctx->user.cmnd_base = sudo_basename(ctx->user.cmnd); /* Convert "sudo sudoedit" -> "sudoedit" */ - if (ISSET(sudo_mode, MODE_RUN) && strcmp(ctx->user.cmnd_base, "sudoedit") == 0) { + if (ISSET(ctx->mode, MODE_RUN) && strcmp(ctx->user.cmnd_base, "sudoedit") == 0) { char *new_cmnd; - CLR(sudo_mode, MODE_RUN); - SET(sudo_mode, MODE_EDIT); + CLR(ctx->mode, MODE_RUN); + SET(ctx->mode, MODE_EDIT); sudo_warnx("%s", U_("sudoedit doesn't need to be run via sudo")); if ((new_cmnd = strdup("sudoedit")) == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); @@ -1547,6 +1545,13 @@ tty_present(struct sudoers_context *ctx) debug_return_bool(true); } +bool +sudoers_set_mode(unsigned int flags, unsigned int mask) +{ + SET(sudoers_ctx.mode, flags); + return ((sudoers_ctx.mode & mask) == sudoers_ctx.mode); +} + const struct sudoers_context * sudoers_get_context(void) { diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 7d0e63b10..8d077a697 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -193,6 +193,7 @@ struct sudoers_context { struct sudoers_plugin_settings settings; struct sudoers_user_context user; struct sudoers_runas_context runas; + unsigned int mode; }; /* @@ -392,12 +393,12 @@ extern const struct iolog_path_escape *sudoers_iolog_path_escapes; /* env.c */ char **env_get(void); -bool env_merge(char * const envp[]); +bool env_merge(const struct sudoers_context *ctx, char * const envp[]); bool env_swap_old(void); bool env_init(char * const envp[]); bool init_envtables(void); bool insert_env_vars(char * const envp[]); -bool read_env_file(const char *path, bool overwrite, bool restricted); +bool read_env_file(const struct sudoers_context *ctx, const char *path, bool overwrite, bool restricted); bool rebuild_env(const struct sudoers_context *ctx); bool validate_env_vars(const struct sudoers_context *ctx, char * const envp[]); int sudo_setenv(const char *var, const char *val, int overwrite); @@ -432,7 +433,7 @@ int sudoers_validate_user(void); void sudoers_cleanup(void); bool sudoers_override_umask(void); const struct sudoers_context *sudoers_get_context(void); -extern unsigned int sudo_mode; +bool sudoers_set_mode(unsigned int flags, unsigned int mask); extern int sudoedit_nfiles; extern sudo_conv_t sudo_conv; extern sudo_printf_t sudo_printf; diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 21aa5991c..daefc7ede 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -81,7 +81,6 @@ static int testsudoers_query(struct sudoers_context *ctx, const struct sudo_nss */ static const char *orig_cmnd; static char *runas_group, *runas_user; -unsigned int sudo_mode = MODE_RUN; #if defined(SUDO_DEVEL) && defined(__OpenBSD__) extern char *malloc_options; @@ -131,6 +130,7 @@ main(int argc, char *argv[]) dflag = 0; grfile = pwfile = NULL; + test_ctx.mode = MODE_RUN; while ((ch = getopt(argc, argv, "+D:dg:G:h:i:L:lP:p:R:T:tu:U:v")) != -1) { switch (ch) { case 'D': @@ -174,12 +174,12 @@ main(int argc, char *argv[]) } FALLTHROUGH; case 'l': - if (sudo_mode != MODE_RUN) { + if (test_ctx.mode != MODE_RUN) { sudo_warnx( "only one of the -l or -v flags may be specified"); usage(); } - sudo_mode = MODE_LIST; + test_ctx.mode = MODE_LIST; pwflag = I_LISTPW; orig_cmnd = "list"; break; @@ -211,12 +211,12 @@ main(int argc, char *argv[]) SET(test_ctx.settings.flags, RUNAS_USER_SPECIFIED); break; case 'v': - if (sudo_mode != MODE_RUN) { + if (test_ctx.mode != MODE_RUN) { sudo_warnx( "only one of the -l or -v flags may be specified"); usage(); } - sudo_mode = MODE_VALIDATE; + test_ctx.mode = MODE_VALIDATE; pwflag = I_VERIFYPW; orig_cmnd = "validate"; break; @@ -255,8 +255,8 @@ main(int argc, char *argv[]) } argc = 0; } else { - if (argc > 2 && sudo_mode == MODE_LIST) - sudo_mode = MODE_CHECK; + if (argc > 2 && test_ctx.mode == MODE_LIST) + test_ctx.mode = MODE_CHECK; test_ctx.user.name = strdup(*argv++); if (test_ctx.user.name == NULL) { sudo_fatalx(U_("%s: %s"), __func__,