From: Kyle J. McKay Date: Sat, 24 Aug 2013 01:49:27 +0000 (-0700) Subject: jailsetup: refactor jailsetup.sh chroot setup X-Git-Url: https://repo.or.cz/w/girocco.git/commitdiff_plain/d7d01b66897a86857ade2f118154225d31650300 jailsetup: refactor jailsetup.sh chroot setup Move the system-specific portion of the chroot setup into a separate script with a system-specific name and then call it from the normal jailsetup.sh script. This permits chroot setups for different system types to be more easily supported in the future. --- diff --git a/chrootsetup_linux.sh b/chrootsetup_linux.sh new file mode 100644 index 0000000..f58523d --- /dev/null +++ b/chrootsetup_linux.sh @@ -0,0 +1,69 @@ +# chrootsetup_linux.sh + +# This file SHOULD NOT be executable! It is sourced by jailsetup.sh and +# SHOULD NOT be executed directly! + +# On entry the current directory will be set to the top of the chroot +# This script must perform platform-specific chroot setup which includes +# creating any dev device entries, setting up proc (if needed), setting +# up lib64 (if needed) as well as installing a basic set of whatever libraries +# are needed for a chroot to function on this platform. + +# This script must also define a pull_in_bin function that may be called to +# install an executable together with any libraries it depends on into the +# chroot. + +# Finally this script must install a suitable nc.openbsd compatible version of +# netcat into the chroot jail that's available as nc.openbsd and which supports +# connects to unix sockets. + +# We are designed to set up the chroot based on binaries from +# amd64 Debian lenny; some things may need slight modifications if +# being run on a different distribution. + +mkdir -p dev proc selinux +chown 0:0 proc selinux +rm -f lib64 +ln -s lib lib64 + +# Seed up /dev: +rm -f dev/null dev/zero dev/random dev/urandom +mknod dev/null c 1 3 +mknod dev/zero c 1 5 +mknod dev/random c 1 8 +mknod dev/urandom c 1 9 +chmod a+rw dev/null dev/zero dev/random dev/urandom + +# Extra directories +mkdir -p var/empty var/run/sshd +chmod 0444 var/empty + +# Bring in basic libraries: +rm -f lib/* +# ld.so: +cp -p -t lib /lib/ld-linux.so.2 +[ ! -d /lib64 ] || cp -p -t lib /lib64/ld-linux-x86-64.so.2 +# libc: +cp -p -t lib /lib/libc.so.6 /lib/libcrypt.so.1 /lib/libutil.so.1 /lib/libnsl.so.1 /lib/libnss_compat.so.2 /lib/libresolv.so.2 /lib/libdl.so.2 /lib/libgcc_s.so.1 + +# pull_in_bin takes two arguments: +# 1: the full path to a binary to pull in (together with any library dependencies) +# 2: the destination directory relative to the current directory to copy it to +# for example, "pull_in_bin /bin/sh bin" will install the shell into the chroot bin directory +# IMPORTANT: argument 1 must be a machine binary, NOT a shell script or other interpreted text +# IMPORTANT: text scripts can simply be copied in or installed as they don't have libraries to copy +# NOTE: it's expected that calling this function on a running chroot may cause temporary disruption +pull_in_bin() { + bin="$1"; dst="$2" + cp -p -t "$dst" "$bin" + # ...and all the dependencies. + ldd "$bin" | grep -v linux-gate | grep -v linux-vdso | grep -v ld-linux | grep '=>' | awk '{print $3}' | xargs -r -- cp -p -u -t lib +} + +# A catch all that needs to be called after everything's been pulled in +chroot_update_permissions() { + chown -R 0:0 bin dev lib sbin var +} + +# nothing special here, the nc.openbsd compatible utility is nc.openbsd +pull_in_bin /bin/nc.openbsd bin diff --git a/jailsetup.sh b/jailsetup.sh index 309260b..37582cd 100755 --- a/jailsetup.sh +++ b/jailsetup.sh @@ -3,21 +3,43 @@ # # If the first parameter is "dbonly", setup the database only # -# We are designed to set up the chroot based on binaries from -# amd64 Debian lenny; some things may need slight modifications if -# being run on a different distribution. +# We are designed to set up the chroot based on the output of +# `uname -s` by sourcing a suitable system-specific script. +# Unrecognized systems will generate an error. When using +# "dbonly" the setup of the chroot binaries is skipped so the +# output of `uname -s` does not matter in that case. set -e +curdir="`pwd`" +srcdir="$curdir/src" +getent="$srcdir/getent" . ./shlib.sh dbonly='' [ "$1" != "dbonly" ] || dbonly=1 -reserved_users="root sshd mob $cfg_cgi_user $cfg_mirror_user" +reserved_users="root sshd _sshd mob $cfg_cgi_user $cfg_mirror_user" + +# Require either sshd or _sshd user unless "dbonly" +sshd_user=sshd +if ! "$getent" passwd sshd >/dev/null && ! "$getent" passwd _sshd >/dev/null; then + if [ -n "$dbonly" ]; then + if [ ! -s etc/passwd ]; then + # Only complain on initial etc/passwd creation + echo "WARNING: no sshd or _sshd user, omitting entries from chroot etc/passwd" + fi + sshd_user= + else + echo "*** Error: You do not have required sshd or _sshd user in system." >&2 + exit 1 + fi +else + "$getent" passwd sshd >/dev/null || sshd_user=_sshd +fi -# Verify we have all we neeed. -if ! getent passwd "$cfg_mirror_user" >/dev/null; then +# Verify we have all we need +if ! "$getent" passwd "$cfg_mirror_user" >/dev/null; then echo "*** Error: You do not have \"$cfg_mirror_user\" user in system yet." >&2 exit 1 fi @@ -38,19 +60,29 @@ cd "$cfg_chroot" chmod 755 "$cfg_chroot" || echo "WARNING: Cannot chmod $cfg_chroot" -# Set up basic user/group configuration; if there is any already, -# we hope it's the same numbers and users. - +# Set up basic user/group configuration; if there isn't any already mobpass='' [ -n "$cfg_mob" ] || mobpass='x' mkdir -p etc if [ ! -s etc/passwd ]; then cat >etc/passwd <>etc/passwd <>etc/passwd <&2 + exit 1 + fi fi if [ ! -s etc/group ]; then @@ -61,7 +93,7 @@ fi mkdir -p etc/sshkeys etc/sshcerts for ruser in $reserved_users; do - touch etc/sshkeys/$ruser + touch etc/sshkeys/$ruser done chgrp $cfg_owning_group etc etc/sshkeys etc/sshcerts || echo "WARNING: Cannot chgrp $cfg_owning_group the etc directories" @@ -80,28 +112,79 @@ chmod -R g+w etc/sshkeys etc/sshcerts 2>/dev/null || [ -z "$dbonly" ] || exit 0 -chown root "$cfg_chroot" -chown $cfg_cgi_user etc etc/passwd etc/group -chown -R $cfg_cgi_user etc/sshkeys etc/sshcerts +# Make sure the system type is supported for chroot +sysname="$(uname -s | tr A-Z a-z || :)" +: ${sysname:=linux} +nosshdir= +# These equivalents may need to be expanded at some point +case "$sysname" in + *kfreebsd*) + sysname=linux;; + *darwin*) + sysname=darwin;; + *freebsd*) + sysname=freebsd;; + *linux*) + sysname=linux;; +esac + +chrootsetup="$curdir/chrootsetup_$sysname.sh" +if ! [ -r "$chrootsetup" -a -s "$chrootsetup" ]; then + echo "*** Error: $chrootsetup not found" + echo "*** Error: creating a chroot for a `uname -s` system is not supported" + exit 1 +fi -# First, setup basic directory structure -mkdir -p bin dev etc lib sbin ${cfg_jailreporoot#/} var/run proc -rm -f usr lib64 +# Set the user and group on the top of the chroot before creating anything else +chown 0:0 "$cfg_chroot" + +# First, setup basic platform-independent directory structure +mkdir -p bin dev etc lib sbin var/empty var/run ${cfg_jailreporoot#/} +rm -rf usr ln -s . usr -ln -s lib lib64 -# Seed up /dev: -rm -f dev/null dev/zero dev/random dev/urandom -mknod dev/null c 1 3 -mknod dev/zero c 1 5 -mknod dev/random c 1 8 -mknod dev/urandom c 1 9 -chmod a+rw dev/null dev/zero dev/random dev/urandom +# Now source the platform-specific script that is responsible for dev device +# setup, proc setup (if needed), lib64 setup (if needed) and basic library +# installation to make a chroot operational. Additionally it will define a +# pull_in_bin function that can be used to add executables and their library +# dependencies to the chroot and finally will install a suitable nc.openbsd +# compatible version of netcat that supports connections to unix sockets. +. "$chrootsetup" -# Set up sshd configuration: -mkdir -p var/run/sshd +# Now, bring in sshd, sh etc. +# The $chrootsetup script should have already provided a suitable nc.openbsd +install -p "$cfg_basedir/bin/git-shell-verify" bin +pull_in_bin "$cfg_basedir/bin/can_user_push" bin +pull_in_bin /bin/sh bin +pull_in_bin /bin/date bin +pull_in_bin /bin/mv bin +pull_in_bin /bin/rm bin +# If /sbin/sshd is already running within the chroot, we get Text file busy +pull_in_bin /usr/sbin/sshd sbin || : -mkdir -p etc/ssh +# ...and the bits of git we need, +# being sure to use the configured git and its --exec-path to find the pieces +git_exec_path="$("$cfg_git_bin" --exec-path)" +for i in git git-index-pack git-receive-pack git-shell git-update-server-info git-upload-archive \ + git-upload-pack git-unpack-objects git-show-ref git-config git-for-each-ref; do + pull_in_bin "$git_exec_path/$i" bin +done + +# Update permissions on the database files +chown $cfg_cgi_user:$cfg_owning_group etc etc/passwd etc/group +chown -R $cfg_cgi_user:$cfg_owning_group etc/sshkeys etc/sshcerts + +# Set up basic sshd configuration: +if [ -n "$nosshdir" ]; then + rm -rf etc/ssh + ln -s . etc/ssh + [ ! -f /etc/moduli ] || { cp -p /etc/moduli etc/; chown 0:0 etc/moduli; } +else + [ ! -e etc/ssh -o -d etc/ssh ] || rm -rf etc/ssh + mkdir -p etc/ssh + [ ! -f /etc/ssh/moduli ] || { cp -p /etc/ssh/moduli etc/ssh/; chown 0:0 etc/ssh/moduli; } +fi +mkdir -p var/run/sshd if [ ! -s etc/ssh/sshd_config ]; then cat >etc/ssh/sshd_config <' | awk '{print $3}' | xargs -r -- cp -p -u -t lib -} - -install -p "$cfg_basedir/bin/git-shell-verify" bin -install -p "$cfg_basedir/bin/can_user_push" bin -pull_in_bin /bin/sh bin -pull_in_bin /bin/nc.openbsd bin -pull_in_bin /bin/date bin -pull_in_bin /bin/mv -pull_in_bin /bin/rm -# If /sbin/sshd is already running within the chroot, we get Text file busy. -pull_in_bin /usr/sbin/sshd sbin || : +# Set the final permissions on the binaries and perform any final twiddling +chroot_update_permissions -# ...and the bits of git we need. -for i in git git-index-pack git-receive-pack git-shell git-update-server-info git-upload-archive \ - git-upload-pack git-unpack-objects git-show-ref git-config git-for-each-ref; do - if [ -e /usr/lib/git-core/$i ]; then - pull_in_bin /usr/lib/git-core/$i bin - elif [ -e /usr/libexec/git-core/$i ]; then - pull_in_bin /usr/libexec/git-core/$i bin - else - pull_in_bin /usr/bin/$i bin - fi -done +# Change the owner of the sshd-related files +chown 0:0 etc/ssh/ssh_* etc/ssh/sshd_* echo "--- Add to your boot scripts: mount --bind $cfg_reporoot $cfg_chroot/$cfg_jailreporoot" echo "--- Add to your boot scripts: mount --bind /proc $cfg_chroot/proc"