From baeb17eb76772a2dbbcc4d52a22ddfc405276db1 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Fri, 4 Sep 2015 11:04:30 -0700 Subject: [PATCH 29/34] Accept LANG and LC_* environment variables from clients by default This preserves most of the old SunSSH locale negotiation behaviour (at least the parts that are most commonly used). diff -wpruN --no-dereference '--exclude=*.orig' a~/servconf.c a/servconf.c --- a~/servconf.c 1970-01-01 00:00:00 +++ a/servconf.c 1970-01-01 00:00:00 @@ -162,6 +162,8 @@ initialize_server_options(ServerOptions options->subsystem_args = NULL; #define init_timingsecret(options) \ options->timing_secret = 0; +#define init_defaultacceptenv(options) \ + options->default_accept_env = 1; #ifdef PAM_ENHANCEMENT /* * Each userauth method will have its own PAM service by default. However, @@ -190,6 +192,7 @@ initialize_server_options(ServerOptions #undef init_rekeylimit #undef init_subsystem #undef init_timingsecret +#undef init_defaultacceptenv #ifdef PAM_ENHANCEMENT #undef init_pamserviceperauthmethod #endif @@ -467,6 +470,32 @@ fill_default_server_options(ServerOption &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS2); } + if (options->default_accept_env == 1) { + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LANG"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_ALL"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_CTYPE"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_COLLATE"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_TIME"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_NUMERIC"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_MONETARY"); + opt_array_append("[default]", 0, "AcceptEnv", + &options->accept_env, &options->num_accept_env, + "LC_MESSAGES"); + } if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_EF; if (options->ip_qos_bulk == -1) @@ -2160,9 +2189,12 @@ process_server_config_line_depth(ServerO if (*arg == '\0' || strchr(arg, '=') != NULL) fatal("%s line %d: Invalid environment name.", filename, linenum); + options->default_accept_env = 0; found = 1; if (!*activep) continue; + if (strcmp(arg, "none") == 0) + continue; opt_array_append(filename, linenum, keyword, &options->accept_env, &options->num_accept_env, arg); @@ -3191,6 +3223,18 @@ serialise_timingsecret(const ServerOptio return 0; } +static int +serialise_defaultacceptenv(const ServerOptions *options, struct sshbuf *buf) +{ + int r; + + if ((r = serialise_s32(buf, options->default_accept_env)) != 0) { + error_fr(r, "serialise"); + return r; + } + return 0; +} + #ifdef PAM_ENHANCEMENT static int serialise_pamserviceperauthmethod(const ServerOptions *options, @@ -3741,6 +3785,18 @@ deserialise_timingsecret(ServerOptions * return 0; } +static int +deserialise_defaultacceptenv(ServerOptions *options, struct sshbuf *buf) +{ + int r; + + if ((r = deserialise_s32(buf, &options->default_accept_env)) != 0) { + error_fr(r, "deserialise"); + return r; + } + return 0; +} + #ifdef PAM_ENHANCEMENT static int deserialise_pamserviceperauthmethod(ServerOptions *options, @@ -3920,6 +3976,7 @@ free_server_options(ServerOptions *optio #define free_persourcepenalties(options) #define free_rekeylimit(options) #define free_timingsecret(options) +#define free_defaultacceptenv(options) #ifdef PAM_ENHANCEMENT #define free_pamserviceperauthmethod(options) #endif @@ -3938,6 +3995,7 @@ free_server_options(ServerOptions *optio #undef free_persourcepenalties #undef free_rekeylimit #undef free_timingsecret +#undef free_defaultacceptenv #ifdef PAM_ENHANCEMENT #undef free_pamserviceperauthmethod #endif diff -wpruN --no-dereference '--exclude=*.orig' a~/servconf.h a/servconf.h --- a~/servconf.h 1970-01-01 00:00:00 +++ a/servconf.h 1970-01-01 00:00:00 @@ -203,6 +203,7 @@ SSHCONF_STRARRAY(deny_users, num_deny_us SSHCONF_STRARRAY(allow_groups, num_allow_groups, AllowGroups, SSHCFG_ALL, SSHCFG_COPY_MATCH) \ SSHCONF_STRARRAY(deny_groups, num_deny_groups, DenyGroups, SSHCFG_ALL, SSHCFG_COPY_MATCH) \ SSHCONF_STRARRAY(accept_env, num_accept_env, AcceptEnv, SSHCFG_ALL, SSHCFG_COPY_MATCH) \ +SSHCONF_NONCONF(defaultacceptenv) \ SSHCONF_STRARRAY(setenv, num_setenv, SetEnv, SSHCFG_ALL, SSHCFG_COPY_MATCH) \ SSHCONF_INT(per_source_max_startups, PerSourceMaxStartups, SSHCFG_GLOBAL, NULL, INT_MAX, SSHCFG_COPY_NONE) \ SSHCONF_STRING(per_source_penalty_exempt, PerSourcePenaltyExemptList, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \ @@ -410,6 +411,8 @@ typedef struct ServerOptions { int rekey_interval; /* Passed by config but not keyword for this */ uint64_t timing_secret; + /* Cleared as a side-effect of AcceptEnv */ + int default_accept_env; #ifdef PAM_ENHANCEMENT /* Set as a side-effect of PAMServiceName */ int pam_service_per_authmethod; diff -wpruN --no-dereference '--exclude=*.orig' a~/session.c a/session.c --- a~/session.c 1970-01-01 00:00:00 +++ a/session.c 1970-01-01 00:00:00 @@ -794,6 +794,18 @@ check_quietlogin(Session *s, const char } /* + * If the given environment variable is set in the daemon's environment, + * push it into the new child as well. If it is unset, do nothing. + */ +static void +child_inherit_env(char ***envp, u_int *envsizep, const char *name) +{ + char *value; + if ((value = getenv(name)) != NULL) + child_set_env(envp, envsizep, name, value); +} + +/* * Reads environment variables from the given file and adds/overrides them * into the environment. If the file does not exist, this does nothing. * Otherwise, it must consist of empty lines, comments (line starts with '#') @@ -977,6 +989,16 @@ do_setup_env(struct ssh *ssh, Session *s ssh_gssapi_do_child(&env, &envsize); #endif + /* Default to the system-wide locale/language settings. */ + child_inherit_env(&env, &envsize, "LANG"); + child_inherit_env(&env, &envsize, "LC_ALL"); + child_inherit_env(&env, &envsize, "LC_CTYPE"); + child_inherit_env(&env, &envsize, "LC_COLLATE"); + child_inherit_env(&env, &envsize, "LC_TIME"); + child_inherit_env(&env, &envsize, "LC_NUMERIC"); + child_inherit_env(&env, &envsize, "LC_MONETARY"); + child_inherit_env(&env, &envsize, "LC_MESSAGES"); + /* Set basic environment. */ for (i = 0; i < s->num_env; i++) child_set_env(&env, &envsize, s->env[i].name, s->env[i].val); @@ -1020,8 +1042,7 @@ do_setup_env(struct ssh *ssh, Session *s /* Normal systems set SHELL by default. */ child_set_env(&env, &envsize, "SHELL", shell); - if (getenv("TZ")) - child_set_env(&env, &envsize, "TZ", getenv("TZ")); + child_inherit_env(&env, &envsize, "TZ"); #ifdef HAVE_LOGIN_CAP if (getenv("XDG_RUNTIME_DIR")) { child_set_env(&env, &envsize, "XDG_RUNTIME_DIR", diff -wpruN --no-dereference '--exclude=*.orig' a~/sshd_config a/sshd_config --- a~/sshd_config 1970-01-01 00:00:00 +++ a/sshd_config 1970-01-01 00:00:00 @@ -27,6 +27,10 @@ #SyslogFacility AUTH #LogLevel INFO +# Use the client's locale/language settings +#AcceptEnv LANG LC_ALL LC_CTYPE LC_COLLATE LC_TIME LC_NUMERIC +#AcceptEnv LC_MONETARY LC_MESSAGES + # Authentication: #LoginGraceTime 2m diff -wpruN --no-dereference '--exclude=*.orig' a~/sshd_config.5 a/sshd_config.5 --- a~/sshd_config.5 1970-01-01 00:00:00 +++ a/sshd_config.5 1970-01-01 00:00:00 @@ -86,7 +86,20 @@ directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. -The default is not to accept any environment variables. +The default is to accept only +.Ev LANG +and the +.Ev LC_* +family of environment variables. If any +.Cm AcceptEnv +directives are present in your config file, they will replace this default +.Po +ie, only the variables you list will be passed into the session's +.Xr environ 7 +.Pc . +You can also use an argument of +.Dq none +to specify that no environment variables should be passed. .It Cm AddressFamily Specifies which address family should be used by .Xr sshd 8 .