38

I've been searching for a way to setup OpenSSH's umask to 0027 in a consistent way across all connection types.

By connection types I'm referring to:

  1. sftp
  2. scp
  3. ssh hostname
  4. ssh hostname program

The difference between 3. and 4. is that the former starts a shell which usually reads the /etc/profile information while the latter doesn't.

In addition by reading this post I've became aware of the -u option that is present in newer versions of OpenSSH. However this doesn't work.

I must also add that /etc/profile now includes umask 0027.

Going point by point:

  • sftp - Setting -u 0027 in sshd_config as mentioned here, is not enough.

If I don't set this parameter, sftp uses by default umask 0022. This means that if I have the two files:

-rwxrwxrwx 1 user user 0 2011-01-29 02:04 execute
-rw-rw-rw- 1 user user 0 2011-01-29 02:04 read-write

When I use sftp to put them in the destination machine I actually get:

-rwxr-xr-x 1 user user 0 2011-01-29 02:04 execute
-rw-r--r-- 1 user user 0 2011-01-29 02:04 read-write

However when I set -u 0027 on sshd_config of the destination machine I actually get:

-rwxr--r-- 1 user user 0 2011-01-29 02:04 execute
-rw-r--r-- 1 user user 0 2011-01-29 02:04 read-write

which is not expected, since it should actually be:

-rwxr-x--- 1 user user 0 2011-01-29 02:04 execute
-rw-r----- 1 user user 0 2011-01-29 02:04 read-write

Anyone understands why this happens?

  • scp - Independently of what is setup for sftp, permissions are always umask 0022. I currently have no idea how to alter this.

  • ssh hostname - no problem here since the shell reads /etc/profile by default which means umask 0027 in the current setup.

  • ssh hostname program - same situation as scp.


In sum, setting umask on sftp alters the result but not as it should, ssh hostname works as expected reading /etc/profile and both scp and ssh hostname program seem to have umask 0022 hardcoded somewhere.

Any insight on any of the above points is welcome.

EDIT: I would like to avoid patches that require manually compiling openssh. The system is running Ubuntu Server 10.04.01 (lucid) LTS with openssh packages from maverick.

Answer: As indicated by poige, using pam_umask did the trick.

The exact changes were:

Lines added to /etc/pam.d/sshd:

# Setting UMASK for all ssh based connections (ssh, sftp, scp)
session    optional     pam_umask.so umask=0027

Also, in order to affect all login shells regardless of if they source /etc/profile or not, the same lines were also added to /etc/pam.d/login.

EDIT: After some of the comments I retested this issue.

At least in Ubuntu (where I tested) it seems that if the user has a different umask set in their shell's init files (.bashrc, .zshrc,...), the PAM umask is ignored and the user defined umask used instead. Changes in /etc/profile did't affect the outcome unless the user explicitly sources those changes in the init files.

It is unclear at this point if this behavior happens in all distros.

10
  • Unode: "I would like to avoid patches that require manually compiling openssh." Why? Jan 29, 2011 at 8:13
  • 5
    @desasteralex - Because (if possible) I would like to avoid having the additional maintenance/administration task that comes with having source based packages and because I find it hard to believe that there is no other way to change umask other than patching openssh. Specially considering this is a rather basic security aspect on any system.
    – Unode
    Jan 31, 2011 at 14:35
  • 1
    After altering /etc/pam.d/sshd (and login), and restarting ssh, I see no behavioral change. Are there other needed changes implied but not mentioned here?
    – Steve Clay
    Jul 30, 2011 at 23:27
  • @mrclay - Do you have UsePAM yes in your sshd_config ?
    – Unode
    Jul 31, 2011 at 15:24
  • 1
    To solve the user's .bashrc problem, try aliasing away the umask command in your /etc/profile. Something like alias umask=/bin/true
    – Tobia
    Mar 18, 2013 at 10:22

10 Answers 10

23
+50

I can suggest trying 2 things:

  1. pam_umask
  2. LD_PRELOAD wrapper (self-written?)
3
  • pam_umask does the trick. Edited question to reflect and elaborate the answer
    – Unode
    Feb 2, 2011 at 17:25
  • Just use stackoverflow.com/q/10220531/220060. However be careful, if you mistype something, you lock yourself out of the server. Always check if you can login again before closing your current session.
    – nalply
    Aug 28, 2014 at 9:05
  • 1
    Addition to the comment by @nalply: Make sure to have a backup root session open, since breaking PAM means you won't be able to sudo or sudo su or the like.
    – Zero3
    Jul 6, 2017 at 22:45
16

Here is a solution that will let you do what you want on a per-user basis. It uses only native sshd features and does not require mucking about with locally maintained patches. This solution takes advantage of the ForceCommand behavior of sshd to insert an environment-setup script into every ssh connection, and then run the original command.

First, create a script somewhere on your system with the following contents:

#!/bin/sh

umask 0027
exec /bin/sh -c "${SSH_ORIGINAL_COMMAND:-$SHELL}"

For the purposes of this example I'll assume you've called this /usr/bin/umask-wrapper.

Now, you have a few options in setting this up. If you want this to be a mandatory configuration for all users (which seems a little unlikely), you can modify your sshd configuration to include the following:

ForceCommand /usr/bin/umask-wrapper

