diff --git a/plugins/sudoers/auth/aix_auth.c b/plugins/sudoers/auth/aix_auth.c index e9f952698..da8abd586 100644 --- a/plugins/sudoers/auth/aix_auth.c +++ b/plugins/sudoers/auth/aix_auth.c @@ -93,7 +93,8 @@ sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth) debug_decl(sudo_aix_cleanup, SUDO_DEBUG_AUTH) /* Unset AUTHSTATE as it may not be correct for the runas user. */ - sudo_unsetenv("AUTHSTATE"); + if (sudo_unsetenv("AUTHSTATE") == -1) + debug_return_int(AUTH_FAILURE); debug_return_int(AUTH_SUCCESS); } diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 8749e2dc3..b98b0a170 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -261,7 +261,8 @@ sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth) if (pam_envp != NULL) { /* Merge pam env with user env. */ env_init(*user_envp); - env_merge(pam_envp); + if (!env_merge(pam_envp)) + status = PAM_SYSTEM_ERR; *user_envp = env_get(); env_init(NULL); efree(pam_envp); diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c index 1265c293b..d2a329ce6 100644 --- a/plugins/sudoers/env.c +++ b/plugins/sudoers/env.c @@ -285,13 +285,17 @@ sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite) size_t nsize; if (env.env_size > SIZE_MAX - 128) { - fatalx_nodebug(U_("internal error, %s overflow"), + warningx_nodebug(U_("internal error, %s overflow"), "sudo_putenv_nodebug"); + errno = EOVERFLOW; + return -1; } nsize = env.env_size + 128; if (nsize > SIZE_MAX / sizeof(char *)) { - fatalx_nodebug(U_("internal error, %s overflow"), + warningx_nodebug(U_("internal error, %s overflow"), "sudo_putenv_nodebug"); + errno = EOVERFLOW; + return -1; } nenvp = realloc(env.envp, nsize * sizeof(char *)); if (nenvp == NULL) { @@ -364,9 +368,8 @@ sudo_putenv(char *str, bool dupcheck, bool overwrite) if (rval == -1) { #ifdef ENV_DEBUG if (env.envp[env.env_len] != NULL) - fatalx(U_("sudo_putenv: corrupted envp, length mismatch")); + warningx(U_("sudo_putenv: corrupted envp, length mismatch")); #endif - fatal(NULL); } debug_return_int(rval); } @@ -381,7 +384,7 @@ sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite) { char *estring; size_t esize; - int rval; + int rval = -1; debug_decl(sudo_setenv2, SUDO_DEBUG_ENV) esize = strlen(var) + 1 + strlen(val) + 1; @@ -392,9 +395,11 @@ sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite) strlcat(estring, "=", esize) >= esize || strlcat(estring, val, esize) >= esize) { - fatalx(U_("internal error, %s overflow"), __func__); + warningx(U_("internal error, %s overflow"), __func__); + errno = EOVERFLOW; + } else { + rval = sudo_putenv(estring, dupcheck, overwrite); } - rval = sudo_putenv(estring, dupcheck, overwrite); if (rval == -1) efree(estring); debug_return_int(rval); @@ -684,17 +689,23 @@ env_should_keep(const char *var) * Merge another environment with our private copy. * Only overwrite an existing variable if it is not * being preserved from the user's environment. + * Returns true on success or false on failure. */ -void +bool env_merge(char * const envp[]) { char * const *ep; + bool rval = true; debug_decl(env_merge, SUDO_DEBUG_ENV) - for (ep = envp; *ep != NULL; ep++) - sudo_putenv(*ep, true, !env_should_keep(*ep)); - - debug_return; + for (ep = envp; *ep != NULL; ep++) { + if (sudo_putenv(*ep, true, !env_should_keep(*ep)) == -1) { + /* XXX cannot undo on failure */ + rval = false; + break; + } + } + debug_return_bool(rval); } static void @@ -738,14 +749,16 @@ env_update_didvar(const char *ep, unsigned int *didvar) * Build a new environment and ether clear potentially dangerous * variables from the old one or start with a clean slate. * Also adds sudo-specific variables (SUDO_*). + * Returns true on success or false on failure. */ -void +bool rebuild_env(void) { char **old_envp, **ep, *cp, *ps1; char idbuf[MAX_UID_T_LEN + 1]; unsigned int didvar; bool reset_home = false; + debug_decl(rebuild_env, SUDO_DEBUG_ENV) /* * Either clean out the environment or reset to a safe default. @@ -821,7 +834,8 @@ rebuild_env(void) if (keepit) { /* Preserve variable. */ - sudo_putenv(*ep, false, false); + if (sudo_putenv(*ep, false, false) == -1) + goto bad; env_update_didvar(*ep, &didvar); } } @@ -869,7 +883,10 @@ rebuild_env(void) easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name); else easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name); - sudo_putenv(cp, ISSET(didvar, DID_MAIL), true); + if (sudo_putenv(cp, ISSET(didvar, DID_MAIL), true) == -1) { + free(cp); + goto bad; + } } } else { /* @@ -891,13 +908,15 @@ rebuild_env(void) SET(didvar, DID_PATH); else if (strncmp(*ep, "TERM=", 5) == 0) SET(didvar, DID_TERM); - sudo_putenv(*ep, false, false); + if (sudo_putenv(*ep, false, false) == -1) + goto bad; } } } /* Replace the PATH envariable with a secure one? */ if (def_secure_path && !user_is_exempt()) { - sudo_setenv2("PATH", def_secure_path, true, true); + if (sudo_setenv2("PATH", def_secure_path, true, true) == -1) + goto bad; SET(didvar, DID_PATH); } @@ -921,63 +940,94 @@ rebuild_env(void) sudo_setenv2("HOME", runas_pw->pw_dir, true, true); /* Provide default values for $TERM and $PATH if they are not set. */ - if (!ISSET(didvar, DID_TERM)) - sudo_putenv("TERM=unknown", false, false); - if (!ISSET(didvar, DID_PATH)) - sudo_setenv2("PATH", _PATH_STDPATH, false, true); + if (!ISSET(didvar, DID_TERM)) { + if (sudo_putenv("TERM=unknown", false, false) == -1) + goto bad; + } + if (!ISSET(didvar, DID_PATH)) { + if (sudo_setenv2("PATH", _PATH_STDPATH, false, true) == -1) + goto bad; + } /* Set PS1 if SUDO_PS1 is set. */ - if (ps1 != NULL) - sudo_putenv(ps1, true, true); + if (ps1 != NULL) { + if (sudo_putenv(ps1, true, true) == -1) + goto bad; + } /* Add the SUDO_COMMAND envariable (cmnd + args). */ if (user_args) { - easprintf(&cp, "%s %s", user_cmnd, user_args); - sudo_setenv2("SUDO_COMMAND", cp, true, true); - efree(cp); + easprintf(&cp, "SUDO_COMMAND=%s %s", user_cmnd, user_args); + if (sudo_putenv(cp, true, true) == -1) { + efree(cp); + goto bad; + } } else { - sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true); + if (sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true) == -1) + goto bad; } /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ - sudo_setenv2("SUDO_USER", user_name, true, true); + if (sudo_setenv2("SUDO_USER", user_name, true, true) == -1) + goto bad; snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid); - sudo_setenv2("SUDO_UID", idbuf, true, true); + if (sudo_setenv2("SUDO_UID", idbuf, true, true) == -1) + goto bad; snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid); - sudo_setenv2("SUDO_GID", idbuf, true, true); + if (sudo_setenv2("SUDO_GID", idbuf, true, true) == -1) + goto bad; /* Free old environment. */ efree(old_envp); + + debug_return_bool(true); + +bad: + debug_return_bool(false); } -void +/* + * Insert all environment variables in envp into the private copy + * of the environment. + * Returns true on success or false on failure. + */ +bool insert_env_vars(char * const envp[]) { char * const *ep; - - if (envp == NULL) - return; + bool rval = true; + debug_decl(insert_env_vars, SUDO_DEBUG_ENV) /* Add user-specified environment variables. */ - for (ep = envp; *ep != NULL; ep++) - sudo_putenv(*ep, true, true); + if (envp != NULL) { + for (ep = envp; *ep != NULL; ep++) { + /* XXX - no undo on failure */ + if (sudo_putenv(*ep, true, true) == -1) { + rval = false; + break; + } + } + } + debug_return_bool(rval); } /* * Validate the list of environment variables passed in on the command * line against env_delete, env_check, and env_keep. - * Calls log_fatal() if any specified variables are not allowed. + * Calls log_warning() if any specified variables are not allowed. + * Returns true if allowed, else false. */ -void +bool validate_env_vars(char * const env_vars[]) { char * const *ep; char *eq, *bad = NULL; size_t len, blen = 0, bsize = 0; - bool okvar; + bool okvar, rval = true; + debug_decl(validate_env_vars, SUDO_DEBUG_ENV) if (env_vars == NULL) - return; + debug_return_bool(true); /* nothing to do */ /* Add user-specified environment variables. */ for (ep = env_vars; *ep != NULL; ep++) { @@ -1011,11 +1061,12 @@ validate_env_vars(char * const env_vars[]) if (bad != NULL) { bad[blen - 2] = '\0'; /* remove trailing ", " */ /* XXX - audit? */ - log_fatal(NO_MAIL, + log_warning(NO_MAIL, N_("sorry, you are not allowed to set the following environment variables: %s"), bad); - /* NOTREACHED */ efree(bad); + rval = false; } + debug_return_bool(rval); } /* @@ -1028,15 +1079,20 @@ validate_env_vars(char * const env_vars[]) * Invalid lines, blank lines, or lines consisting solely of a comment * character are skipped. */ -void +bool read_env_file(const char *path, int overwrite) { FILE *fp; + bool rval = true; char *cp, *var, *val, *line = NULL; size_t var_len, val_len, linesize = 0; + debug_decl(read_env_file, SUDO_DEBUG_ENV) - if ((fp = fopen(path, "r")) == NULL) - return; + if ((fp = fopen(path, "r")) == NULL) { + if (errno != ENOENT) + rval = false; + debug_return_bool(rval); + } while (sudo_parseln(&line, &linesize, NULL, fp) != -1) { /* Skip blank or comment lines */ @@ -1070,10 +1126,16 @@ read_env_file(const char *path, int overwrite) memcpy(cp, var, var_len + 1); /* includes '=' */ memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */ - sudo_putenv(cp, true, overwrite); + if (sudo_putenv(cp, true, overwrite) == -1) { + /* XXX - no undo on failure */ + rval = false; + break; + } } free(line); fclose(fp); + + debug_return_bool(rval); } void diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index fcf6f60dc..3fbbbdd23 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -2082,10 +2082,13 @@ sudo_set_krb5_ccache_name(const char *name, const char **old_name) if (old_name != NULL) *old_name = sudo_getenv("KRB5CCNAME"); } - if (name != NULL && *name != '\0') - sudo_setenv("KRB5CCNAME", name, true); - else - sudo_unsetenv("KRB5CCNAME"); + if (name != NULL && *name != '\0') { + if (sudo_setenv("KRB5CCNAME", name, true) == -1) + rc = -1; + } else { + if (sudo_unsetenv("KRB5CCNAME") == -1) + rc = -1; + } debug_return_int(rc); } @@ -2500,8 +2503,8 @@ sudo_ldap_open(struct sudo_nss *nss) /* Prevent reading of user ldaprc and system defaults. */ if (sudo_getenv("LDAPNOINIT") == NULL) { - ldapnoinit = true; - sudo_setenv("LDAPNOINIT", "1", true); + if (sudo_setenv("LDAPNOINIT", "1", true) == 0) + ldapnoinit = true; } /* Set global LDAP options */ @@ -2533,7 +2536,7 @@ sudo_ldap_open(struct sudo_nss *nss) goto done; if (ldapnoinit) - sudo_unsetenv("LDAPNOINIT"); + (void) sudo_unsetenv("LDAPNOINIT"); if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { #if defined(HAVE_LDAP_START_TLS_S) diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 4f824154e..2796d58df 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -364,7 +364,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], def_env_reset = false; /* Build a new environment that avoids any nasty bits. */ - rebuild_env(); + if (!rebuild_env()) + goto bad; /* Require a password if sudoers says so. */ rval = check_user(validated, sudo_mode); @@ -421,8 +422,10 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], /* XXX - audit? */ warningx(U_("sorry, you are not allowed to preserve the environment")); goto bad; - } else - validate_env_vars(sudo_user.env_vars); + } else { + if (!validate_env_vars(sudo_user.env_vars)) + goto bad; + } } if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) { @@ -489,7 +492,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM)) /* Insert system-wide environment variables. */ - read_env_file(_PATH_ENVIRONMENT, true); + if (!read_env_file(_PATH_ENVIRONMENT, true)) + warning("%s", _PATH_ENVIRONMENT); #endif #ifdef HAVE_LOGIN_CAP_H /* Set environment based on login class. */ @@ -504,11 +508,14 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], } /* Insert system-wide environment variables. */ - if (def_env_file) - read_env_file(def_env_file, false); + if (def_env_file) { + if (!read_env_file(def_env_file, false)) + warning("%s", def_env_file); + } /* Insert user-specified environment variables. */ - insert_env_vars(sudo_user.env_vars); + if (!insert_env_vars(sudo_user.env_vars)) + goto bad; if (ISSET(sudo_mode, MODE_EDIT)) { efree(safe_cmnd); diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index d7fdf162d..59be378b6 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -336,13 +336,13 @@ char *expand_iolog_path(const char *prefix, const char *dir, const char *file, /* env.c */ char **env_get(void); -void env_merge(char * const envp[]); +bool env_merge(char * const envp[]); void env_init(char * const envp[]); void init_envtables(void); -void insert_env_vars(char * const envp[]); -void read_env_file(const char *, int); -void rebuild_env(void); -void validate_env_vars(char * const envp[]); +bool insert_env_vars(char * const envp[]); +bool read_env_file(const char *, int); +bool rebuild_env(void); +bool validate_env_vars(char * const envp[]); int sudo_setenv(const char *var, const char *val, int overwrite); int sudo_unsetenv(const char *var); char *sudo_getenv(const char *name);