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