A new command line option, -W or --accept-env, has been added to
allow administrators to effectively extend the default whitelist
with an additional environment variable that may be accepted from
a client.
This is useful for systems that require specific variables to be
passed to the login process, which would otherwise be dropped due
to a lack of presence in the default environment variable whitelist.
This implementation uses a static array of 16 string pointers to
store administrator-defined environment variable patterns, which
eliminates the need to deal with heap memory management.
* telnetd/telnetd.h: Add prototype for add_allowed_env_pattern().
* telnetd/telnetd.c (argp_options): Add the "W"/"accept-env" option.
(parse_opt): Handle the 'W' case by calling add_allowed_env_pattern().
* telnetd/utility.c: Declare user_env_vars storage and extend
is_env_var_allowed() to check user patterns first.
---
telnetd/telnetd.c | 6 ++++++
telnetd/telnetd.h | 1 +
telnetd/utility.c | 26 ++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/telnetd/telnetd.c b/telnetd/telnetd.c
index affa2c96..12001caa 100644
--- a/telnetd/telnetd.c
+++ b/telnetd/telnetd.c
@@ -117,6 +117,8 @@ static struct argp_option argp_options[] = {
"do not print host information before login has been completed", GRID},
{"linemode", 'l', "MODE", OPTION_ARG_OPTIONAL,
"set line mode", GRID},
+ {"accept-env", 'W', "PATTERN", 0,
+ "specify an additional environment variable pattern to accept", GRID},
{"no-keepalive", 'n', NULL, 0,
"disable TCP keep-alive", GRID},
{"reverse-lookup", 'U', NULL, 0,
@@ -180,6 +182,10 @@ parse_opt (int key, char *arg, struct argp_state *state
MAYBE_UNUSED)
reverse_lookup = 1;
break;
+ case 'W':
+ add_allowed_env_pattern (arg);
+ break;
+
#ifdef AUTHENTICATION
case 'X':
auth_disable_name (arg);
diff --git a/telnetd/telnetd.h b/telnetd/telnetd.h
index c9914a2e..32a31b6b 100644
--- a/telnetd/telnetd.h
+++ b/telnetd/telnetd.h
@@ -318,6 +318,7 @@ extern void tty_tspeed (int);
extern char *expand_line (const char *fmt);
extern void exorcise_env (void);
extern int is_env_var_allowed (const char *var);
+extern void add_allowed_env_pattern (const char *pattern);
/* FIXME */
diff --git a/telnetd/utility.c b/telnetd/utility.c
index 590f545a..86b9a041 100644
--- a/telnetd/utility.c
+++ b/telnetd/utility.c
@@ -75,6 +75,10 @@ static int pcc;
extern int not42;
+#define MAX_USER_ENV_VARS 16
+static const char *user_env_vars[MAX_USER_ENV_VARS];
+static size_t user_env_var_count = 0;
+
/* A default whitelist for environment variables. */
static const char *allowed_env_vars[] = {
"USER",
@@ -89,6 +93,13 @@ int
is_env_var_allowed (const char *var)
{
const char **p;
+ size_t i;
+
+ for (i = 0; i < user_env_var_count; i++)
+ {
+ if (fnmatch (user_env_vars[i], var, FNM_NOESCAPE) == 0)
+ return 1;
+ }
for (p = allowed_env_vars; *p; p++)
{
@@ -99,6 +110,21 @@ is_env_var_allowed (const char *var)
return 0;
}
+void
+add_allowed_env_pattern (const char *pattern)
+{
+ if (!pattern || *pattern == 0)
+ return;
+
+ if (user_env_var_count >= MAX_USER_ENV_VARS)
+ {
+ syslog (LOG_NOTICE, "Ignoring --accept-env option: limit reached");
+ return;
+ }
+
+ user_env_vars[user_env_var_count++] = (char *)pattern;
+}
+
void
exorcise_env (void)
{
--