Codebase list libnet-sftp-sftpserver-perl / HEAD
HEAD

Tree @HEAD (Download .tar.gz)

NAME
    Net::SFTP::SftpServer - A Perl implementation of the SFTP subsystem with
    user access controls

SYNOPSIS
      use Net::SFTP::SftpServer;

      my $sftp = Net::SFTP::SftpServer->new();

      $sftp->run();

DESCRIPTION
    A Perl port of sftp-server from openssh providing access control on a
    per user per command basis and improved logging via syslog

    The limitations compared with the openssh implementation are as follows:

    *   Only files and directories are dealt with - other types are not
        returned on readdir

    *   a virtual chroot is performed - / is treated as the users home
        directory from the client perspective and all file access to / will
        be in /<home_path>/<username> home_path is defined on object
        initialisation not accessed from /etc/passwd

    *   all sym linked files or directories are hidden and not accessible on
        request

    *   symlink returns permission denied

    *   readlink returns file does not exist

    *   setting of stats (set_stat or set_fstat) is disabled - client will
        receive permission denied

    *   permissions for file or dir is defaulted - default set on object
        initialisation

USAGE
    Basic usage:

      use Net::SFTP::SftpServer;

    Import options:

      :LOG    - Import logging functions for use in callbacks
      :ACTION - Import constants for Allow/Deny of actions

    Configuring syslog:

    Syslog output mode must be configured in the use statement of the module
    as follows:

      use Net::SFTP::SftpServer ( { log => 'local5' }, qw ( :LOG :ACTIONS ) );

    Net::SFTP::SftpServer will default to using "daemon" see your system's
    syslog documentation for more details

    Options for object initialisation:

    *   debug

        Log debug level information. Deault=0 (note this will create very
        large log files - use with caution)

    *   home

        Filesystem location of user home directories. default=/home

    *   file_perms

        Octal file permissions to force on creation of files. Default=0666
        or permissions specified by file open command from client

    *   dir_perms

        Octal dir permissions to force on creation of directories.
        Default=0777 or permissions specified by mkdir command from client

    *   on_file_sent, on_file_received

        References to callback functions to be called on complete file sent
        or received. Function will be passed the full path and filename on
        the filesystem as a single argument

    *   use_tmp_upload

        Use temporary upload filenames while a file is being uploaded - this
        allows a monitoring script to know which files are in transit
        without having to watch file size. Will be done transparantly to the
        user, the file will be renamed to the original file name when close.
        The temportary extension is ".SftpXFR.$$". Default=0

    *   max_file_size

        Maximum file size (in bytes) which can be uploaded. Default=0 (no
        limit)

    *   valid_filename_char

        Array of valid characters for filenames

    *   allow, deny

        Actions allowed or denied - see "PERMISSIONS" for details, Default
        is to allow ALL.

    *   fake_ok

        Array of actions (see action contants in "PERMISSIONS") which will
        be given response SSH2_FX_OK instead of SSH2_FX_PERMISSION_DENIED
        when denied by above deny options. Default=[]

PERMISSIONS
      ALL                      - All actions
      NET_SFTP_SYMLINKS        - Symlinks in paths to files (recommended deny to enforce chroot)
      NET_SFTP_RENAME_DIR      - Rename directories (recommended deny if also denying SSH2_FXP_MKDIR)
      SSH2_FXP_OPEN
      SSH2_FXP_CLOSE
      SSH2_FXP_READ
      SSH2_FXP_WRITE
      SSH2_FXP_LSTAT
      SSH2_FXP_STAT_VERSION_0
      SSH2_FXP_FSTAT
      SSH2_FXP_SETSTAT         - Automatically denied, not implemented in module
      SSH2_FXP_FSETSTAT        - Automatically denied, not implemented in module
      SSH2_FXP_OPENDIR
      SSH2_FXP_READDIR
      SSH2_FXP_REMOVE
      SSH2_FXP_MKDIR
      SSH2_FXP_RMDIR
      SSH2_FXP_STAT
      SSH2_FXP_RENAME
      SSH2_FXP_READLINK        - Automatically denied, not implemented in module
      SSH2_FXP_SYMLINK         - Automatically denied, not implemented in module

CALLBACKS
    Callback functions can be used to perform actions when files are sent or
    received, for example move a fully downloaded file to a processed
    directory or move a received file into an input directory.

LOGGING
    If :LOG is used when including Net::SFTP::SftpServer the following
    logging functions will be available:

      logError    - syslog with a log level of error
      logWarning  - syslog with a log level of warning
      logGeneral  - syslog with a log level of info
      logDetail   - syslog with a log level of debug, unless object was created with debug=>1 then syslog with a level of info

