allowing scp but not ssh (here's how) REVISITED

Scott Prive Scott.Prive at storigen.com
Fri Aug 16 10:44:36 EDT 2002


You might consider creating a small webpage, or a project on Sourceforge. 

My thinking here is not to put more time into it (assume it's done), but to get wider exposure for your code: there's an educational aspect, if someone may offer you interesting patches, or plugs a weakness never considered.

It's easy to make a suggestion, when you don't have to do the dirty work. Heh :-)

-Scott


-----Original Message-----
From: Derek D. Martin [mailto:ddm at pizzashack.org]
Sent: Friday, August 16, 2002 12:33 AM
To: BLU Users' Group
Subject: Re: allowing scp but not ssh (here's how) REVISITED


-----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 <ddm at pizzashack.org>.
 *
 * 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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>
#include <wordexp.h>

/* 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 at 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-----
_______________________________________________
Discuss mailing list
Discuss at blu.org
http://www.blu.org/mailman/listinfo/discuss



More information about the Discuss mailing list