Move sudo_mode into struct sudoers_context.

This commit is contained in:
Todd C. Miller
2023-08-21 10:47:23 -06:00
parent 837da1bef0
commit 3473bf9360
12 changed files with 147 additions and 137 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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"));

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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__,