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)
 {
-- 


Reply via email to