OpenSSH SFTP Server Permission Behavior: Umask vs. Client-Side Preservation in Chroot Environments


3 views

When working with OpenSSH's SFTP implementation (particularly internal-sftp), there's significant confusion around how file permissions are handled during uploads. The key question is whether the server applies the configured umask or preserves client-side permissions during put operations.

Testing with OpenSSH 5.9 on RHEL 6.2 reveals:

# On client
touch MYFILE
mkdir MYDIR
chmod 600 MYFILE
chmod 700 MYDIR

# SFTP operations
sftp> mkdir testdir       # 775 (umask 0002 applied)
sftp> put MYFILE          # 600 (client permissions preserved)
sftp> put -r MYDIR        # 700 (client permissions preserved)

The OpenSSH SFTP protocol implements the SSH File Transfer Protocol which includes extensions for permission preservation. The behavior differs between:

  • New directory creation: Follows server umask
  • File upload (put): Preserves client permissions
  • Recursive upload (put -r): Preserves directory permissions

Several approaches were tested without success:

# Option 1: internal-sftp umask flag
Subsystem sftp internal-sftp -u 0002

# Option 2: PAM configuration (in /etc/pam.d/sshd)
session    optional     pam_umask.so umask=0002

For enforcing server-side permissions:

# Post-upload permission reset script
#!/bin/bash
inotifywait -m -e close_write --format %f /chroot/upload/ | while read FILE
do
    chmod 640 "/chroot/upload/$FILE"
done

Or using ForceCommand with a wrapper:

# In sshd_config
ForceCommand /usr/local/bin/sftp-wrapper

# sftp-wrapper content
#!/bin/sh
umask 0027
exec /usr/lib/openssh/sftp-server "$@"

Documented changes in OpenSSH behavior:

Version Behavior
OpenSSH 5.4+ Added -u umask flag
OpenSSH 6.0+ More consistent permission handling
OpenSSH 7.4+ Added PermitUserEnvironment options

For production systems requiring strict permission control:

  1. Upgrade to OpenSSH 7.4+ for better permission management
  2. Combine internal-sftp with filesystem ACLs
  3. Implement post-upload hooks for permission normalization

When working with OpenSSH's SFTP implementation (particularly version 5.9 on RHEL 6.2), there's significant confusion around how file permissions are handled during transfers. The key question revolves around whether the server applies the configured umask or preserves client-side permissions when files are uploaded.

From practical testing with a chrooted environment using internal-sftp subsystem:

# Sample test observations
1. mkdir → New directory respects umask (002)
2. put MYFILE → Preserves client permissions (600)
3. put -r MYDIR → Preserves directory permissions (700)

Several approaches exist for permission control:

  • internal-sftp -u 0002 (umask specification)
  • PAM configuration in /etc/pam.d/sshd
  • Wrapper scripts for sftp-server

OpenSSH implements SFTP protocol extensions that transfer file metadata including permissions. This behavior appears hardcoded in the OpenSSH implementation:

// Simplified representation of OpenSSH's SFTP server logic
if (client_sends_permissions) {
    apply_client_permissions();
} else {
    apply_umask();
}

For those needing umask enforcement:

  1. Post-upload permission reset:
    # Example inotifywait solution
    inotifywait -m -e close_write /chroot/path | while read path action file
    do
        chmod 640 "$path$file"
    done
    
  2. Forced umask via PAM:
    # /etc/pam.d/sshd addition
    session optional pam_umask.so umask=0022
    

Behavior differs across OpenSSH versions:

Version Behavior
<5.4 No umask support
5.4-7.4 Umask applies to new files only
7.5+ More consistent umask application

For RHEL 6.2 environments:

  • Combine PAM umask with post-upload scripts
  • Consider upgrading to newer OpenSSH versions if possible
  • Document the behavior clearly for users