Setting the umask for SFTP transactions

I ran into this problem when was setting up a web server for usage by a team setting up our company web site. There were two developers and they both would be uploading files to the machine, and they both were going to want to modify each others files if need-be. I made a common group and set the sgid bit on the parent directory. I didn’t want to open up straight FTP access to the box so I told them to use SFTP or SCP. This worked great until I found that each users umask was not being applied to new files and directories. The two developers could see each others files but not modify them. I found that the sftp process is spawned by the root user and its umask is applied to the transaction. I wasn’t in favor or modifying the root umask so I came up with another solution.

The only thing I could find to work was to create a wrapper script around the sftp process that would temporarily set the umask for the transaction.

First I created the wrapper script:

#!/bin/bash
 
umask 0002
 
# The path to your sftp-server binary may differ
exec /usr/libexec/openssh/sftp-server

Then I pointed the Subsystem directive in the sshd_config file to my script:

Subsystem       sftp    /opt/sftp-server-wrapper.sh

A quick restart/reload of the sshd configuration and I was in business. Both users could see and edit each others files. Email or comment with questions.

—Edit (20090619)
Or even simpler still as @Gilles pointed out in the comments you can do away with the wrapper script entirely and simply change the Subsystem line in your sshd_config to this:

Subsystem sftp /bin/sh -cumask 0002; /usr/libexec/openssh/sftp-server’

Thanks Gilles!

—Edit (20110525)
Or simplest yet, as @Larry and @simingol pointed out in the comments, there is a new flag for the sftp-server, ‘-u’, that allows you to directly set the umask, overriding the user umask. So to use it, just do this:

