/* * environ[] array cleanup code and getenv() wappers * * No copyright is claimed. This code is in the public domain; do with * it what you wish. */ #include #include #include #ifdef HAVE_SYS_PRCTL_H #include #else #define PR_GET_DUMPABLE 3 #endif #if (!defined(HAVE_PRCTL) && defined(linux)) #include #endif #include #include #include "env.h" #ifndef HAVE_ENVIRON_DECL extern char **environ; #endif static char * const forbid[] = { "BASH_ENV=", /* GNU creeping featurism strikes again... */ "ENV=", "HOME=", "IFS=", "KRB_CONF=", "LD_", /* anything with the LD_ prefix */ "LIBPATH=", "MAIL=", "NLSPATH=", "PATH=", "SHELL=", "SHLIB_PATH=", (char *) 0 }; /* these are allowed, but with no slashes inside (to work around security problems in GNU gettext) */ static char * const noslash[] = { "LANG=", "LANGUAGE=", "LC_", /* anything with the LC_ prefix */ (char *) 0 }; void sanitize_env(void) { char **envp = environ; char * const *bad; char **cur; int last = 0; for (cur = envp; *cur; cur++) last++; for (cur = envp; *cur; cur++) { for (bad = forbid; *bad; bad++) { if (strncmp(*cur, *bad, strlen(*bad)) == 0) { last = remote_entry(envp, cur - envp, last); cur--; break; } } } for (cur = envp; *cur; cur++) { for (bad = noslash; *bad; bad++) { if (strncmp(*cur, *bad, strlen(*bad)) != 0) continue; if (!strchr(*cur, '/')) continue; /* OK */ last = remote_entry(envp, cur - envp, last); cur--; break; } } } char *safe_getenv(const char *arg) { uid_t ruid = getuid(); if (ruid != 0 || (ruid != geteuid()) || (getgid() != getegid())) return NULL; #ifdef HAVE_PRCTL if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) return NULL; #else #if (defined(linux) && defined(SYS_prctl)) if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) return NULL; #endif #endif #ifdef HAVE_SECURE_GETENV return secure_getenv(arg); #elif HAVE___SECURE_GETENV return __secure_getenv(arg); #else return getenv(arg); #endif } #ifdef TEST_PROGRAM int main(void) { char *const *bad; char copy[32]; char *p; int retval = EXIT_SUCCESS; for (bad = forbid; *bad; bad++) { strcpy(copy, *bad); p = strchr(copy, '='); if (p) *p = '\0'; setenv(copy, copy, 1); } sanitize_env(); for (bad = forbid; *bad; bad++) { strcpy(copy, *bad); p = strchr(copy, '='); if (p) *p = '\0'; p = getenv(copy); if (p) { warnx("%s was not removed", copy); retval = EXIT_FAILURE; } } return retval; } #endif