pavement

SSH, limiting to SCP or Rsync only

From FreeBSDwiki
(Difference between revisions)
Jump to: navigation, search
m
(no mention of the scponly port? someone has done all this work already...)
Line 1: Line 1:
 
Fairly commonly, you may want to set something up so that a user can [[scp]] or [[rsync]] files to (or from) a server of yours, but you don't want to allow them a shell account.  That's not ENTIRELY possible, but you can manage something along those lines by either creating a [[jail]] for them, or, more simply, by forcing them to use a very very neutered custom [[shell]] when they log in that will only allow them access to the commands that you want them to be able to use.
 
Fairly commonly, you may want to set something up so that a user can [[scp]] or [[rsync]] files to (or from) a server of yours, but you don't want to allow them a shell account.  That's not ENTIRELY possible, but you can manage something along those lines by either creating a [[jail]] for them, or, more simply, by forcing them to use a very very neutered custom [[shell]] when they log in that will only allow them access to the commands that you want them to be able to use.
  
You can use the small C program at the bottom of this article to create a [[custom shell]] for user accounts that you want to be able to use [[scp]], [[sftp]], or [[rsync]] with SSH transport, but not to have an actual shell available.  Remember that this limits "snoopiness" to some degree but is NOT any kind of hardcore lockout, as any files or directories that the user has read permissions on can be [[scp]]'ed or [[rsync]]'ed over to their machine for local perusal, and any which they have write permissions on can be OVERWRITTEN with versions [[scp]]'ed or [[rsync]]'ed over FROM their machine!
+
The general idea is to create a [[custom shell]] for user accounts that you want to be able to use [[scp]], [[sftp]], or [[rsync]] with SSH transport, but not to have an actual shell available.  Remember that this limits "snoopiness" to some degree but is NOT any kind of hardcore lockout, as any files or directories that the user has read permissions on can be [[scp]]'ed or [[rsync]]'ed over to their machine for local perusal, and any which they have write permissions on can be OVERWRITTEN with versions [[scp]]'ed or [[rsync]]'ed over FROM their machine!
  
Once you've saved the code at the bottom of the article to a work directory as '''scpsftprsynconly.c''', you can compile it and assign it as a user's shell with [[pw]] or [[chsh]]:
+
==scponly==
 +
 
 +
[http://www.sublimation.org/scponly/ scponly] is open-source software that offers this functionality. It is available through the ports collection under /usr/ports/shells/scponly.
 +
 
 +
==scpsftprsynconly==
 +
 
 +
An alternative is to use the small C program at the bottom of this article. Once you've saved the code to a work directory as '''scpsftprsynconly.c''', you can compile it and assign it as a user's shell with [[pw]] or [[chsh]]:
  
 
  ph34r# '''gcc scpsftprsynconly.c -o /usr/local/bin/scpsftprsynconly'''
 
  ph34r# '''gcc scpsftprsynconly.c -o /usr/local/bin/scpsftprsynconly'''

Revision as of 19:43, 25 April 2006

Fairly commonly, you may want to set something up so that a user can scp or rsync files to (or from) a server of yours, but you don't want to allow them a shell account. That's not ENTIRELY possible, but you can manage something along those lines by either creating a jail for them, or, more simply, by forcing them to use a very very neutered custom shell when they log in that will only allow them access to the commands that you want them to be able to use.

The general idea is to create a custom shell for user accounts that you want to be able to use scp, sftp, or rsync with SSH transport, but not to have an actual shell available. Remember that this limits "snoopiness" to some degree but is NOT any kind of hardcore lockout, as any files or directories that the user has read permissions on can be scp'ed or rsync'ed over to their machine for local perusal, and any which they have write permissions on can be OVERWRITTEN with versions scp'ed or rsync'ed over FROM their machine!

scponly

scponly is open-source software that offers this functionality. It is available through the ports collection under /usr/ports/shells/scponly.

scpsftprsynconly

An alternative is to use the small C program at the bottom of this article. Once you've saved the code to a work directory as scpsftprsynconly.c, you can compile it and assign it as a user's shell with pw or chsh:

ph34r# gcc scpsftprsynconly.c -o /usr/local/bin/scpsftprsynconly
ph34r# pw usermod dave -s /usr/local/bin/scpsftprsynconly

Now user dave can use scp or sftp (if sftp is set up) or rsync (if rsync is available) commands with ssh, but cannot actually log into the box - remotely OR locally I might add! Here's a test showing ssh and local logins failing, but an scp succeeding:

ph34r# ssh dave@localhost
This account is currently not available.
ph34r# su dave
This account is currently not available.
ph34r# scp dave@localhost:/usr/local/bin/scpsftprsynconly .
Password:
scpsftprsynconly                               100%  130KB 129.7KB/s   00:00

And there we have it - it works. Note that you might want to actually LOOK at the code; it's assuming that rsync and scp will be findable via the system's PATH environment variable. If that's not the case, or if you're feeling a little extra-paranoid and want to hard-code in assurance that ONLY the particular executable you want - say, /usr/local/bin/rsync - can be run, you might want to hack that in the way you want it; just keep in mind that if your custom shell is looking to allow just rsync, it WON'T allow /usr/local/bin/rsync and vice versa. So you might wind up having to mess about with flags for your scp and rsync commands from remote machines to specify paths, if you screw around with that stuff.

Enjoy!

 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 /*
 **  Original by Patric Draper <http://www.pdrap.org/about/>
 **
 **  Changes on 13-Mar-2004 by Msquared <http://www.msquared.id.au/>
 **
 **    * fixed bug in args to realloc()
 **    * fixed bug in parameter checks (validates entire command name)
 **    * Modified to work with OpenSSH SFTP
 **    * Added rsync support
 **
 **  This code is in the public domain.  No warranty.  If it breaks,
 **  you can dispose of it as you see fit.
 **
 **  Build with DEBUG to save calling arguments to /tmp/scpshell.log
 **  This is useful to add new protocols, debug existing calls, etc.
 */
 
 char * restrictmsg = "This account is currently not available.\n";
 
 int main (int argc, char *argv []) {
         char **newargs = NULL;
         char *newbuff = NULL;
         int i;
         char *s;
 
 #ifdef DEBUG
 
         FILE * log = fopen("/tmp/scpshell.log","a+");
         if ( log ) {
                 char **par = argv;
                 while ( *par )
                         fprintf ( log, "[%s] ", *par++ );
                 fprintf ( log, "\n" );
                 fclose(log);
         }
 
 #endif
 
         if (argc < 3) {
                 printf (restrictmsg);
                 return 1;
         }
         if ((strncmp (argv [2], "scp ", 4) != 0) &&
             (strncmp (argv [2], "/usr/libexec/openssh/sftp-server", 33) != 0) &&
             (strncmp (argv [2], "rsync ", 6) != 0)) {
                 printf (restrictmsg);
                 return 2;
         }
         i = 0;
         newbuff = strdup(argv[2]);
         s = strtok (newbuff, " ");
         do {
                 newargs = (char **) realloc (newargs, ++i*sizeof(*newargs));
                 newargs [i - 1] = strdup (s);
         } while ((s = strtok (NULL, " ")) != NULL);
 
         newargs = (char **) realloc (newargs, ++i*sizeof(*newargs));
         newargs [i - 1] = NULL;
 
         execvp (newargs [0], newargs);
 
         return 0;
 }
Personal tools