342 lines
11 KiB
Bash
342 lines
11 KiB
Bash
|
#!/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
|
||
|
|