SSH server implementations are not known for their flexibility in per-user configuration. However, they turn out to provide just enough infrastructure to make it possible to make "special" accounts that are only used for a specific task. Here, I will concentrate on OpenSSH and restricting access to file transfer and only a particular type of file transfer.
First, the right place to tweak things is to use public key authentication and forced commands. So make a key pair for the account you want to give restricted access to, give the private key to the people who need to use the restricted service (they need to invoke scp as scp -i path/to/private_key), and drop the public key into the server account's .ssh/authorized_keys. Then, add options to the beginning of the line so that the line reads something like this (the line has been broken for readability but should be on one line without a backslash, newline or space character):
no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,\ command="/home/myaccount/check_log_and_run" ssh-dss AAAAB......
Then write the script "check_log_and_run" in the account's home directory. The script should be executable and contain commands to check, log and execute the command in environment variable SSH_ORIGINAL_COMMAND. In this example, we only accept uploading to a specific directory via scp:
#!/bin/sh cmd="$SSH_ORIGINAL_COMMAND" echo "`date` ($SSH_CLIENT): $cmd" >> ssh-command-log # check that command doesn't involve upwards path components in any # location to prevent, for instance, scp -t upload/../ echo "$cmd" | fgrep '..' >/dev/null && echo "Forbidden command: $cmd" && exit case "$cmd" in scp\ *-t\ upload) exec $cmd ;; scp\ *-t\ upload/*) exec $cmd ;; *) echo "Forbidden command: $cmd" ;; esac
In the case patterns, the first wildcard is meant to capture different use cases: when scp is invoked for sending files, it might spawn scp -t, scp -d -t, scp -r -t or scp -r -d -t on the server side. If you only want to allow downloading, allow scp -f. The invocation modes are documented here: http://blogs.sun.com/janp/entry/how_the_scp_protocol_works
You can also permit SFTP by specifying the SFTP server as an allowed command; you can find it like this:
$ grep sftp /etc/ssh/sshd_config Subsystem sftp /usr/lib/openssh/sftp-serverThis means that if you want to enable sftp, you need to allow the command /usr/lib/openssh/sftp-server to be executed.
Note! If you enable SFTP or don't restrict scp upload to a specific directory, there will be lots of files that you need to protect from trashing. The client can overwrite .ssh/authorized_keys to lift the restrictions, put arbitrary commands in .bashrc, etc. as explained in this article: http://www.snailbook.com/faq/restricted-scp.auto.html
If you want to be extra sure that files only ever end in your upload folder, you can fix the executed command to be "scp -t upload/" instead of "check_log_and_run". This will have the pleasant side effect that all uploaded files will land in upload/ irrespectible of what the client specifies, but it will have also the side effect of denying recursive copies (scp -t won't accept directories unless -r is also specified). "scp -r -t upload/" might be okay, though. OpenSSH's scp is cool enough to complain about "../" in file names on the protocol level, even if it accepts "../" for the -t parameter.