From e616b2d3163675d01b2ee0b49f9a0d48e8901156 Mon Sep 17 00:00:00 2001 From: lars Date: Mon, 12 Dec 2005 22:32:22 +0000 Subject: [PATCH] seperated actions that need root privilege changed default mount point to /var/lib/cryptobox/mnt --- DEBIAN/control | 2 +- DEBIAN/postinst | 11 + DEBIAN/postrm | 5 + cbox-tree.d/etc/cryptobox/cryptobox.conf | 15 +- cbox-tree.d/mnt/cb-etc/.placeholder | 1 - cbox-tree.d/mnt/crypto/.placeholder | 1 - cbox-tree.d/usr/lib/cgi-bin/cryptobox.pl | 2 +- cbox-tree.d/usr/lib/cryptobox/cbox-manage.sh | 220 +++++------- .../usr/lib/cryptobox/cbox-root-actions.sh | 315 ++++++++++++++++++ .../usr/share/doc/cryptobox/README.Debian | 4 +- .../var/lib/cryptobox/config/.placeholder | 1 + .../var/lib/cryptobox/mnt/.placeholder | 1 + 12 files changed, 432 insertions(+), 146 deletions(-) delete mode 100644 cbox-tree.d/mnt/cb-etc/.placeholder delete mode 100644 cbox-tree.d/mnt/crypto/.placeholder create mode 100755 cbox-tree.d/usr/lib/cryptobox/cbox-root-actions.sh create mode 100644 cbox-tree.d/var/lib/cryptobox/config/.placeholder create mode 100644 cbox-tree.d/var/lib/cryptobox/mnt/.placeholder diff --git a/DEBIAN/control b/DEBIAN/control index 6c9a042..4a8e94a 100644 --- a/DEBIAN/control +++ b/DEBIAN/control @@ -3,7 +3,7 @@ Version: 0.3.0-1 Section: base Priority: optional Architecture: all -Depends: bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), perl, httpd-cgi, hashalot, libconfigfile-perl, cryptsetup-luks, dmsetup, at +Depends: bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), perl, httpd-cgi, hashalot, libconfigfile-perl, cryptsetup-luks, dmsetup, at, sudo Suggests: stunnel, cron, iptables, samba Maintainer: Lars Kruse Description: Web interface for encrypting fileserver diff --git a/DEBIAN/postinst b/DEBIAN/postinst index 8c9e16a..bb6ed6e 100755 --- a/DEBIAN/postinst +++ b/DEBIAN/postinst @@ -5,4 +5,15 @@ update-rc.d cryptobox defaults 98 invoke-rc.d cryptobox restart +if grep -q "cryptobox package.*HEADER" /etc/sudoers + then true + else echo "Adding a new (disabled) entry to /etc/sudoers" + cat >>/etc/sudoers <<-EOF + ######### Automatically inserted by cryptobox package - do not remove - HEADER ###### + # read /usr/share/doc/cryptobox/SECURITY carefully before enabling the following line + #www-data ALL=NOPASSWD:/usr/lib/cryptobox/cbox-root-actions.sh + ######### Automatically inserted by cryptobox package - do not remove - FOOTER ###### + EOF + fi + true diff --git a/DEBIAN/postrm b/DEBIAN/postrm index a81615c..2d8c2b2 100755 --- a/DEBIAN/postrm +++ b/DEBIAN/postrm @@ -3,5 +3,10 @@ # remove symlinks in /etc/rc?.d [ "$1" = "purge" ] && update-rc.d cryptobox remove +if [ "$1" = "purge" ] && grep -q "cryptobox package.*HEADER" /etc/sudoers + then echo "Removing entry from /etc/sudoers" + sed -i "/cryptobox package.*HEADER/,/cryptobox package.*FOOTER/d" /etc/sudoers + fi + # return without error true diff --git a/cbox-tree.d/etc/cryptobox/cryptobox.conf b/cbox-tree.d/etc/cryptobox/cryptobox.conf index 16d92b0..7b43915 100644 --- a/cbox-tree.d/etc/cryptobox/cryptobox.conf +++ b/cbox-tree.d/etc/cryptobox/cryptobox.conf @@ -3,8 +3,13 @@ LANGUAGE=en NET_IFACE=eth0 -SAMBA_USER=nobody -SCAN_DEVICES="hda hdb hdc hdd hde hdf hdg scd0 scd1 scd2 scd3 sg sda sdb sdc sdd" +FILE_USER=cryptobox-data +WEB_USER=www-data +SCAN_DEVICES="hda hdb hdc hdd hde hdf hdg scd sg sda sdb sdc sdd" + +# set this to "1" to create a dedicated configuration partition (very small) +# this should only be necessary, if your root filesystem is read-only (as for a live-cd) +USE_SEPERATE_CONFIG_PARTITION=0 # web interface HTML_TEMPLATE_DIR=/usr/share/cryptobox/templates @@ -14,11 +19,12 @@ STYLESHEET_URL=/cryptobox-misc/cryptobox.css LANGUAGE_DIR=/usr/share/cryptobox/lang DOC_DIR=/usr/share/doc/cryptobox/html CONFIG_DEFAULTS_DIR=/usr/share/cryptobox/defaults -CONFIG_DIR=/mnt/cb-etc -MNT_PARENT=/mnt/crypto +CONFIG_DIR=/var/lib/cryptobox/config +MNT_PARENT=/var/lib/cryptobox/mnt # some files CB_SCRIPT=/usr/lib/cryptobox/cbox-manage.sh +ROOT_PERM_SCRIPT=/usr/lib/cryptobox/cbox-root-actions.sh DEV_FEATURES_SCRIPT=/usr/lib/cryptobox/devel-features.sh FIREWALL_SCRIPT=/usr/lib/cryptobox/firewall.sh MAKE_CERT_SCRIPT=/usr/lib/cryptobox/make_stunnel_cert.sh @@ -39,6 +45,7 @@ MKFS_DATA=/sbin/mkfs.ext3 MKFS_CONFIG=/sbin/mkfs.ext2 CRYPTSETUP=/sbin/cryptsetup IPTABLES=/sbin/iptables +IFCONFIG=/sbin/ifconfig # firewall setings # do not use multiports (iptables) as the timeout-script depends on diff --git a/cbox-tree.d/mnt/cb-etc/.placeholder b/cbox-tree.d/mnt/cb-etc/.placeholder deleted file mode 100644 index 9592d47..0000000 --- a/cbox-tree.d/mnt/cb-etc/.placeholder +++ /dev/null @@ -1 +0,0 @@ -do not remove this file diff --git a/cbox-tree.d/mnt/crypto/.placeholder b/cbox-tree.d/mnt/crypto/.placeholder deleted file mode 100644 index 9592d47..0000000 --- a/cbox-tree.d/mnt/crypto/.placeholder +++ /dev/null @@ -1 +0,0 @@ -do not remove this file diff --git a/cbox-tree.d/usr/lib/cgi-bin/cryptobox.pl b/cbox-tree.d/usr/lib/cgi-bin/cryptobox.pl index 75139ae..68c6aca 100755 --- a/cbox-tree.d/usr/lib/cgi-bin/cryptobox.pl +++ b/cbox-tree.d/usr/lib/cgi-bin/cryptobox.pl @@ -23,7 +23,7 @@ my $CONFIG_FILE = '/etc/cryptobox/cryptobox.conf'; my $pagedata; my ($LANGUAGE_DIR, $DEFAULT_LANGUAGE, $HTML_TEMPLATE_DIR, $DOC_DIR); -my ($CB_SCRIPT, $LOG_FILE, $IS_DEVEL); +my ($CB_SCRIPT, $LOG_FILE, $IS_DEVEL, $STYLESHEET_URL); &fatal_error ("could not find configuration file ($CONFIG_FILE)") unless (-e $CONFIG_FILE); my $config = ConfigFile::read_config_file($CONFIG_FILE); diff --git a/cbox-tree.d/usr/lib/cryptobox/cbox-manage.sh b/cbox-tree.d/usr/lib/cryptobox/cbox-manage.sh index ca106ec..f9276a9 100755 --- a/cbox-tree.d/usr/lib/cryptobox/cbox-manage.sh +++ b/cbox-tree.d/usr/lib/cryptobox/cbox-manage.sh @@ -15,6 +15,9 @@ # - the web frontend cgi # +# TODO: check permissions and owners of config files, directories and scripts before +# running cbox-root-actions.sh + set -eu # read the default setting file, if it exists @@ -25,6 +28,9 @@ CONF_FILE=${CONF_FILE:-/etc/cryptobox/cryptobox.conf} # parse config file . "$CONF_FILE" +# check for writable log file +[ -w "$LOG_FILE" ] || LOG_FILE=/tmp/$(basename "$LOG_FILE") + ## configuration CERT_TEMP=/tmp/stunnel.pem @@ -54,28 +60,16 @@ function error_msg() } -function create_partitions() -# Parameter: device -{ - # TODO: allow different layouts - # TODO: skip config partition if a configuration is already active - local device=$1 - # first partition size is 1 sector, second goes til end - # sfdisk -n doesn't actually write (for testing purpose) - echo -e "0,1,L \n,,L\n" | "$SFDISK" "$device" -} - - function config_set_value() # parameters: SettingName [SettingValue] # read from stdin if SettingValue is not defined { - mountpoint -q "$CONFIG_DIR" && mount -o rw,remount "$CONFIG_DIR" + [ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && sudo "$ROOT_PERM_SCRIPT" remount_config rw if [ $# -gt 1 ] then echo -n "$2" > "$CONFIG_DIR/$1" else cat - >"$CONFIG_DIR/$1" fi - mountpoint -q "$CONFIG_DIR" && mount -o ro,remount "$CONFIG_DIR" + [ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && sudo "$ROOT_PERM_SCRIPT" remount_config ro } @@ -84,7 +78,7 @@ function config_get_value() { # use mounted config, if it exists - otherwise use defaults local conf_dir - if is_config_mounted + if is_config_active then conf_dir=$CONFIG_DIR else conf_dir=$CONFIG_DEFAULTS_DIR fi @@ -112,14 +106,13 @@ function create_config() { local device=$1 # create the new configuration filesystem if it is not static - if is_config_mounted + if is_config_active then log_msg "Using static configuration ..." else log_msg "Creating config filesystem ..." - # filter output through 'tr' to replace tabs - $MKFS_CONFIG "$device" | tr '\010' ' ' - # mount the config partition rw + sudo "$ROOT_PERM_SCRIPT" create_config "$device" log_msg "Mounting config partition ..." - mount "$device" "$CONFIG_DIR" + sudo "$ROOT_PERM_SCRIPT" mount_config "$device" + sudo "$ROOT_PERM_SCRIPT" remount_config rw fi # create a marker to recognize a cryptobox partition date -I >"$CONFIG_DIR/$CONFIG_MARKER" @@ -127,7 +120,7 @@ function create_config() cp -a "$CONFIG_DEFAULTS_DIR/." "$CONFIG_DIR" log_msg "Copying temporary certificate file to config filesystem ..." - # beware: the temp file should always be there - even after reboot - see "mount_config" + # beware: the temp file should always be there - even after reboot - see "load_config" cp -p "$CERT_TEMP" "$CERT_FILE" log_msg "Setting inital values ..." @@ -135,12 +128,6 @@ function create_config() config_set_value "ip" "$(get_current_ip)" # create database of readable names config_set_value "names.db" "" - - # reinitialise configuration - log_msg "Unmounting config partition ..." - umount_config - log_msg "Reload configuration ..." - mount_config } @@ -148,30 +135,51 @@ function get_current_ip() # not necessarily the same as configured (necessary for validation) { # filter the output of ifconfig and remove trailing line break - echo -n $(ifconfig $NET_IFACE | grep "inet" | cut -d ":" -f2 | cut -d " " -f1) + echo -n $("$IFCONFIG" "$NET_IFACE" | grep "inet" | cut -d ":" -f2 | cut -d " " -f1) } -function list_crypto_containers() +function list_partitions_of_type() +# parameter: { config | crypto | plaindata | unused } { + local config= + local crypto= + local plaindata= + local unused= for a in $ALL_PARTITIONS - do "$CRYPTSETUP" isLuks "/dev/$a" 2>/dev/null && echo "/dev/$a" - done -} - - -function list_unused_partitions() -{ - for a in $ALL_PARTITIONS - do "$CRYPTSETUP" isLuks "/dev/$a" 2>/dev/null || echo "/dev/$a" + do if sudo "$ROOT_PERM_SCRIPT" is_crypto_partition "/dev/$a" + then crypto="$crypto /dev/$a" + elif sudo "$ROOT_PERM_SCRIPT" is_config_partition "/dev/$a" + then config="$config /dev/$a" + elif sudo "$ROOT_PERM_SCRIPT" is_plaindata_partition "/dev/$a" + then plaindata="$plaindata /dev/$a" + else unused="$unused /dev/$a" + fi done + case "$1" in + config ) + echo "$config" + ;; + crypto ) + echo "$crypto" + ;; + plaindata ) + echo "$plaindata" + ;; + unused ) + echo "$unused" + ;; + * ) + errot_msg "wrong parameter ($1) for list_partition_types in $(basename $0)" + ;; + esac | tr " " "\n" | grep -v '^$' } function get_crypto_uuid() # Parameter: DEVICE { - "$CRYPTSETUP" luksUUID "$1" + sudo "$ROOT_PERM_SCRIPT" get_device_name "$1" } @@ -180,7 +188,7 @@ function get_crypto_name() # return the readable name of the crypto container, it it is already defined # if undefined - return the uuid { - local uuid=$($CRYPTSETUP luksUUID $1) + local uuid=$(get_crypto_uuid "$1") local dbname=$(config_get_value "names.db" | grep "^$uuid:" | cut -d ":" -f 2-) if [ -z "$dbname" ] then echo -n "$uuid" @@ -190,9 +198,10 @@ function get_crypto_name() function set_crypto_name() +# TODO: the implementation is quite ugly, but it works (tm) # Parameter: DEVICE NAME { - local uuid=$($CRYPTSETUP luksUUID $1) + local uuid=$(get_crypto_uuid "$1") # remove the old setting for this device and every possible entry with the same name (config_get_value 'names.db' | sed "/^$uuid:/d; /^[^:]*:$2$/d"; echo "$uuid:$2") | config_set_value 'names.db' } @@ -208,53 +217,26 @@ function does_crypto_name_exist() function create_crypto() # Parameter: DEVICE NAME KEYFILE # keyfile is necessary, to allow background execution via 'at' +# TODO: check if the keyfile is still necessary for sudo -b { local device=$1 local name=$2 local keyfile=$3 # otherwise the web interface will hang # passphrase may be passed via command line - log_msg "Creating crypto partition with the cipher $DEFAULT_CIPHER on $device" - # the hash is ignored by luks - # the iter-time specifies the time spent on PBKDF2 - one second is said to be sufficient - # luksFormat floods the container with random noise automatically - cat "$keyfile" | $CRYPTSETUP -c "$DEFAULT_CIPHER" luksFormat "$device" - set_crypto_name "$device" "$name" - local uuid=$(get_crypto_uuid "$device") - - # map the crypto container - cat "$keyfile" | $CRYPTSETUP luksOpen "$device" "$uuid" - + local key=$(<"$keyfile") # remove the passphrase-file as soon as possible dd if=/dev/zero of="$keyfile" bs=512 count=1 2>/dev/null rm "$keyfile" - # filter output through 'tr' to replace tabs - $MKFS_DATA "$CRYPTMAPPER_DIR/$uuid" | tr '\0101' ' ' + log_msg "Creating crypto partition with the cipher $DEFAULT_CIPHER on $device" + echo "$key" | sudo "$ROOT_PERM_SCRIPT" create_crypto "$device" - # set user for samba - # TODO: rename SAMBA_USER to something like FILE_USER - mkdir -p "$MNT_PARENT/$name" - mount "$CRYPTMAPPER_DIR/$uuid" "$MNT_PARENT/$name" - chown $SAMBA_USER "$MNT_PARENT/$name" - umount_crypto "$device" + set_crypto_name "$device" "$name" } -function config_mount_test() -# Parameter: device -{ - local device=$1 - local STATUS=0 - mount "${device}" "$CONFIG_DIR" &>/dev/null || true - is_config_mounted && STATUS=1 - umount "$CONFIG_DIR" &>/dev/null || true - # return code is the result of this expression - test 1 -eq "$STATUS" -} - - -function is_config_mounted() +function is_config_active() { test -f "$CONFIG_DIR/$CONFIG_MARKER" } @@ -263,8 +245,8 @@ function is_config_mounted() function is_crypto_mounted() # Parameter: DEVICE { - local uuid=$(get_crypto_uuid $1) - test -e "$CRYPTMAPPER_DIR/$uuid" + local name=$(get_crypto_uuid "$1") + [ -n "$name" ] && mountpoint -q "$MNT_PARENT/$name" } @@ -313,22 +295,17 @@ function get_available_disks() } -function mount_config() +function load_config() { # error if dynamic configuration is active # return if static configuration is active - if is_config_mounted && mountpoint -q "$CONFIG_DIR" - then error_msg 3 "configuration directory ($CONFIG_DIR) is already mounted!" - else is_config_mounted && return - fi + is_config_active && [ "$USE_SEPERATE_CONFIG_PARTITION" != "1" ] && return # look for a configuration partition - # modify all scan_devices to get regular expressions like "^hda[0-9]*$" - local scan_regex=$(echo "SCAN_DEVICES" | tr " " "\n" | sed 's/^/^/; s/$/[0-9]*$/') - echo "$ALL_PARTITIONS" | grep "$scan_regex" | while read part + list_partitions_of_type config | head -1 | while read part do log_msg "Trying to load configuration from /dev/$part ..." - if config_mount_test "/dev/$part" + if sudo "$ROOT_PERM_SCRIPT" is_config_partition "/dev/$part" then log_msg "configuraton found on $part" - mount "/dev/$part" "$CONFIG_DIR" + sudo "$ROOT_PERM_SCRIPT" mount_config "/dev/$part" # copy certificate to /tmp in case of re-initialization # /tmp should be writable, so tmpfs has to be mounted before (/etc/rcS.d) cp "$CERT_FILE" "$CERT_TEMP" @@ -342,10 +319,10 @@ function mount_config() function umount_config() { - is_config_mounted || return + is_config_active || return # only try to unmount, if it is not static (the config of a live-cd is always dynamic) - if mountpoint -q "$CONFIG_DIR" - then umount "$CONFIG_DIR" + if [ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] + then sudo "$ROOT_PERM_SCRIPT" umount_config else true fi } @@ -357,21 +334,9 @@ function mount_crypto() local device=$1 [ -z "$device" ] && error_msg 4 'No valid harddisk found!' && return 1 is_crypto_mounted "$device" && echo "The crypto filesystem is already active!" && return - local uuid=$(get_crypto_uuid "$device") - local name=$(get_crypto_name "$device") # passphrase is read from stdin - log_msg "Mounting crypto partition $name ($device)" - $CRYPTSETUP luksOpen "$device" "$uuid" - [ -e "$MNT_PARENT/$name" ] || mkdir -p "$MNT_PARENT/$name" - if mount "$CRYPTMAPPER_DIR/$uuid" "$MNT_PARENT/$name" - then true - # log_msg "Mount succeeded - now starting samba ..." - # /etc/init.d/samba start - return 0 - else log_msg "Mount failed - removing the crypto device $uuid ..." - $CRYPTSETUP luksClose "$uuid" - return 1 - fi + log_msg "Mounting a crypto partition from $device" + sudo "$ROOT_PERM_SCRIPT" mount "$device" } @@ -379,39 +344,17 @@ function umount_crypto() # Parameter: DEVICE { local device=$1 - # do not break on error - set +e - # TODO: do not stop samba - or do it just temporarily - #if ps -e | grep -q " [sn]mbd$" - # then log_msg "Stopping samba ..." - # /etc/init.d/samba stop - # ps -e | grep -q " smbd$" && killall smbd - # ps -e | grep -q " nmbd$" && killall nmbd - # ps -e | grep -q " smbd$" && killall -9 smbd - # ps -e | grep -q " nmbd$" && killall -9 nmbd - # fi local uuid=$(get_crypto_uuid $device) - local name=$(get_crypto_name $device) - if mountpoint -q "$MNT_PARENT/$name" - then log_msg "Unmounting crypto partition ..." - umount "$MNT_PARENT/$name" - rmdir "$MNT_PARENT/$name" - fi - if [ -e "$CRYPTMAPPER_DIR/$uuid" ] - then log_msg "Removing dev-mapper ..." - $CRYPTSETUP luksClose "$uuid" - fi - set -e + sudo "$ROOT_PERM_SCRIPT" umount "$uuid" } function box_purge() # removing just the first bytes from the harddisk should be enough { - local device get_available_disks | while read a - do log_msg "Purging $device ..." - dd if=/dev/zero of=$device bs=1M count=1 + do log_msg "Purging $a ..." + sudo "$ROOT_PERM_SCRIPT" trash_device "$a" log_msg " " done } @@ -423,9 +366,10 @@ function init_cryptobox() local device=$(find_harddisk) [ -z "$device" ] && log_msg 'No valid harddisk found!' && return 1 turn_off_all_crypto - is_config_mounted && umount_config || true - log_msg "Initializing config partition on $device ..." + is_config_active && umount_config || true + log_msg "Partitioning the device ($device) ..." create_partitions "$device" + log_msg "Initializing config partition on ${device}1 ..." # TODO: this should not be hard-coded create_config "${device}1" } @@ -463,7 +407,7 @@ case "$ACTION" in then conf_ip=$(config_get_value "ip") log_msg "Configuring $NET_IFACE for $conf_ip ..." echo "Configuring network interface for $NET_IFACE: $conf_ip" - ifconfig $NET_IFACE "$conf_ip" + "$IFCONFIG" "$NET_IFACE" "$conf_ip" fi if [ "${EXEC_FIREWALL_RULES:-0}" = 1 ] then log_msg "Starting the firewall ..." @@ -492,15 +436,17 @@ case "$ACTION" in fi if [ "${SKIP_NETWORK_CONFIG:-1}" != 1 ] then log_msg "Shutting the network interface down ..." - ifconfig "$NET_IFACE" down + "$IFCONFIG" "$NET_IFACE" down fi ;; services-up ) # the mount point has to be writeable + # this action is called as root - so we are allowed to umount mount -t tmpfs tmpfs "$MNT_PARENT" # is something special necessary? ;; services-down ) + # this action is called as root - so we are allowed to umount umount "$MNT_PARENT" # TODO: we should not depend on samba and thttpd # /etc/init.d/samba stop || true @@ -533,10 +479,10 @@ case "$ACTION" in create_crypto "$@" ;; crypto-list ) - list_crypto_containers + list_partitions_of_type crypto ;; crypto-list-unused ) - list_unused_partitions + list_partitions_of_type unused ;; crypto-name ) # Parameter: DEVICE @@ -547,7 +493,7 @@ case "$ACTION" in is_crypto_mounted "$1" ;; is_config_mounted ) - is_config_mounted + is_config_active ;; is_init_running ) is_init_running @@ -560,7 +506,7 @@ case "$ACTION" in # reconfigure the network interface to a new IP address # wait for 5 seconds to finish present http requests if [ "${SKIP_NETWORK_CONFIG:-1}" != 1 ] - then echo -n "sleep 5; ifconfig $NET_IFACE $(config_get_value ip)" | at now + then echo -n "sleep 5; sudo $ROOT_PERM_SCRIPT update_network" | at now fi ;; get_available_disks ) @@ -579,7 +525,7 @@ case "$ACTION" in ;; diskinfo ) get_available_disks | while read a - do "$SFDISK" -L -q -l "$a" + do sudo "$ROOT_PERM_SCRIPT" diskinfo "$a" done ;; box-purge ) diff --git a/cbox-tree.d/usr/lib/cryptobox/cbox-root-actions.sh b/cbox-tree.d/usr/lib/cryptobox/cbox-root-actions.sh new file mode 100755 index 0000000..9d22eb1 --- /dev/null +++ b/cbox-tree.d/usr/lib/cryptobox/cbox-root-actions.sh @@ -0,0 +1,315 @@ +#!/bin/sh +# +# Copyright (c) 02005 sense.lab +# +# License: This script is distributed under the terms of version 2 +# of the GNU GPL. See the LICENSE file included with the package. +# +# $Id$ +# +# this script is responsible for all dangerous actions, that require root privileges +# every action should be checked at least TWICE a day for open holes :) +# usually will get call via sudo +# +# called by: +# - cbox-manage.sh +# + +set -eu + +[ "$(id -u)" -ne 0 ] && echo "$(basename $0) - only root may call this script" >&2 && exit 100 + +# read the default setting file, if it exists +[ -e /etc/default/cryptobox ] && . /etc/default/cryptobox + +# set CONF_FILE to default value, if not configured in /etc/default/cryptobox +CONF_FILE=${CONF_FILE:-/etc/cryptobox/cryptobox.conf} +# parse config file +. "$CONF_FILE" + + +############ some useful functions ############### + +# check if the given device is part of the SCAN_DEVICE list +# every entry in SCAN_DEVICES is matched as "^/dev/${SCAN_DEVICE}[0-9]*$" against +# the given device +# other devices may not be touched +function is_device_allowed() +# parameter: device +{ + for a in $SCAN_DEVICES + do [[ "$1" =~ "^/dev/${a}[0-9]*$" ]] && return 0 + done + return 1 +} + + +function get_device_name() +# return the uuid of the device +# if there is no uuid, then the device name is "flattened" and returned +# ignore volume-id as it may be non-unique +{ + local UUID= + # check for luksUUID or ext2/3-uuid + if is_luks_device "$1" + then UUID=$("$CRYPTSETUP" luksUUID "$1") + else [ -n "$(which dumpe2fs)" ] && UUID=$(dumpe2fs -h "$1" 2>/dev/null | grep "UUID" | cut -d ":" -f 2 | sed "s/ *//g") + fi + # if there is no valid UUUD, then take the flattened device name + is_uuid_valid "$UUID" || UUID=${1//\//_} + echo "$UUID" +} + + +function is_uuid_valid() +# every devmapper name should look like a UUID +{ + local hex=[0-9a-f] + [[ "$1" =~ "^$hex\{8\}-$hex\{4\}-$hex\{4\}-$hex\{4\}-$hex\{12\}$" ]] +} + + +function error_msg() +# parameter ExitCode ErrorMessage +{ + echo "CBOX-ERROR: [$(basename $0) - $ACTION] - $2" >&2 + exit $1 +} + + +function partition_device() +# parameter: device sfdisk_layout_setup +# e.g.: /dev/hda "0,1,L \n,,L\n" +{ + # TODO: allow different layouts + # TODO: skip config partition if a configuration is already active + # sfdisk -n doesn't actually write (for testing purpose) + echo -e "$2" | "$SFDISK" -n "$1" && \ + echo -e "$2" | "$SFDISK" "$1" +} + + +function is_luks_device() +# parameter: device +{ + "$CRYPTSETUP" isLuks "$1" +} + + +################ main #################### + +ACTION=unknown +[ $# -gt 0 ] && ACTION=$1 && shift + + +case "$ACTION" in + partition_disk ) + [ $# -ne 2 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + partition_device "$1" "$2" || \ + error_msg 2 "failed to create new partition table on device $1" + ;; + mount ) + # parameters: device + # returns the relative name of the mointpoint for success + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + name=$(get_device_name "$1") + mountpoint -q "$MNT_PARENT/$name" && \ + error_msg 5 "a device with the same name ($name) is already mounted" + mkdir -p "$MNT_PARENT/$name" + if is_luks_device "$1" + then "$CRYPTSETUP" luksOpen "$1" "$name" || \ + error_msg 6 "could not open encrypted device $1" + if mount "$DEV_MAPPER_DIR/$name" "$MNT_PARENT/$name" + then true + else "$CRYPTSETUP" luksClose "$name" || true + error_msg 7 "wrong password for $1 supplied" + fi + else mount "$1" "$MNT_PARENT/$name" || \ + error_msg 8 "invalid filesystem on device $1" + fi + # just in case, that there is no ext2/3 filesystem: + # set uid option (will fail silently for ext2/3) + mount -o remount,uid="$FILE_USER" "$MNT_PARENT/$name" 2>/dev/null || true + # adapt top-level permission to current setup - again: may fail silently + chown "$FILE_USER" "$MNT_PARENT/$name" 2>/dev/null || true + true + ;; + umount ) + #parameter: name (relative mountpoint) + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_uuid_valid "$1" || [[ "$1" =~ "^[_a-z0-9]*$" ]] || \ + error_msg 4 "invalid UUID ($1)" + mountpoint -q "$MNT_PARENT/$1" || \ + error_msg 9 "the device with the UUID ($1) is not mounted" + # try to unmount - continue even on errors + umount "$MNT_PARENT/$1" || \ + error_msg 0 "unmount of device $1 failed - device is busy" + # remove (if necessary) the dev mapping + [ -e "$DEV_MAPPER_DIR/$1" ] && "$CRYPTSETUP" luksClose "$1" || \ + error_msg 11 "could not remove the device mapper for device $1" + # try to remove the mountpoint - a failure is not important + rmdir "$MNT_PARENT/$1" || true + # set exitcode + mountpoint -q "$MNT_PARENT/$1" && exit 1 + exit 0 + ;; + create_crypto ) + # parameter: device + # the passphrase is expected on stdin + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + # read the passphrase from stdin + key=$(cat -) + # the iter-time is in milliseconds + echo "$key" | \ + "$CRYPTSETUP" --cipher "$DEFAULT_CIPHER" --iter-time 50000 luksFormat "$1" || \ + error_msg 11 "failed to create the encrypted partition" + name=$(get_device_name "$1") + echo "$key" | "$CRYPTSETUP" luksOpen "$1" "$name" || \ + error_msg 12 "failed to open the encrypted partition" + # silent output from mkfs.ext3 + "$MKFS_DATA" -q "$DEV_MAPPER_DIR/$name" || \ + error_msg 13 "failed to create the encrypted filesystem" + "$CRYPTSETUP" luksClose "$name" || \ + error_msg 14 "failed to close the encrypted mapped device" + ;; + get_device_name ) + # parameter: device + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + get_device_name "$1" + ;; + mount_config ) + # parameter: device + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + [ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ + error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + mountpoint -q "$CONFIG_DIR" && \ + error_msg 0 "the configuration partition is already mounted" + mount "$1" "$CONFIG_DIR" || \ + error_msg 16 "failed to mount configuration partition" + # chown to fix permissions - may fail for non-ext2/3 filesystems + chown -R "$WEB_USER" "$CONFIG_DIR" || true + mount -o remount,ro "$CONFIG_DIR" || \ + error_msg 18 "failed to remount configuration partition" + true + ;; + remount_config ) + # parameter: { ro | rw } + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + [ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ + error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" + [[ "$1" =~ "^r[ow]$" ]] || error_msg 17 "only 'rw' and 'ro' are allowed" + mount -o "remount,$1" "$CONFIG_DIR" || \ + error_msg 18 "failed to remount configuration partition" + true + ;; + umount_config ) + # no parameters + [ $# -ne 0 ] && error_msg 1 "wrong number of parameters" + [ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ + error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" + mountpoint -q "$CONFIG_DIR" && umount "$CONFIG_DIR" || \ + error_msg 18 "failed to unmount configuration partition" + ;; + is_config_partition ) + # parameter: device + # returns exitcode 0 if the device contains a configuration + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + [ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ + error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + is_config=0 + tmp_dir=/tmp/$(basename $0)-$$-mnt + mkdir -p "$tmp_dir" + # error means "no config partition" + if mount "$1" "$CONFIG_DIR" + then [ -e "$CONFIG_DIR/$CONFIG_MARKER" ] && is_config=1 + umount "$CONFIG_DIR" || \ + error_msg 14 "unable to unmount configation partition after probing" + fi + rmdir "$tmp_dir" || true + # return 0 if $device is a config partition + [ "$is_config" -eq 1 ] && exit 0 + exit 1 + ;; + is_crypto_partition ) + # parameter: device + # returns exitcode 0 if the device contains a luks header + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + is_luks_device "$1" + ;; + is_data_partition ) + # parameter: device + # returns exitcode 0 if the device contains a readable filesystem + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + status=0 + tmp_dir=/tmp/$(basename $0)-$$-mnt + mkdir -p "$tmp_dir" + if mount "$1" "$tmp_dir" + then [ ! -e "$tmp_dir/$CONFIG_MARKER" ] && status=1 + umount "$tmp_dir" + fi + rmdir "$tmp_dir" || true + [ "$status" -eq 1 ] && exit 0 + exit 1 + ;; + trash_device ) + # parameter: device + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + dd if=/dev/urandom of="$1" bs=512 count=1 2>/dev/null + ;; + diskinfo ) + # parameter: device + [ $# -ne 1 ] && error_msg 1 "wrong number of parameters" + is_device_allowed "$1" || \ + error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" + "$SFDISK" -L -q -l "$1" + ;; + update_network ) + # parameter: none + ip= + # TODO: can we avoid to hard-code the filename ($CONFIG_DIR/ip) here? + [ -e "$CONFIG_DIR/ip" ] && ip=$(<"$CONFIG_DIR/ip") + [ -n "$z" ] && ifconfig "$NET_IFACE" "$ip" + ;; + * ) + echo "Syntax: $(basename $0) ACTION PARAMETERS" + echo ' partition_disk $device $disk_layout' + echo ' get_device_name $device' + echo ' create_crypto $device' + echo ' mount $device' + echo ' umount $name' + echo ' create_config $device' + echo ' mount_config $device' + echo ' remount_config { ro | rw }' + echo ' umount_config' + echo ' is_config_partition $device' + echo ' is_plaindata_partition $device' + echo ' is_crypto_partition $device' + echo ' trash_device $device' + echo ' diskinfo $device' + echo ' update_network' + echo ' help' + echo + [ "$ACTION" == "help" ] && exit 0 + # return error for any unknown/unspecified action + exit 1 + ;; + esac + diff --git a/cbox-tree.d/usr/share/doc/cryptobox/README.Debian b/cbox-tree.d/usr/share/doc/cryptobox/README.Debian index 75e30cb..72c1a65 100644 --- a/cbox-tree.d/usr/share/doc/cryptobox/README.Debian +++ b/cbox-tree.d/usr/share/doc/cryptobox/README.Debian @@ -1,10 +1,11 @@ -CryptoBox for Debian +CryptoBox for Debian - installation notes 1) additional dependencies you need the following packages, which are not (yet) part of the main debian distribution: * cryptsetup_luks - http://luks.endorphin.org/masses * clearsilver for perl (>=0.9.14) - http://www.clearsilver.net/downloads/ + 2) cgi-bin If you do not use thttpd as your webserver, you should add the cgi-bin path to your script directory. For apache this would be something like the following: @@ -12,5 +13,6 @@ your script directory. For apache this would be something like the following: Alias /cryptobox-misc /var/www/cryptobox-misc ScriptAlias /cryptobox /usr/lib/cgi-bin/cryptobox.pl + -- Lars Kruse Sun, 4 Dec 2005 21:05:45 +0100 diff --git a/cbox-tree.d/var/lib/cryptobox/config/.placeholder b/cbox-tree.d/var/lib/cryptobox/config/.placeholder new file mode 100644 index 0000000..e293edf --- /dev/null +++ b/cbox-tree.d/var/lib/cryptobox/config/.placeholder @@ -0,0 +1 @@ +DO NOT REMOVE THIS FILE - it is a placeholder for the debian installer diff --git a/cbox-tree.d/var/lib/cryptobox/mnt/.placeholder b/cbox-tree.d/var/lib/cryptobox/mnt/.placeholder new file mode 100644 index 0000000..e293edf --- /dev/null +++ b/cbox-tree.d/var/lib/cryptobox/mnt/.placeholder @@ -0,0 +1 @@ +DO NOT REMOVE THIS FILE - it is a placeholder for the debian installer