Subsystem sftp /usr/libexec/openssh/sftp-server -u 0002
  1. #1 by Joel on October 4, 2008 - 8:28 pm

    This was a 3 hour pain for me on Ubuntu. But this helped a lot.

    For Ubuntu here is what I did(similar to above):

    Create a shell file( note .sh extension) with your favourite editor(vi for me)
    $ sudo vi /usr/lib/openssh/sftp-server.sh

    Add the following lines:
    #!/bin/bash
    umask 0002
    /usr/lib/openssh/sftp-server

    Set the execute permissions
    $ sudo chmod +x sftp-server.sh

    Edit the sshd_config
    $ sudo vi /etc/ssh/sshd_config

    Add .sh to the end of the Subsystem line(near the bottom of the file):
    Subsystem sftp /usr/lib/openssh/sftp-server
    becomes:
    Subsystem sftp /usr/lib/openssh/sftp-server.sh

    Then restart sftp server
    $ sudo /etc/init.d/ssh restart

    And finally it worked:S

  2. #2 by joe on October 28, 2008 - 7:30 am

    I tried this but it didn’t work fine for me, When a user upload files using scp or sftp it preserves the old permission the file had on the sending side, What may be dome?
    Regards,

  3. #3 by jeffro on October 28, 2008 - 2:44 pm

    You need to double check if the Subsystem script is even being run. Add an echo statement before and after setting the umask and redirect it to a file. Check if the file is even being created.

    And just to check, you did restart SSHD after you made these edits, correct?

  4. #4 by Kaanon on November 18, 2008 - 4:16 pm

    Thank goodness for you! I was getting pretty discouraged.

  5. #5 by PE BESSE on February 19, 2009 - 1:03 pm

    Thank’s a lot for your help.

  6. #6 by Xivind on March 19, 2009 - 5:46 pm

    Thanks a lot for this tip guys. Worked right away, and probably more secure also than to change the umask by using the profile documents.

  7. #7 by Fozzy on April 3, 2009 - 4:13 pm

    I can’t seem to get this to work either and it might have something to do with using Openssh’s built-in chroot (jail).

    In this case, the Subsystem used is “internal-sftp” and I adjust the script accordingly, but when I try to login, I get an error about not having BASH or something, which I dont’, as I set the shell to “/bin/false” as per the sftp config. directions.

    I can’t seem to find a way to get this to work when chrooting.

  8. #8 by jeffro on April 6, 2009 - 11:57 am

    @Fozzy
    Unfortunately OpenSSH requires a valid shell to operate. You might try RSSH if you don’t want to allow users a full shell.
    RSSH tutorial: ( http://www.cyberciti.biz/tips/rhel-centos-linux-install-configure-rssh-shell.html )

  9. #9 by ernesto on April 30, 2009 - 5:55 am

    thanks, very helpful, google long for this!

  10. #10 by Gilles Detillieux on June 18, 2009 - 4:31 pm

    Thanks for the handy tip! I had been trying to figure this problem out. It turns out you can even do away with the wrapper script, and instead just change the Subsystem line in sshd_config to this:

    Subsystem sftp /bin/sh -c ‘umask 0002; /usr/libexec/openssh/sftp-server’

    Works for me, anyway. It won’t work in a chroot jail, though, which isn’t an issue for me.

  11. #11 by jeffro on June 19, 2009 - 8:26 am

    @Gilles Detillieux

    Very nice tip also! I will add it to the article, thank you for posting your update.

  12. #12 by Lucky on July 5, 2009 - 8:52 pm

    A gentleman from the Ubuntu forums directed me here, as I was having the same problem. Thank you for the help!

  13. #13 by subba on September 29, 2009 - 10:31 am

    How to use this umask setting for “Subsystem sftp internal-sftp”?

  14. #14 by jeffro on September 29, 2009 - 10:43 am

    @subba

    Not sure I understand your question…Can you try to be more clear?

  15. #15 by kishba on October 27, 2009 - 1:57 pm

    Someone from Rackspace sent me to this article and it worked with RHEL 5 with one minor modification. Rather than umask 0002 I had to use 002.

  16. #16 by Patrick Fisher on October 28, 2009 - 6:54 pm

    Thank you very much, very helpful. Wish this article came up higher in the Google search results!

  17. #17 by jeffro on November 5, 2009 - 4:49 pm

    @kishba
    @ Patrick Fisher

    I am glad you both found it useful!

  18. #18 by Mark Jones on December 3, 2009 - 12:32 pm

    All,
    I was able to compile and create an RPM using SFTPfilecontrol and Openssh5.2p1 which will allow you to set the Umask.

    Steps:
    1. Download tar from openssh.com

    2. Download sftpfilecontrol v1.3 from sftpfilcontrol.sourceforge.com

    3. Extract TAR and then run patch -p0 < /path/to/patch
    with the patch in the same root directory you extracted from.

    4. Tar the source back up and keep extracted directory

    5. Use new source and follow these directions for RHEl or Centos to create a distributable package:
    http://binblog.wordpress.com/2009/02/27/packaging-openssh-on-centos/

  19. #19 by Mark Jones on December 3, 2009 - 5:39 pm

    I just reread my post and it looks a little confusing sorry all hah.

    Anyway, with the SFTPFILECOntrol patch it works with chroot jailing and I have tested it out and it works. It gives you a line in sshd_config where you set the umask.

    If you have any questions on the stuff or want the RPM’s compiled already you can email me at mark d jones 82 at hotmail com

    no spaces and dots, just putting that to avoid spam.

  20. #20 by jeffro on December 4, 2009 - 12:52 pm

    Thanks for the post Mark, while this sounds like a good suggestions I generally steer away from custom compiled versions of software. This will most likely solve the issue of setting the umask but will cause headaches down the road when security patches are released and you have to do the whole exercise over again.

    Just my opinion, others may have differing views.

    BTW, that link (sftpfilcontrol.sourceforge.com) doesn’t go anywhere. In fact I can’t find anything on Sourceforge about a project named sftpfilcontrol. A little help here?

  21. #21 by Mark Jones on December 5, 2009 - 1:03 am

    Jeff,
    You do have a point in regards to security patches, but if you follow the link the source is actually compiled to RPM using Redhat contributions to the package. So, down the line I believe RHEL will be integrating this and security patches should work.

    RHEL only supports 4.3 right now, but it appears they have plans to go to 5.2 at some point.

    File control has been implemented in AIX and HPUX already I believe in the Openssh on there

    Here is the link for the file control:
    http://sftpfilecontrol.sourceforge.net/

  22. #22 by fwiffo on January 13, 2010 - 1:47 pm

    @jeffro, this is similar to subba’s question.
    Using this in sshd_config:
    Match Group sftponly
    ChrootDirectory /var/sftp
    ForceCommand internal-sftp

    wanting to set umask on rhel 5, openssh 5.3, sftpfilecontrol does not have a patch for 5.3.

    any ideas?

  23. #23 by cjackson on March 12, 2010 - 9:18 pm

    I tried implementing this, but the files that are being copied via an SFTP connection are simply maintaining the permissions they have from the original source. Any ideas on what may be causing this?

  24. #24 by jeffro on March 13, 2010 - 10:42 am

    Not entirely sure without a few more details. The only thing I can think of right now is that the copy transaction is being performed with some sort of preserve permissions flag. Are you using a client or the command line to copy the files?

  25. #25 by Jason K on April 6, 2010 - 12:20 pm

    Jeff,

    Thanks a lot we’ve spent alot of time looking for a solution when we upgraded our Mac servers to 10.5 from 10.4.

    Neither AFP nor SMB achieve the permissions we wanted on uploaded files.
    SFTP did but client was using Dreamweaver which does not have any advance permissions setting on it, but this gets us around it.

    Cheers.
    Jason K

  26. #26 by lr on May 27, 2010 - 1:34 pm

    Hi,

    5.4: Changes since OpenSSH 5.3

    Allow setting an explicit umask on the sftp-server(8) commandline to
    override whatever default the user has. bz#1229

    http://openssh.com/txt/release-5.4

  27. #27 by Ankit on June 27, 2010 - 10:07 am

    hi i need help for setting up openssh with sftpfilecontrol patch

  28. #28 by Ankit on June 27, 2010 - 10:09 am

    I have followed the above instructions from mark Jones and was able to get the rpm built with patch but however i still dont find my sftp to be working

    can anyone please help me out

  29. #29 by jeffro on June 27, 2010 - 5:25 pm

    This post is in support of the sftp wrapper script, not the patched RPM. I haven’t tried the patched binary so I can’t answer any questions concerning it.

  30. #30 by gaojinbo on July 8, 2010 - 4:00 am

    Good.
    Thank’s a lot for your help.

  31. #31 by abelr on July 23, 2010 - 5:17 pm

    thanks for info update. however either the wrapper script nor the direct modification to enable the umask settings suffices. it still default to the umask of root on rhel 5

    here is what i noticed the parent process is owned by root and child process owned by the sftp user.

    Note: sftp-server is ver 3 and not running Jail env

  32. #32 by jeffro on July 23, 2010 - 9:27 pm

    Hi @abelr, I am sorry to hear that you couldn’t get this working. Unfortunately, I originally set this up on a RHEL 5 box, so I know without a doubt it works there. Since then I have implemented it successfully in CentOS, Debian and Ubuntu. You did remember to restart the SSHD daemon after making the config changes correct?

  33. #33 by Patricio on September 28, 2010 - 11:41 pm

    Thank you so much! works perfect!

  34. #34 by JonMcL on March 5, 2011 - 2:04 pm

    I’m glad I found this, but I’m still stuck.

    I’m amateurishly setting up an Ubuntu 10.04 server. I fixed the global umask in /etc/profile first (to 002) and of course still had problems with sftp. So I tried both the shell wrapper solution and the sshd_config solution by Gilles at #10.

    Everything works great for directories created via sftp, but unfortunately files are still going in as 644 instead of 664. I’ve not only restart ssh, but I even restarted the server.

    Anyone have any ideas why the directories are okay, but files are not?

  35. #35 by Larry on May 11, 2011 - 1:49 pm

    I found that there is a built-in arg to sftp-server…
    Edit the line for the Subsystem and append -u 0002 to it.
    In my example it would change from:
    Subsystem sftp /usr/lib/openssh/sftp-server
    to
    Subsystem sftp /usr/lib/openssh/sftp-server -u 0002

  36. #36 by slmingol on May 25, 2011 - 11:25 am

    Check the man page for sftp-server it discusses the use of the -u switch.

    -u umask
    Sets an explicit umask(2) to be applied to newly-created files and directories, instead of the
    user’s default mask.

  37. #37 by jeffro on May 25, 2011 - 9:30 pm

    @Larry
    @ slmingol

    Great find Larry and simingol. However, when I first wrote this article in 2008 the ‘-u’ option to set the umask for the sftp-server hadn’t been introduced yet, that didn’t come about until early 2010. (I only know because I dug through the man pages of previous versions of OpenBSD)

    I have updated the article to show how you could use the flag. Thanks for keeping me on my toes.

  38. #38 by Spencer Rose on June 3, 2011 - 7:00 pm

    I am dying here. The sshd_config will not call the wrapper. I have put echo statements at every stage of the wrapper file. Nothing. I have run the wrapper from another file and it fires and echos fine (if I comment out: exec /usr/libexec/openssh/sftp-server). I have tried a million different things from executable status to permissions to firing it from different directories, but the sshd_config file will not call and fire the wrapper. I am stumped any help would be incredible. I am 6 hours into this.

  39. #39 by John L on July 26, 2011 - 5:42 pm

    Thanks for the help here! I’m having the same problem JonMcL mentioned (but I’m using RHEL 5.6) — this fixed the umask for new directories, but not for new files. Any ideas?

  40. #40 by jeffro on July 28, 2011 - 5:58 pm

    Have you tried the -u switch, or the wrapper? Its possible that you might not be setting the umask correctly. Remember that while the umask is like the directory octals, its not the same:
    0 – no permissions
    1 – execute only
    2 – write only
    3 – write and execute
    4 – read only
    5 – read and execute
    6 – read and write
    7 – read, write and execute

    Setting the umask properly for what I am trying to accomplish is what usually causes me the most issues. Sorry, I can’t be more help. Drop me an email if you want to try an hash it out a bit more.

  41. #41 by Doug on August 9, 2011 - 6:57 pm

    The problem I am having is that when my team is creating a new file on Transmit (SFTP client), it is not honoring the umask.

  42. #42 by Stefan on August 11, 2011 - 10:38 am

    @Joel
    Thanks alot! ALOT

  43. #43 by jeffro on August 11, 2011 - 10:46 am

    @Doug
    I would check that the SFTP client doesn’t have some sort of permission preset setting over-ridding the umask. I know Filezilla has this and it can cause headaches if you don’t know what its doing.

(will not be published)