Make sshd override login shell of a group of users

9,766

Solution 1

The rssh manpage indicates it should be the login shell of these users:

The  system  administrator  should  install the shell on the restricted
system.  Then the password file entry  of  any  user  for  whom  it  is
desireable  to  provide  restricted  access should be edited, such that
their shell is rssh. For example:

      luser:x:666:666::/home/luser:/usr/bin/rssh

With the ForceCommand, only that command is run. When you run scp or sftp, commands are run by SSH (scp, /usr/lib/openssh/sftp-server, respectively), and of course they can't be run unless the program executed by ForceCommand uses SSH_ORIGINAL_COMMAND to do so. So, for rssh to do its job, it has to be the login shell, not a ForceCommand.

Related:


You can, instead, use a wrapper script that will use rssh instead of the login shell to execute commands. For example:

/usr/local/bin/wrapper-shell:

#! /bin/sh
rssh -c "$SSH_ORIGINAL_COMMAND"

And in /etc/ssh/sshd_config:

Match group sftponly
     X11Forwarding no
     AllowTcpForwarding no
     ForceCommand /usr/local/bin/wrapper-shell

With /usr/local/bin/wrapper-shell being executable should work.

Solution 2

We had the same problem: a server must allow scp sftp and rsync for all users but no connection with command line. User database is in ldap and we cannot modify /etc/passwd locally. rssh was therefore not an option.

One solution I have found is by using ForceCommand and a shell script. In /etc/ssh/sshd_config adding these lines:

Match user *
    X11Forwarding no
    AllowTcpForwarding no
    ForceCommand /usr/local/bin/wrapper-shell user1 user2 user3

Where userX are special users allowed to log in via ssh. The wrapper-shell script, which do the actual filtering, is:

#!/bin/sh
SSHCMD=`echo "$SSH_ORIGINAL_COMMAND" | awk '{ print $1 }'`
ME=`id -u -n`
DOIT=Maybe
# Root is always allowed in order to not being locked out
for n in root $*
do
  if [ "$ME" = "$n" ]
  then
    DOIT=YES
    break
  fi
done
if [ "$DOIT" = YES -o "$SSHCMD" = "scp" -o "$SSHCMD" = "rsync" -o "$SSHCMD" = /usr/lib/openssh/sftp-server ]
then
    sh -c "$SSH_ORIGINAL_COMMAND"
else
    cat <<EOF 1>&2

This account is restricted and the command is not allowed.

User $ME is locked out.

If you believe this is in error, please contact your system administrator.
EOF
    exit 1
fi
Share:
9,766

Related videos on Youtube

umläute
Author by

umläute

Updated on September 18, 2022

Comments

  • umläute
    umläute over 1 year

    My users are shared across a number of machines via LDAP.

    For one of those machines (let's call it 'fileserf'), I would like to restrict some users in what they can do (actually: prevent them from logging into an interactive session via ssh). On the other machines, these users should be able to use ssh normally.

    So my initial idea was to use the internal-sftp subsystem, along the lines of:

    Match group sftponly
         ChrootDirectory %h
         X11Forwarding no
         AllowTcpForwarding no
         ForceCommand internal-sftp
    

    This works ok as it restricts only the members of the (local) group sftponly on a single host fileserf, but unfortunately the internal-sftp subsystem only allows sftp and not scp (or rsync).

    So I did some more research and found rssh, which seems to allow me to do exactly what I want to do (permission-wise).

    Now the problem is that I cannot set the login-shell of those users to /usr/bin/rssh in my LDAP, because that would mean that they would be restricted on all machines, not just on fileserf.

    So my idea is to override the login shell via some configuration in fileserf's sshd_config:

    Match group sftponly
         X11Forwarding no
         AllowTcpForwarding no
         ForceCommand /usr/bin/rssh
    

    Unfortunately this doesn't seem to work, since now the users get a Connection closed whenever they try to sftp into the machine:

    $ ssh user@fileserf 
    
    This account is restricted by rssh.
    Allowed commands: scp sftp 
    
    If you believe this is in error, please contact your system administrator.
    
    Connection to fileserf closed.
    
    $ sftp user@fileserf
    Connection closed
    $
    

    How can I make ForceCommand work with rssh?

    Alternatively, How can I configure sshd to override the login-shell for a group of users?

    • muru
      muru over 8 years
      If you can add these users to a local group, perhaps you can create local users which shadow them?
  • umläute
    umläute over 8 years
    that's why the title of my question says [how to] "make sshd override login shell". updated the question-body to reflect that...
  • muru
    muru over 8 years
    @umläute you should understand that SSH can't override the login shell. The login shell is what it is, ForceCommand doesn't change that. Try running a shell script as a ForceCommand which prints $SHELL.
  • muru
    muru over 8 years
    @umläute see update.
  • umläute
    umläute over 8 years
    the update seems promising; i tried something like that before but failed; i will try again following your suggestion when i'm back at the machine.
  • umläute
    umläute over 8 years
    actually that did the trick; i don't know why my prior tests with such a wrapper script failed (esp. since my wrapper was identical to yours :-()