version 1.1.1.3, 2012/10/09 09:29:52
|
version 1.1.1.6, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2000-2005, 2007-2011 | * Copyright (c) 2000-2005, 2007-2013 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
Line 22
|
Line 22
|
#include <config.h> |
#include <config.h> |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
Line 286 sudo_putenv_nodebug(char *str, bool dupcheck, bool ove
|
Line 285 sudo_putenv_nodebug(char *str, bool dupcheck, bool ove
|
size_t nsize; |
size_t nsize; |
|
|
if (env.env_size > SIZE_MAX - 128) { |
if (env.env_size > SIZE_MAX - 128) { |
errorx2(1, _("internal error, %s overflow"), | fatalx_nodebug(U_("internal error, %s overflow"), |
"sudo_putenv_nodebug()"); |
"sudo_putenv_nodebug()"); |
} |
} |
nsize = env.env_size + 128; |
nsize = env.env_size + 128; |
if (nsize > SIZE_MAX / sizeof(char *)) { |
if (nsize > SIZE_MAX / sizeof(char *)) { |
errorx2(1, _("internal error, %s overflow"), | fatalx_nodebug(U_("internal error, %s overflow"), |
"sudo_putenv_nodebug()"); |
"sudo_putenv_nodebug()"); |
} |
} |
nenvp = realloc(env.envp, nsize * sizeof(char *)); |
nenvp = realloc(env.envp, nsize * sizeof(char *)); |
Line 365 sudo_putenv(char *str, bool dupcheck, bool overwrite)
|
Line 364 sudo_putenv(char *str, bool dupcheck, bool overwrite)
|
if (rval == -1) { |
if (rval == -1) { |
#ifdef ENV_DEBUG |
#ifdef ENV_DEBUG |
if (env.envp[env.env_len] != NULL) |
if (env.envp[env.env_len] != NULL) |
errorx(1, _("sudo_putenv: corrupted envp, length mismatch")); | fatalx(U_("sudo_putenv: corrupted envp, length mismatch")); |
#endif |
#endif |
errorx(1, _("unable to allocate memory")); | fatal(NULL); |
} |
} |
debug_return_int(rval); |
debug_return_int(rval); |
} |
} |
Line 393 sudo_setenv2(const char *var, const char *val, bool du
|
Line 392 sudo_setenv2(const char *var, const char *val, bool du
|
strlcat(estring, "=", esize) >= esize || |
strlcat(estring, "=", esize) >= esize || |
strlcat(estring, val, esize) >= esize) { |
strlcat(estring, val, esize) >= esize) { |
|
|
errorx(1, _("internal error, %s overflow"), "sudo_setenv2()"); | fatalx(U_("internal error, %s overflow"), "sudo_setenv2()"); |
} |
} |
rval = sudo_putenv(estring, dupcheck, overwrite); |
rval = sudo_putenv(estring, dupcheck, overwrite); |
if (rval == -1) |
if (rval == -1) |
Line 403 sudo_setenv2(const char *var, const char *val, bool du
|
Line 402 sudo_setenv2(const char *var, const char *val, bool du
|
|
|
/* |
/* |
* Similar to setenv(3) but operates on a private copy of the environment. |
* Similar to setenv(3) but operates on a private copy of the environment. |
|
*/ |
|
int |
|
sudo_setenv(const char *var, const char *val, int overwrite) |
|
{ |
|
return sudo_setenv2(var, val, true, (bool)overwrite); |
|
} |
|
|
|
/* |
|
* Similar to setenv(3) but operates on a private copy of the environment. |
* Does not include warnings or debugging to avoid recursive calls. |
* Does not include warnings or debugging to avoid recursive calls. |
*/ |
*/ |
static int |
static int |
sudo_setenv_nodebug(const char *var, const char *val, int overwrite) |
sudo_setenv_nodebug(const char *var, const char *val, int overwrite) |
{ |
{ |
char *estring; | char *ep, *estring = NULL; |
| const char *cp; |
size_t esize; |
size_t esize; |
int rval = -1; |
int rval = -1; |
|
|
esize = strlen(var) + 1 + strlen(val) + 1; | if (var == NULL || *var == '\0') { |
if ((estring = malloc(esize)) == NULL) { | errno = EINVAL; |
errno = ENOMEM; | |
goto done; |
goto done; |
} |
} |
|
|
/* Build environment string and insert it. */ | /* |
if (strlcpy(estring, var, esize) >= esize || | * POSIX says a var name with '=' is an error but BSD |
strlcat(estring, "=", esize) >= esize || | * just ignores the '=' and anything after it. |
strlcat(estring, val, esize) >= esize) { | */ |
| for (cp = var; *cp && *cp != '='; cp++) |
| ; |
| esize = (size_t)(cp - var) + 2; |
| if (val) { |
| esize += strlen(val); /* glibc treats a NULL val as "" */ |
| } |
|
|
errno = EINVAL; | /* Allocate and fill in estring. */ |
| if ((estring = ep = malloc(esize)) == NULL) { |
| errno = ENOMEM; |
goto done; |
goto done; |
} |
} |
|
for (cp = var; *cp && *cp != '='; cp++) |
|
*ep++ = *cp; |
|
*ep++ = '='; |
|
if (val) { |
|
for (cp = val; *cp; cp++) |
|
*ep++ = *cp; |
|
} |
|
*ep = '\0'; |
|
|
rval = sudo_putenv_nodebug(estring, true, overwrite); |
rval = sudo_putenv_nodebug(estring, true, overwrite); |
done: |
done: |
if (rval == -1) |
if (rval == -1) |
efree(estring); | free(estring); |
return rval; |
return rval; |
} |
} |
|
|
/* |
/* |
* Similar to setenv(3) but operates on a private copy of the environment. |
|
*/ |
|
int |
|
sudo_setenv(const char *var, const char *val, int overwrite) |
|
{ |
|
int rval; |
|
debug_decl(sudo_setenv, SUDO_DEBUG_ENV) |
|
|
|
rval = sudo_setenv_nodebug(var, val, overwrite); |
|
if (rval == -1) { |
|
if (errno == EINVAL) |
|
errorx(1, _("internal error, %s overflow"), "sudo_setenv()"); |
|
errorx(1, _("unable to allocate memory")); |
|
} |
|
debug_return_int(rval); |
|
} |
|
|
|
/* |
|
* Similar to unsetenv(3) but operates on a private copy of the environment. |
* Similar to unsetenv(3) but operates on a private copy of the environment. |
* Does not include warnings or debugging to avoid recursive calls. |
* Does not include warnings or debugging to avoid recursive calls. |
*/ |
*/ |
Line 538 sudo_getenv(const char *name)
|
Line 545 sudo_getenv(const char *name)
|
} |
} |
|
|
/* |
/* |
* Merge another environment with our private copy. |
|
*/ |
|
void |
|
env_merge(char * const envp[], bool overwrite) |
|
{ |
|
char * const *ep; |
|
debug_decl(env_merge, SUDO_DEBUG_ENV) |
|
|
|
for (ep = envp; *ep != NULL; ep++) |
|
sudo_putenv(*ep, true, overwrite); |
|
|
|
debug_return; |
|
} |
|
|
|
/* |
|
* Check the env_delete blacklist. |
* Check the env_delete blacklist. |
* Returns true if the variable was found, else false. |
* Returns true if the variable was found, else false. |
*/ |
*/ |
Line 566 matches_env_delete(const char *var)
|
Line 558 matches_env_delete(const char *var)
|
debug_decl(matches_env_delete, SUDO_DEBUG_ENV) |
debug_decl(matches_env_delete, SUDO_DEBUG_ENV) |
|
|
/* Skip anything listed in env_delete. */ |
/* Skip anything listed in env_delete. */ |
for (cur = def_env_delete; cur; cur = cur->next) { | SLIST_FOREACH(cur, &def_env_delete, entries) { |
len = strlen(cur->value); |
len = strlen(cur->value); |
/* Deal with '*' wildcard */ |
/* Deal with '*' wildcard */ |
if (cur->value[len - 1] == '*') { |
if (cur->value[len - 1] == '*') { |
Line 597 matches_env_check(const char *var)
|
Line 589 matches_env_check(const char *var)
|
int keepit = -1; |
int keepit = -1; |
debug_decl(matches_env_check, SUDO_DEBUG_ENV) |
debug_decl(matches_env_check, SUDO_DEBUG_ENV) |
|
|
for (cur = def_env_check; cur; cur = cur->next) { | SLIST_FOREACH(cur, &def_env_check, entries) { |
len = strlen(cur->value); |
len = strlen(cur->value); |
/* Deal with '*' wildcard */ |
/* Deal with '*' wildcard */ |
if (cur->value[len - 1] == '*') { |
if (cur->value[len - 1] == '*') { |
Line 632 matches_env_keep(const char *var)
|
Line 624 matches_env_keep(const char *var)
|
goto done; |
goto done; |
} |
} |
|
|
for (cur = def_env_keep; cur; cur = cur->next) { | SLIST_FOREACH(cur, &def_env_keep, entries) { |
len = strlen(cur->value); |
len = strlen(cur->value); |
/* Deal with '*' wildcard */ |
/* Deal with '*' wildcard */ |
if (cur->value[len - 1] == '*') { |
if (cur->value[len - 1] == '*') { |
Line 688 env_should_keep(const char *var)
|
Line 680 env_should_keep(const char *var)
|
debug_return_bool(keepit == true); |
debug_return_bool(keepit == true); |
} |
} |
|
|
|
/* |
|
* Merge another environment with our private copy. |
|
* Only overwrite an existing variable if it is not |
|
* being preserved from the user's environment. |
|
*/ |
|
void |
|
env_merge(char * const envp[]) |
|
{ |
|
char * const *ep; |
|
debug_decl(env_merge, SUDO_DEBUG_ENV) |
|
|
|
for (ep = envp; *ep != NULL; ep++) |
|
sudo_putenv(*ep, true, !env_should_keep(*ep)); |
|
|
|
debug_return; |
|
} |
|
|
static void |
static void |
env_update_didvar(const char *ep, unsigned int *didvar) |
env_update_didvar(const char *ep, unsigned int *didvar) |
{ |
{ |
Line 1002 validate_env_vars(char * const env_vars[])
|
Line 1011 validate_env_vars(char * const env_vars[])
|
if (bad != NULL) { |
if (bad != NULL) { |
bad[blen - 2] = '\0'; /* remove trailing ", " */ |
bad[blen - 2] = '\0'; /* remove trailing ", " */ |
log_fatal(NO_MAIL, |
log_fatal(NO_MAIL, |
_("sorry, you are not allowed to set the following environment variables: %s"), bad); | N_("sorry, you are not allowed to set the following environment variables: %s"), bad); |
/* NOTREACHED */ |
/* NOTREACHED */ |
efree(bad); |
efree(bad); |
} |
} |
Line 1022 void
|
Line 1031 void
|
read_env_file(const char *path, int overwrite) |
read_env_file(const char *path, int overwrite) |
{ |
{ |
FILE *fp; |
FILE *fp; |
char *cp, *var, *val; | char *cp, *var, *val, *line = NULL; |
size_t var_len, val_len; | size_t var_len, val_len, linesize = 0; |
|
|
if ((fp = fopen(path, "r")) == NULL) |
if ((fp = fopen(path, "r")) == NULL) |
return; |
return; |
|
|
while ((var = sudo_parseln(fp)) != NULL) { | while (sudo_parseln(&line, &linesize, NULL, fp) != -1) { |
/* Skip blank or comment lines */ |
/* Skip blank or comment lines */ |
if (*var == '\0') | if (*(var = line) == '\0') |
continue; |
continue; |
|
|
/* Skip optional "export " */ |
/* Skip optional "export " */ |
Line 1062 read_env_file(const char *path, int overwrite)
|
Line 1071 read_env_file(const char *path, int overwrite)
|
|
|
sudo_putenv(cp, true, overwrite); |
sudo_putenv(cp, true, overwrite); |
} |
} |
|
free(line); |
fclose(fp); |
fclose(fp); |
} |
} |
|
|
Line 1075 init_envtables(void)
|
Line 1085 init_envtables(void)
|
for (p = initial_badenv_table; *p; p++) { |
for (p = initial_badenv_table; *p; p++) { |
cur = ecalloc(1, sizeof(struct list_member)); |
cur = ecalloc(1, sizeof(struct list_member)); |
cur->value = estrdup(*p); |
cur->value = estrdup(*p); |
cur->next = def_env_delete; | SLIST_INSERT_HEAD(&def_env_delete, cur, entries); |
def_env_delete = cur; | |
} |
} |
|
|
/* Fill in the "env_check" list. */ |
/* Fill in the "env_check" list. */ |
for (p = initial_checkenv_table; *p; p++) { |
for (p = initial_checkenv_table; *p; p++) { |
cur = ecalloc(1, sizeof(struct list_member)); |
cur = ecalloc(1, sizeof(struct list_member)); |
cur->value = estrdup(*p); |
cur->value = estrdup(*p); |
cur->next = def_env_check; | SLIST_INSERT_HEAD(&def_env_check, cur, entries); |
def_env_check = cur; | |
} |
} |
|
|
/* Fill in the "env_keep" list. */ |
/* Fill in the "env_keep" list. */ |
for (p = initial_keepenv_table; *p; p++) { |
for (p = initial_keepenv_table; *p; p++) { |
cur = ecalloc(1, sizeof(struct list_member)); |
cur = ecalloc(1, sizeof(struct list_member)); |
cur->value = estrdup(*p); |
cur->value = estrdup(*p); |
cur->next = def_env_keep; | SLIST_INSERT_HEAD(&def_env_keep, cur, entries); |
def_env_keep = cur; | |
} |
} |
} |
} |
|
|
Line 1105 sudoers_hook_getenv(const char *name, char **value, vo
|
Line 1112 sudoers_hook_getenv(const char *name, char **value, vo
|
return SUDO_HOOK_RET_NEXT; |
return SUDO_HOOK_RET_NEXT; |
|
|
in_progress = true; |
in_progress = true; |
|
|
|
/* Hack to make GNU gettext() find the sudoers locale when needed. */ |
|
if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) { |
|
if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) { |
|
*value = NULL; |
|
goto done; |
|
} |
|
if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) { |
|
*value = def_sudoers_locale; |
|
goto done; |
|
} |
|
} |
|
|
*value = sudo_getenv_nodebug(name); |
*value = sudo_getenv_nodebug(name); |
|
done: |
in_progress = false; |
in_progress = false; |
return SUDO_HOOK_RET_STOP; |
return SUDO_HOOK_RET_STOP; |
} |
} |