-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 At some point hitherto, Derek D. Martin hath spake thusly: > As I mentioned I would, I wrote a quick dummy shell to allow scp and > sftp, but not anything else. [SNIP] > The major problem is that if one of the arguments to scp is a > filename that contains a (quoted) space, the spaces will be treated > as argument delimitors. I didn't make much effort to do a whole lot > of processing on the command line, so any space that appears in > argv[2] will be treated as an argument delimitor for the command > which is exec'd. I can't even believe how easy to fix this turned out to be! As it turns out, POSIX.2 defines wordexp(3) to do expansion of command line arguments. It's unfortunately not documented on Linux, or at least not on my RH 7.[12] systems. I ran into it by accident when I came across the glob(3) function. The manpage mentions wordexp(3), though there is no manpage for it. But there is one on my HP-UX system... Ok, so for those who were interested, here's the new and improved rssh. It now has the ability to restrict the user to either scp or sftp, or both, depending on how you name the binary. The intent is to provide all three, by creating the binary called rssh, and providing links to it (either hard or soft, but I'd probably choose soft myself) called scpsh and sftpsh. This code is, AFAIK, bug free, and does the job 100%. It really could use a configure script and a Makefile, but until I write them, there's a little cheesy install script at the end. Also, remember to change the path to the sftp-server binary if it's different on your platform. - ----------- cut here ---------------------- /* * rssh.c - restricted shell for ssh to allow scp or sftp only * * Copyright 2002 Derek D. Martin . * * This program is licensed under a BSD-style license, as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include /* for sftp */ #define _PATH_SFTP_SERVER "/usr/libexec/openssh/sftp-server" #define _ALLOW_SCP 1 #define _ALLOW_SFTP (1 << 1) void do_exit_message( int flags ); char **build_arg_vector( char *str ); extern int errno; int main( int argc, char **argv ) { char **argvec; int allowed_command = 0; int flag = 0; /* convert argv[2] into an arg vector suitable for execvp() */ argvec = build_arg_vector(argv[2]); /* check argv[0] for scp or sftp to see what's allowed */ if ( !strcmp(basename(argv[0]), "scpsh") ) allowed_command = _ALLOW_SCP; if ( !strcmp(basename(argv[0]), "sftpsh") ) allowed_command = _ALLOW_SFTP; if ( !strcmp(basename(argv[0]), "rssh") ) allowed_command = _ALLOW_SFTP | _ALLOW_SCP; /* q&d arg count check */ if ( argc < 3 ) do_exit_message(allowed_command); /* if first arg is anything but -c, it's no good */ if ( strcmp("-c", argv[1]) ) do_exit_message(allowed_command); /* check to see if we got an allowed command */ if ( (!strcmp(argvec[0], _PATH_SFTP_SERVER)) && (allowed_command & _ALLOW_SFTP ) ) flag = 1; if ( (!strcmp(argvec[0], "scp") && (allowed_command & _ALLOW_SCP)) ) flag = 1; /* if no allowed command, print message and exit */ if ( !flag ) do_exit_message(allowed_command); /* if all that passed, exec the relevant command */ execvp(argvec[0], argvec); /* we only get here if the exec fails */ fprintf(stderr, "rssh: excecvp() failed. "); switch (errno){ case EACCES: case ENOTDIR: case ENOENT: fprintf(stderr, "%s is not an executable file, or permission denied.\n\n", argv[2]); break; case EPERM: fprintf(stderr, "FS mounted nosuid or process is being traced\n" "(and you are not root)\n\n"); break; default: fprintf(stderr, "an unknown error occurred.\n\n"); } exit(1); } char **build_arg_vector( char *str ) { wordexp_t result; if ( (wordexp(str, &result, 0)) ){ fprintf(stderr, "rssh: error expanding arguments\n"); exit(1); } return result.we_wordv; } void do_exit_message( int flags ) { if ( !flags ){ fprintf(stderr, "\nrssh is not installed correctly!\n"); exit(1); } fprintf( stderr, "\nThis account is restricted, for the use of "); switch (flags){ case (_ALLOW_SCP | _ALLOW_SFTP): fprintf(stderr, "scp or sftp"); break; case _ALLOW_SCP: fprintf(stderr, "scp"); break; case _ALLOW_SFTP: fprintf(stderr, "sftp"); break; default: fprintf(stderr, "\n\nrssh error! This can only happen if rssh" " is not installed correctly.\n Please see your " "system administrator.\n\n"); exit(1); } fprintf(stderr, " only.\nIf you believe this is in error, please contact" " your system\nadministrator.\n\n" ); exit(0); } - -------- cut here ----------------------- #!/bin/sh # cheesy rssh install script mycwd=`pwd` installdir=/usr/local/bin cc -o rssh rssh.c cp rssh $installdir chmod 111 $installdir/rssh chown root.root $installdir/rssh cd $installdir ln -s rssh scpsh ln -s rssh sftpsh cd $mycwd - ----- cut here ------------------------- - -- Derek Martin ddm@pizzashack.org - --------------------------------------------- I prefer mail encrypted with PGP/GPG! GnuPG Key ID: 0x81CFE75D Retrieve my public key at http://pgp.mit.edu Learn more about it at http://www.gnupg.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE9XIBddjdlQoHP510RAunAAKCouZzPePV5Dle4GnVxGekIcEd1rQCfeb6d SUfVMwvd6d3XI9CnAYd5yTQ= =YrJ5 -----END PGP SIGNATURE-----