If you only want this to apply to some users, you can use a Match block (this goes at the end of your sshd_config):

Match User user1,user2
ForceCommand /usr/bin/umask-wrapper

If you want this to be user-controllable behavior, then you can use the command= option in an authorized_key file to select this behavior for specific keys. For example, while testing this out I added an entry to my authorized_keys file that looks something like this:

command="/home/lars/bin/umask-wrapper" ssh-rsa AAAAB3NzaC1 ... umask-test

And here are some results of my test:

Using ssh with no command:

localhost$ ssh remotehost
remotehost$ touch umask-test/file1
remotehost$ ls -l umask-test/file1
-rw-r-----. 1 lars lars 0 Feb  2 06:02 file1

Using ssh with a command:

localhost$ ssh remotehost touch umask-test/file2
localhost$ ssh remotehost ls -l umask-test/file2
-rw-r-----. 1 lars lars 0 Feb  2 06:03 file2

Using scp:

localhost$ touch file3
localhost$ ls -l file3
-rw-r--r--  1 lars  staff  0 Feb  2 06:03 file3
localhost$ scp file3 remotehost:umask-test/file3
localhost$ ssh remotehost ls -l umask-test/file3
-rw-r-----. 1 lars lars 0 Feb  2 06:03 file3

Using sftp:

localhost$ sftp remotehost
sftp> put file3 umask-test/file4
sftp> ls -l umask-test/file4
-rw-r-----    0 500      500             0 Feb  2 06:05 umask-test/file4

And there you have it. I believe this is the behavior you were looking for. If you have any questions about this solution I would be happy to provide additional details.

3
  • Although this method seems to work, it looks a bit of a maintenance nightmare. Still, +1 for cases where pam cannot be used.
    – Unode
    Feb 2, 2011 at 17:24
  • 4
    I don't know that it's all that difficult to maintain. The primary advantage over a PAM-based solution is that it doesn't require any special privileges -- you can set this up for your own account without administrator intervention.
    – larsks
    Feb 2, 2011 at 17:56
  • I was thinking in terms of keeping a selected list of users, but indeed I didn't notice the aspect of this working on plain user setup. When I first read it I thought ForceCommand was "required" and not "one way of setting it up". command= is indeed a neat feature of ssh.
    – Unode
    Feb 2, 2011 at 19:00
5

I took a slightly different approach to centralize the setting.

This was added to /etc/pam.d/common-session:

session    optional     pam_umask.so

This was modified in /etc/login.defs:

UMASK           0027
2

I've gotten pam_umask to work with ssh, but not with scp or sftp.

The wrapper method also does nothing for sftp or scp. I'm not sure 027 is a good example since most distros have umask set to that already. Try with 002 and see if that works.

1

Programs that don't set their own umask inherit the umask of the application that started it. Stop sshd completely, set your umask to 0027, then start it again. (You can add the umask command in the init script for future reboots.)

Tested to work with scp.

1
  • Sorry DerfK but this was one of the first things I've tried without success. All login shells have umask 0027 (if they read /etc/profile) but restarting ssh doesn't affect scp nor ssh.
    – Unode
    Jan 29, 2011 at 3:20
1

If pam_umask doesn't seem to affect your SFTP sessions, then check if UsePam is set to Yes in the /etc/ssh/sshd_config file.

If you have disabled password authentication and UsePam was set or defaulted to No. You may want to set ChallengeResponseAuthentication No in the sshd_config file because otherwise you may inadvertently enable a password authentication through that system.

1

An added note to user188737's answer above:

This may go without saying, but if you are not using the openssh-server package, and have manually compiled OpenSSH, make sure you "Enable PAM support" by passing the --with-pam configuration flag.

Otherwise, UsePAM=yes in sshd_config, plus any changes to /etc/pam.d/* will effectively be ignored by sshd.

It finally dawned on me why none of the recommended PAM solutions were having any affect testing via non-interactive SFTP connections...

1

Since umask is inherited from the parent process, on a Slackware system that uses /etc/rc.d/rc.sshd to start/stop/restart sshd, you could simply place umask 0027 on a line by itself directly above "sshd_start" or "sshd_restart", or alternatively, at any point before the main execution section begins, in /etc/rc.d/rc.sshd:

case "$1" in
'start')
  umask 0027
  sshd_start
  ;;
'stop')
  sshd_stop
  ;;
'restart')
  umask 0027
  sshd_restart
  ;;
*)

Or, alternatively, at the top of the file:

#!/bin/sh
# Start/stop/restart the secure shell server:
umask 0027
0

I have just tested a possible improvement to larsks sshd_config options on solaris 11

Setup a group with the users to be managed and move the script into the config file itself, in my case I wanted to set the umask to 0002.

the resulting configuration becomes....

Match Group managedgroup
ForceCommand /bin/sh -c 'umask 0002; ${SSH_ORIGINAL_COMMAND:-$SHELL}'
-1

I have been struggling with this issue, specifically with file permissions after copying a file using scp, and it finally occurred to me to simply use ssh to change the permissions after the copy.

Here is the solution:

  1. Copy your file: localhost$ scp filename remotehost:umask-test/filename
  2. Fix permission: localhost$ ssh remotehost "chmod go+r umask-test/filename"

Best of all, no root access is necessary to effect this solution.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .