diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index e13663ceafb8..de6aa63dbc62 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -6,9 +6,9 @@ SHLIB_MAJOR= 4 SHLIBDIR?= /lib CFLAGS+=-DLIBC_SCCS -I${.CURDIR} -I${.CURDIR}/../libc/gen/ CFLAGS+=-DINET6 -SRCS= _secure_path.c auth.c fparseln.c login.c login_auth.c \ - login_cap.c login_class.c login_crypt.c login_ok.c login_times.c \ - login_tty.c logout.c logwtmp.c property.c pty.c \ +SRCS= _secure_path.c auth.c clean_environment.c fparseln.c login.c \ + login_auth.c login_cap.c login_class.c login_crypt.c login_ok.c \ + login_times.c login_tty.c logout.c logwtmp.c property.c pty.c \ pw_util.c realhostname.c stub.c \ trimdomain.c uucplock.c INCS= libutil.h login_cap.h @@ -16,7 +16,7 @@ INCS= libutil.h login_cap.h MAN+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \ login_cap.3 login_class.3 login_times.3 login_ok.3 \ _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \ - realhostname_sa.3 trimdomain.3 fparseln.3 + realhostname_sa.3 trimdomain.3 fparseln.3 clean_environment.3 MAN+= login.conf.5 auth.conf.5 MLINKS+= property.3 properties_read.3 property.3 properties_free.3 MLINKS+= property.3 property_find.3 diff --git a/lib/libutil/clean_environment.3 b/lib/libutil/clean_environment.3 new file mode 100644 index 000000000000..b99ebf334780 --- /dev/null +++ b/lib/libutil/clean_environment.3 @@ -0,0 +1,86 @@ +.\" Copyright (c) 2003 Tim Kientzle +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 1, 2004 +.Os +.Dt CLEAN_ENVIRONMENT 3 +.Sh NAME +.Nm clean_environment +.Nd sanitize environment variables +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In libutil.h +.Ft void +.Fn clean_environment "const char * const *whitelist" "const char * const *extra_whitelist" +.Sh DESCRIPTION +The +.Fn clean_environment +function removes unsafe environment variables from the current +process environment. +It scans the current environment and discards any environment variable +that does not occur in one of the two NULL-terminated lists. +.Pp +If the first argument is +.Dv NULL , +a built-in default whitelist will be used. +Most callers will use +.Dv NULL +for both arguments to obtain the default environment screening. +Callers who need to make minor adjustments to the built-in +whitelist can set the first argument to +.Dv NULL +and use the second argument to, in effect, +add elements to the built-in whitelist. +.Sh EXAMPLES +The first example illustrates the typical usage. +In this case, the default built-in environment screen +will be used, which removes all environment variables +that are not on the built-in whitelist. +.Bd -literal -offset indent + clean_environment(NULL, NULL); +.Ed +.Pp +The following example applies the default environment screens +except that the environment variables +.Cm MYCUSTOM +and +.Cm MYCUSTOM2 +will also be kept and the +.Cm TERM +and +.Cm TERMCAP +environment variables will be removed. +.Bd -literal -offset indent + const char *keep[] = { "MYCUSTOM", "MYCUSTOM2", NULL }; + const char *remove[] = { "TERM", "TERMCAP", NULL }; + + clean_environment(NULL, keep); + for (p = remove; *p != NULL; p++) + unsetenv(*p); +.Ed +.Sh SEE ALSO +.Xr unsetenv 3 diff --git a/lib/libutil/clean_environment.c b/lib/libutil/clean_environment.c new file mode 100644 index 000000000000..068e412365f4 --- /dev/null +++ b/lib/libutil/clean_environment.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2004 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "libutil.h" + +static int env_var_in_list(const char * const *list, char *var, size_t len); + + +/* + * Default whitelist of "known safe" environment variables. + */ +static const char *default_whitelist[] = { + /* List from SUS "Environment Variables" Appendix */ + "ARFLAGS", "CC", "CDPATH", "CFLAGS", "CHARSET", "COLUMNS", + "DATEMSK", "DEAD", "EDITOR", "ENV", "EXINIT", "FC", "FCEDIT", + "FFLAGS", "GET", "GFLAGS", "HISTFILE", "HISTORY", "HISTSIZE", + "HOME", "IFS", "LANG", "LC_ALL", "LC_COLLATE", "LC_CTYPE", + "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LDFLAGS", + "LEX", "LFLAGS", "LINENO", "LINES", "LISTER", "LOGNAME", "LPDEST", + "MAIL", "MAILCHECK", "MAILER", "MAILPATH", "MAILRC", "MAKEFLAGS", + "MAKESHELL", "MANPATH", "MBOX", "MORE", "MSGVERB", "NLSPATH", + "NPROC", "OLDPWD", "OPTARG", "OPTERR", "OPTIND", "PAGER", "PATH", + "PPID", "PRINTER", "PROCLANG", "PROJECTDIR", "PS1", "PS2", "PS3", + "PS4", "PWD", "RANDOM", "SECONDS", "SHELL", "TERM", "TERMCAP", + "TERMINFO", "TMPDIR", "TZ", "USER", "VISUAL", "YACC", "YFLAGS", + + /* Additional Environment Variables */ + "KRB5CCNAME", "LOGIN", "MAILDIR", "SSH_AGENT_PID", "SSH_AUTH_SOCK", + + /* Terminating NULL */ + NULL +}; + +static int +env_var_in_list(const char * const *list, char *var, size_t len) +{ + if (list == NULL) + return (0); + + while (*list != NULL) { + if (strncmp(var, *list, len) == 0 && + len == strlen(*list)) + return (1); + list++; + } + return (0); +} + + +/* + * Scrub the environment by applying a "whitelist" of safe variables + * and a "blacklist" of known dangerous variables. Each environment + * variable is examined and is retained only if it appears in a whitelist + * and does not appear in the blacklist. + * + * If the first argument is NULL, a built-in whitelist will be used. + * The second and third arguments allow clients to adjust the built-in + * whitelist without having to replicate it. + * + */ +void +clean_environment(const char * const *whitelist, + const char * const *extra_whitelist) +{ + extern char **environ; + char *p, **new, **old; + int len; + int safe; + + old = environ; + new = environ; + + if (whitelist == NULL) + whitelist = default_whitelist; + + while (*old != NULL) { + safe = 0; + p = strchr(*old, '='); + if (p != NULL) + len = p - *old; + else + len = strlen(*old); + + if (env_var_in_list(whitelist, *old, len) || + env_var_in_list(extra_whitelist, *old, len)) + *new++ = *old; + + old++; + } + while (*new != NULL) + *new++ = NULL; + +}