[scponly] script to check for common chroot problems

J.D. Baldwin baldwin at panix.com
Wed Mar 1 17:25:36 EST 2006


On Thu, Feb 23, 2006 at 12:33:50AM -0700, Daniel Webb wrote:
> Permissions problem.  My umask changed somewhere along the line.
> /etc/passwd in the chroot dir didn't have world-readable.
> 
> It would be nice if scp had just *said* that (like "permission
> denied reading /etc/passwd") instead of "unknown user"...

Maybe it just uses PAM or library calls that only tell it whether a
user was found.

> Anyhow, if you are a reader finding this post through a search
> engine, here are the most common reasons for "unknown user" with
> scp:
> 
> 1. Missing, invalid, or permission denied /etc/passwd
> 2. Missing /lib/libnss<something>
> 3. Missing /etc/nsswitch.conf (doesn't apply in most cases)
> 
> Also, make sure you find all libraries you need by using ldd on
> every binary in your chroot.

I have a shell script to build the chroot directories and their
contents, based on predefined binary executables and then looping over
those to check library support, readability of config files, etc.

I have adapted this script to check these things without modifying
them.  I have included it below.  Please try it out and let me know
whether you find it useful.  It may even be worthwhile distributing it
with future revs of scponly; you are welcome to do so.  I am also
interested in any suggestions for improvements.

#!/bin/ksh

# Checks permissions and links for the chroot directory

# Usage:  ./chroot_check.ksh <chroot_dir>
#     where <chroot_dir> is the top-level directory for chroot-ed
#     users

# Written 6/2005, revised 3/2006 by J.D. Baldwin 
#    <scponlyscript at baldwin.users.panix.com>

# Written and tested on Solaris 9 / 10 only.  The script ought, in 
# general, to work on other UNIX-like operating systems, but you may
# have to tweak it -- for example, if your OS's ldd has incompatible
# output.

# Use and distribute freely.  Provided without warranty of any kind.
# Use ordinary care when executing scripts found on the Internet (like
# this one.)

##### HOUSEKEEPING #####

CHR_DIR=$1

# Took passwd and chown out of this list

USR_BIN_BINARIES='chgrp chmod groups ln mkdir rm chmod echo id ls mv
                    pwd rmdir'
USR_LOCAL_BIN_BINARIES='rsync scp'
USR_LOCAL_LIBEXEC_BINARIES='sftp-server'

ETC_CONFIG_FILES='passwd group nsswitch.conf'

PROBLEMS_FLAGGED=0

LDD_BIN=''
LDD_BIN=$(which ldd 2>/dev/null)

if [[ ! -x $LDD_BIN ]]
then
    fail 5 "Cannot find ldd binary in path"
fi

##### FUNCTION DEFINITIONS #####

function fail
{
# Usage:  fail <errcode> "<message>" 
    echo "\nFATAL ERROR:  $2"
    echo
    exit $1
}

function flag_problem
{
# Usage:  flag_problem "<message>"

    if [[ $PROBLEMS_FLAGGED -eq 0 ]]
    then
        echo "POSSIBLE PROBLEM(S) WITH BINARIES UNDER $CHR_DIR"
        PROBLEMS_FLAGGED=1
    fi
    echo "  $1"
}

function check_libraries 
{
    BINPATH=$1

    PROBLEMS_SO_FAR=0
    $LDD_BIN $1 | awk '{print $NF}' | while read a
    do
        LIBPATH=$CHR_DIR/$a
	if [[ ! -r $LIBPATH ]]
        then
	    if [[ $PROBLEMS_SO_FAR -eq 0 ]]
            then
                flag_problem "Problem(s) with supporting libraries for $BINPATH"
                PROBLEMS_SO_FAR=1
            fi
            flag_problem "   File $LIBPATH does not exist or not readable"
        fi
    done
}

function check_binaries
{
    # Usage:  check_binaries <location_dir> <list_of_files>
    #     checks in $CHR_DIR/<location_dir> over list <list_of_files> 
    #       to ensure they are ordinary files that are executable, then
    #       checks for supporting library files as determined by ldd
    LOCDIR=$CHR_DIR/$1
    shift
    for a in $*
    do
        if [[ -f $LOCDIR/$a && -x $LOCDIR/$a && ! -L $LOCDIR/$a ]]
        then
           #noop
           echo ok > /dev/null
        else
	   flag_problem "$LOCDIR/$a not a file or not executable"
        fi

        check_libraries $LOCDIR/$a

    done
}

function check_readable
{
    # Usage:  check_readable <location_dir> <list_of_files>
    #     checks in <location_dir> over list <list_of_files> to make
    #       sure they are ordinary files that are readable (at least
    #       by this process)
    LOCDIR=$1
    shift
    for a in $*
    do
        if [[ -f $LOCDIR/$a && -r $LOCDIR/$a && ! -L $LOCDIR/$a ]]
        then
           #noop
           echo ok > /dev/null
        else
	   flag_problem "$LOCDIR/$a not found or not readable"
        fi
    done
}

##### MAIN PROGRAM #####

if [[ -z $CHR_DIR || ! -z $2 ]]
then
    fail -1 "Usage:  ./chroot_setup.ksh <chroot_dir>"
fi

if [[ ! -d $CHR_DIR ]]
then
    fail -1 "Cannot find directory $CHR_DIR"
fi
    
cd $CHR_DIR

if [[ $? -ne 0 ]]
then
    fail -3 "Cannot cd to $CHR_DIR"
fi

check_binaries /usr/bin $USR_BIN_BINARIES
check_binaries /usr/local/bin $USR_LOCAL_BIN_BINARIES
check_binaries /usr/local/libexec $USR_LOCAL_LIBEXEC_BINARIES

check_readable /etc $ETC_CONFIG_FILES




More information about the scponly mailing list