The Secure Shell (SSH) [RFC4251] is a
"protocol for secure remote login and other secure network services over an insecure network".
"Secure Shell (SSH) Connection Protocol" as defined in [RFC4254] provides
"interactive login sessions, remote execution of commands, forwarded TCP/IP connections, and forwarded X11 connections. All of these channels are multiplexed into a single encrypted tunnel".
The connection protocol describe channel request for "Environment Variable Passing".
OpenSSH is a FREE implementation of the SSH protocol.
As of version 3.9 OpenSSH is able to pass environment variables.
Environment passing is only supported for SSH protocol version 2.
On server side control is done via AcceptEnv(1) configuration option.
Client use option SendEnv(2) to select variables from the local environment that should be sent to the server.
Both options accept the wildcard characters "*" and "?".
- User locale:
Main issue is to pass variables related to user locale.
Lets to prepare list of variables to pass.
"The locale program writes information about the current locale environment(3)(4)".
Let environment variable LANG is set to bg_BG.ISO8859-5.
Command locale return:
Note for historical reason user may set LC_ALL too.
In additional to these variables is good to pass LANGUAGE - in use by GNU gettext(5).
As result the list of necessary variables to pass on remote host is LANG, LC_* and LANGUAGE.
- OpenSSH setup:
On the server side admin should put in sshd_config, usually located in directory /etc/ssh, following line:
AcceptEnv LANG LC_* LANGUAGE
Client program "ssh" can obtain configuration data from different sources:
- command line
- user configuration file ($HOME/.ssh/config)
- system-wide configuration file (usually /etc/ssh/ssh_config)
It is not recommended to put option SendEnv in system-wide configuration file.
Good place is user configuration file in sections for selected hosts.
- So far so good:
All that depend from openssh is done.
We assume that locale database on hosts is properly setup.
Unfortunately environment passing is secure shell session don't work at all.
- Test case:
To test we should logon on remote system with following command:
$ LANG=testLANG \
, where <remote_host> is name or ip_address on remote host and
we override some environment variables from command line.
Note that value of LC_* and LANG is invalid locale.
In logon session we should execute:
$ echo "TEST=$LANG $LC_ALL $LC_CTYPE $LC_TEST"
TEST=testLANG testLC_ALL testLC_CTYPE testTEST
When result is not as shown above (in green) we should modify startup files read by login shell.
Note that only root can modify system-wide startup files.
The startup files we can obtain from shell manual page.
First step is to modify system-wide startup files.
Note that files can contain commands that instruct shell to read from other files.
To do this we should check all assignments to variables LANG, LC_CTYPE and LC_ALL.
At beginning of startup file read first by shell we should check whether at least one of variables is set and
when is set we should assign to variable LOCALE_IS_SET nonempty string, as example yes.
Later in this file or in files read by shell we should find where user locale is set.
Lines that set user locale we should enclose in if-statement:
- "Bourne" like shells:
if test -z "$LOCALE_IS_SET"; then
#lines that set user locale, as example
- "C" like shells:
if (! $?LOCALE_IS_SET) then
#lines that set user locale, as example
setenv LC_ALL POSIX
In personal startup files for all users we should enclose in if-statement lines that set locale.
As example for german locale:
It is good to find and modify template files in directory /etc/skel.
Following two commands help us to find system-wide startup files that we should modify so "locale environment passing in ssh sessions" to work.
$ grep -w LANG /etc/* /etc/*/* 2>/dev/null
$ grep -w LC_.* /etc/* /etc/*/* 2>/dev/null
One of files is /etc/profile.d/lang.sh if exist.
If exist /etc/environment take a look too.
In addition to variables that set user locale we might pass some others variables:
Developers might found that is usefull to pass CVSROOT and CVS_RSH.
- used by print spooler to set default printer:
LPDEST, PRINTER or PDPRINTER
- used by Xprint:
XPRINTER and XPSERVERLIST