In the manual page for sshd, the section "AUTHORIZED_KEYS FILE FORMAT" indicates that a public key can be modified to include 'command="command"' and within this paragraph it is indicated that "This option might be useful to restrict certain public keys to perform just a specific operation". By (slightly) abusing this feature one can restrict public key authentication to only allow scp, i.e., no shell or command execution, for a specific key. 1. Modify the public key in .ssh/authenticated_keys to include 'command="scp-only"'. 2. Apply the attached patch to session.c, RCSID("$OpenBSD: session.c,v 1.191 2005/12/24 02:27:41 djm Exp $"), included in the source for portable openssh-4.3p2. The patch takes advantage of the check for the existence of a value in forced_command. Instead of simply replacing the command from the remote user with the value in forced_command, the value of forced_command is checked for the "magic value" of "scp-only" (or some more suitable value or convention). If the forced_command begins with this magic value and the command is for scp then the substitution is not made and the value of command is allowed to continue. On the other hand, if the command is not for scp then fatal() is called to terminate the connection. With suitable restrictions on the users home directory, .ssh directory, and the .ssh/authorized_keys file, it seems that a fairly tight restriction forbidding shell or remote command execution can be achieved while still allowing scp to function normally. The patch includes a bit to run through the user submitted scp command and truncate it at the first ';'. This may or may not be a useful exercise. Having it does cause a compiler warning "assignment discards qualifiers from pointer target type" because command is a const. My thought was that it might be better to truncate then to allow for any funny business that might be included after the ';'. The position in session.c where the patch is applied might also be a good place to put a more general hook to control activities related to a particular authentication key by further abusing the value of 'command="some_other_magic_value"' that is included in the public key where "some_other_magic_value" follows a convention that allows meaningful magic values to be recognized as not being any actual command (the original intent of command=).
Created attachment 1093 [details] Patch session.c
An alternative to the above hack might be to recognize a new option, e.g., "scp-only" and change auth_parse_options() to recognize this option and set a global variable similar to what happens with, say, "no-port-forwarding". Then change the patch to check for this global variable and act accordingly if it is set instead of abusing the command= option with "magic values". Then to get the "only scp with this key" behavior you could insert "scp-only" at the beginning of the key instead of command="scp-only". I'd be happy to provide this patch if it has a better chance of acceptance.
Created attachment 1094 [details] Implements "scp-only" as separate option The cleaner approach of implementing the scp-only behavior as a separate option instead of abusing the command= option. Tested between two Slackware boxes. Running the scp command from the "client" behaves as expected. Attempting to open a shell or remotely run a command results in the client being rudely disconnected. Related failure message are sent to syslog via fatal().
OpenSSH now has a "Match" directive that supports proscriptive control of the user's command. We won't be building in special glue for scp, but you can use it (along with the new chroot support) to force users to be able to run sftp only. If you absolutely require scp, then you can use the same mechanism to force them to use a restrictive shell like "scponly".
Mass update RESOLVED->CLOSED after release of openssh-5.1