#!/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) if echo -e "$2" | "$SFDISK" -n "$1" then echo -e "$2" | "$SFDISK" "$1" || return 1 else return 2 fi true } 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 - keep it low for fast mounting echo "$key" | \ "$CRYPTSETUP" --cipher "$DEFAULT_CIPHER" --iter-time 2000 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" "$MKFS_CONFIG" -q "$1" || \ error_msg 20 "failed to create config partition filesystem" ;; 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