SSH not passing LANG environment variable

5

I'm running a Debian server (uname -v output #1 SMP Debian 4.9.65-3+deb9u1 (2017-12-23)). When I log in from any of several clients (macOS 10.13 laptop with default ssh, the "Prompt" app on iOS, among others), LANG=C, despite passing in LANG=en_US.UTF-8 from the client. Here is some relevant information:

client$ env | grep LANG
LANG=en_US.UTF-8
client$ ssh -v server
...
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
server$ env | grep LANG
LANG=C
server$ grep -in lang /etc/profile ~/.bash_profile ~/.bash_login ~/.profile ~/.bash_logout ~/.bashrc
grep: ~/.bash_profile: No such file or directory
grep: ~/.bash_login: No such file or directory
server$ locale -a
C
C.UTF-8
POSIX
en_US.utf8
server$ sudo sshd -T | grep acceptenv
acceptenv LANG
acceptenv LC_*

So, ssh claims to be sending LANG, sshd claims to be accepting LANG, and LANG is not being set in any of the bash startup/shutdown files.

I know I could "fix" this with a setting in ~/.profile or somesuch, but I'm more interested in why the environment isn't getting passed properly.

Edit:

I just noticed that the LANG name is different on macOS and Debian. This still doesn't work, however:

client$ LANG=en_US.utf8 ssh -v server
...
debug1: Sending environment.
debug1: Sending env LANG = en_US.utf8
server$ env | grep LANG
LANG=C

Edit 2:

This difference in names isn't, it turns out, a Mac-vs-Linux issue. locale -a reports a different name for the locale than is used by $LANG. I haven't bothered to investigate why.

Scott Colby

Posted 2018-01-01T23:25:51.753

Reputation: 155

1Maybe it is overriden by some profile processing dring the logon on the server? Same problem here between two Ubuntus... LANG seems clobbered but other envvars are carried over correctly. – xenoid – 2018-01-02T00:44:46.213

Answers

5

In my Kubuntu or Debian there is a file /etc/default/locale like:

#  File generated by update-locale
LANG="pl_PL.UTF-8"

It is mentioned in various /etc/pam.d/* files. This is a fragment of /etc/pam.d/sshd:

# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session    required     pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale

Now from man 5 pam.conf:

When a PAM aware privilege granting application is started, it activates its attachment to the PAM-API. This activation performs a number of tasks, the most important being the reading of the configuration file(s): /etc/pam.conf. Alternatively, this may be the contents of the /etc/pam.d/ directory. The presence of this directory will cause Linux-PAM to ignore /etc/pam.conf.

When a user logs in via SSH, sshd forks itself and this is the moment /etc/pam.d/sshd does its job. See man 8 pam_env, it is responsible for setting/unsetting environment variables. I wasn't sure if sshd forks before or after accepting variables from a client, so I made a simple test. I commented out this single line on my Debian server:

session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale

and the issue you pointed out was fixed (tested with LANG=C ssh myserver in my case). I uncommented the line and the issue reappeared.

Kamil Maciorowski

Posted 2018-01-01T23:25:51.753

Reputation: 38 429

This is where the variable setting came from on my system as well. Running dpkg-reconfigure locales allowed me to set the new default. Also interesting--the output of locale -a, en_US.utf8, doesn't match the name the variable is set to, en_US.UTF-8. What a strange world we have created for ourselves. – Scott Colby – 2018-01-02T04:22:13.517