Eliminate calls to fatal()/fatalx()/log_fatal() in env.c and just

pass back a return value.
This commit is contained in:
Todd C. Miller
2014-04-30 16:57:12 -06:00
parent e45b388a37
commit 5086194c67
6 changed files with 141 additions and 67 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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