cryptonas/bin-perl-old/cbox-root-actions.sh

342 lines
11 KiB
Bash
Executable File

#!/bin/sh
#
# Copyright (c) 02005 sense.lab <senselab@systemausfall.org>
#
# 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
LIB_DIR=$(dirname "$0")
LIB_DIR=$(cd "$LIB_DIR"; pwd)
test "$(id -u)" -ne 0 && echo "$(basename $0) - only root may call this script" >&2 && exit 100
# read the default setting file, if it exists
test -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"
# parse distribution specific file
. "$DISTRIBUTION_CONF"
CB_SCRIPT="$LIB_DIR/cbox-manage.sh"
CONFIG_MARKER=cryptobox.marker
############ 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}[^/]*$" against
# the given device
# other devices may not be touched
function is_device_allowed()
# parameter: device
{
for a in $SCAN_DEVICES
do echo "$1" | grep -q "^/dev/${a}[^/]*$" && return 0
done
return 1
}
# return the uuid of the partition (if possible)
# this works at least for luks, ext2/3 and vfat partitions
function get_device_uuid() {
local UUID
# check for luksUUID or ext2/3-uuid
if is_luks_device "$1"
then UUID=$("$CRYPTSETUP" luksUUID "$1")
else test -x "$BLKID" && UUID=$("$BLKID" -s UUID -o value -c /dev/null -w /dev/null "$1" 2>/dev/null)
fi
if test -z "$UUID"
then get_device_flat_name "$1"
else echo "$UUID"
fi
return 0
}
# the device name is "flattened"
function get_device_flat_name() {
echo "$1" | sed 's#/#_#g'
}
# the basename of the mountpoint for this device - should be somehow human_readable
function get_device_mnt_name() {
"$CB_SCRIPT" get_device_name "$1"
}
# every devmapper name should look like a UUID
function is_uuid_valid() {
local hex=[0-9a-f]
echo "$1" | grep -q "^$hex\{8\}-$hex\{4\}-$hex\{4\}-$hex\{4\}-$hex\{12\}$"
}
# parameter ExitCode ErrorMessage
function error_msg() {
echo "CBOX-ERROR: [$(basename $0) - $ACTION] - $2" >&2
exit $1
}
# parameter: device sfdisk_layout_setup
# e.g.: /dev/hda "0,1,L \n,,L\n"
function partition_device() {
# 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" 2>/dev/null
}
################ main ####################
ACTION=unknown
test $# -gt 0 && ACTION=$1 && shift
case "$ACTION" in
partition_disk )
test $# -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
test $# -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)"
mnt_name=$(get_device_mnt_name "$1")
mountpoint -q "$MNT_PARENT/$mnt_name" && \
error_msg 5 "a device with the same name ($mnt_name) is already mounted"
mkdir -p "$MNT_PARENT/$mnt_name"
if is_luks_device "$1"
then "$CRYPTSETUP" luksOpen "$1" "$mnt_name" || \
error_msg 6 "could not open encrypted device $1"
if mount "$DEV_MAPPER_DIR/$mnt_name" "$MNT_PARENT/$mnt_name"
then true
else "$CRYPTSETUP" luksClose "$mnt_name" || true
error_msg 7 "wrong password for $1 supplied"
fi
else mount "$1" "$MNT_PARENT/$mnt_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)
# TODO: there is no FILE_USER setting anymore - do we still need it?
#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: device
test $# -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)"
mnt_name=$(get_device_mnt_name "$1")
mountpoint -q "$MNT_PARENT/$mnt_name" || \
error_msg 9 "the device ($1) is not mounted as '$mnt_name'"
# try to unmount - do it in lazy mode
umount -l "$MNT_PARENT/$mnt_name"
# TODO: check, what happens, if there are open files - does the device gets mapping removed?
# remove (if necessary) the device mapping
if test -e "$DEV_MAPPER_DIR/$mnt_name"
then "$CRYPTSETUP" luksClose "$mnt_name" || \
error_msg 11 "could not remove the device mapper ($mnt_name) for device $1"
fi
# try to remove the mountpoint - a failure is not important
rmdir "$MNT_PARENT/$mnt_name" || true
# set exitcode
mountpoint -q "$MNT_PARENT/$mnt_name" && exit 1
true
;;
create_crypto )
# parameter: device keyfile
test $# -ne 2 && error_msg 1 "wrong number of parameters"
keyfile=$2
test -e "$keyfile" || error_msg 2 "keyfile ($keyfile) not found"
is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
# read the passphrase from stdin
# the iter-time is in milliseconds - keep it low for fast mounting
cat "$keyfile" | \
"$CRYPTSETUP" --cipher "$DEFAULT_CIPHER" --iter-time 2000 --batch-mode luksFormat "$1" || \
error_msg 11 "failed to create the encrypted partition"
name=$(get_device_mnt_name "$1")
cat "$keyfile" | "$CRYPTSETUP" --batch-mode luksOpen "$1" "$name" || \
error_msg 12 "failed to open the encrypted partition"
# trash the passphrase in keyfile
echo "0123456789abcdefghijklmnopqrstuvwxyz" > "$keyfile"
# the disk cache surely prevents the previous line from being written, but we do it anyway ...
echo "zyxwvutsrqponmlkjihgfedcba9876543210" > "$keyfile"
rm "$keyfile"
# complete in background
(
"$MKFS_DATA" "$DEV_MAPPER_DIR/$name" || \
error_msg 13 "failed to create the encrypted filesystem"
"$CRYPTSETUP" --batch-mode luksClose "$name" || \
error_msg 14 "failed to close the encrypted mapped device"
) </dev/null >/dev/null 2>/dev/null &
true
;;
create_plain )
# parameter: device
test $# -ne 1 && error_msg 1 "wrong number of parameters for 'create_plain'"
is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
# complete in background
(
"$MKFS_DATA" "$1" || \
error_msg 15 "failed to create the plaintext filesystem"
) </dev/null >/dev/null 2>/dev/null &
true
;;
get_device_mnt_name )
# parameter: device
test $# -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_mnt_name "$1"
;;
get_device_uuid )
# parameter: device
test $# -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_uuid "$1"
;;
is_config_partition )
# parameter: device
# returns exitcode 0 if the device contains a configuration
test $# -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_config=0
tmp_dir=/tmp/$(basename $0)-$$-mnt
mkdir -p "$tmp_dir"
# error means "no config partition"
if mount "$1" "$CONFIG_DIR"
then test -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
test "$is_config" -eq 1 && exit 0
exit 1
;;
is_crypto_partition )
# parameter: device
# returns exitcode 0 if the device contains a luks header
test $# -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_plain_partition )
# parameter: device
# returns exitcode 0 if the device contains a readable filesystem
test $# -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" >/dev/null 2>/dev/null
then test ! -e "$tmp_dir/$CONFIG_MARKER" && status=1
umount "$tmp_dir"
fi
rmdir "$tmp_dir" || true
test "$status" -eq 1 && exit 0
exit 1
;;
trash_device )
# parameter: device
test $# -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
test $# -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?
test -e "$CONFIG_DIR/ip" && ip=$(<"$CONFIG_DIR/ip")
test -n "$z" && ifconfig "$NET_IFACE" "$ip"
;;
poweroff )
# TODO: check configuration setting before
"$POWEROFF"
;;
reboot )
# TODO: check configuration setting before
"$REBOOT"
;;
* )
echo "[$(basename $0)] - unknown action: $ACTION" >&2
echo "Syntax: $(basename $0) ACTION PARAMETERS"
echo ' partition_disk $device $disk_layout'
echo ' get_device_name $device'
echo ' get_device_uuid $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_plain_partition $device'
echo ' is_crypto_partition $device'
echo ' trash_device $device'
echo ' diskinfo $device'
echo ' update_network'
echo ' poweroff'
echo ' reboot'
echo ' help'
echo
test "$ACTION" = "help" && exit 0
# return error for any unknown/unspecified action
exit 1
;;
esac