HARDENED EXAMPLE SCRIPT
    The following example script shows how this module can be used to give
    far greater control over what is allowed on your SFTP server.

    This setup is aimed at admins which want to user SFTP uploads but do not
    wish to grant users a system account. You will also need to set both the
    SFTP subsystem and the user's shell to the sftp script, eg
    /usr/local/bin/sftp-server.pl

    This configuration:

    *   Enforces that users can only access the sftp script, not an ssh
        shell.

    *   Chroots them into their home directory in /var/upload/sftp

    *   Sets all file permissions to 0660 and does not permit users to
        change them.

    *   Does not allow symlinks, making directories or renaming directories,
        but allows all other normal actions.

    *   Has a max upload filesize of 200Mb

    *   Has a script memory limit of 100Mb for safety

    *   Will log actions by user sftptest in debug mode

    *   Will only allow alphanumeric plus _ . and - in filenames

    *   Will call ActionOnSent and ActionOnReceived respectively when files
        have been sent or received.

      #!/usr/local/bin/perl

      use strict;
      use warnings;
      use Net::SFTP::SftpServer ( { log => 'local5' }, qw ( :LOG :ACTIONS ) );
      use BSD::Resource;        # for setrlimit

      use constant DEBUG_USER => {
        SFTPTEST => 1,
      };


      # Security - make sure we have started this as sftp not ssh
      unless ( scalar @ARGV == 2 and
               $ARGV[0] eq '-c'  and
               ($ARGV[1] eq '/usr/local/bin/sftp-server.pl') ){

             logError "SFTP connection attempted for application $ARGV[0] - exiting";
             print "\n\rYou do not have permission to login interactively to this host.\n\r\n\rPlease contact the system administrator if you believe this to be a configuration error.\n\r";
             exit 1;
      }

      my $MEMLIMIT = 100 * 1024 * 1024; # 100 Mb

      # hard limits on process memory usage;
      setrlimit( RLIMIT_RSS,  $MEMLIMIT, $MEMLIMIT );
      setrlimit( RLIMIT_VMEM, $MEMLIMIT, $MEMLIMIT );

      my $debug = (defined DEBUG_USER->{uc(getpwuid($>))} and DEBUG_USER->{uc(getpwuid($>))}) ? 1 : 0;

      my $sftp = Net::SFTP::SftpServer->new(
        debug               => $debug,
        home                => '/var/upload/sftp',
        file_perms          => 0660,
        on_file_sent        => \&ActionOnSent,
        on_file_received    => \&ActionOnReceived,
        use_tmp_upload      => 1,
        max_file_size       => 200 * 1024 * 1024,
        valid_filename_char => [ 'a' .. 'z', 'A' .. 'Z', '0' .. '9', '_', '.', '-' ],
        deny                => ALL,
        allow               => [ (
                                    SSH2_FXP_OPEN,
                                    SSH2_FXP_CLOSE,
                                    SSH2_FXP_READ,
                                    SSH2_FXP_WRITE,
                                    SSH2_FXP_LSTAT,
                                    SSH2_FXP_STAT_VERSION_0,
                                    SSH2_FXP_FSTAT,
                                    SSH2_FXP_OPENDIR,
                                    SSH2_FXP_READDIR,
                                    SSH2_FXP_REMOVE,
                                    SSH2_FXP_STAT,
                                    SSH2_FXP_RENAME,
                                 )],
        fake_ok             => [ (
                                    SSH2_FXP_SETSTAT,
                                    SSH2_FXP_FSETSTAT,
                                 )],
      );

      $sftp->run();

      sub ActionOnSent {
        my $filename = shift;
         ## Do Stuff
      }

      sub ActionOnReceived {
        my $filename = shift;
         ## Do Stuff
      }

DEPENDENCIES
      Stat::lsMode
      Fcntl
      POSIX
      Sys::Syslog
      Errno

SEE ALSO
    Sftp protocol
    <http://www.openssh.org/txt/draft-ietf-secsh-filexfer-02.txt>

AUTHOR
      Simon Day, Pirum Systems Ltd
      cpan <at> simonday.info

COPYRIGHT AND LICENSE
    Based on sftp-server.c Copyright (c) 2000-2004 Markus Friedl. All rights
    reserved.

    Ported to Perl and extended by Simon Day Copyright (c) 2009 Pirum
    Systems Ltd. All rights reserved.

    Permission to use, copy, modify, and distribute this software for any
    purpose with or without fee is hereby granted, provided that the above
    copyright notice and this permission notice appear in all copies.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.