moved to a volume based web interface

initialization now uses a single volume (no partitioning)
SCAN_DEVICES now define only the allowed prefix ("hd" -> all harddisks)
DEBUG_LEVEL added
check for https improved
This commit is contained in:
lars 2006-05-29 07:09:17 +00:00
parent 49a5f739a5
commit 5fb9108640
34 changed files with 1308 additions and 804 deletions

View file

@ -20,24 +20,24 @@
set -eu
# define reasonable defaults
USE_STUNNEL=0
EXEC_FIREWALL_RULES=0
SKIP_NETWORK_CONFIG=1
# default location of config file
CONF_FILE=/etc/cryptobox/cryptobox.conf
LIB_DIR=$(dirname "$0")
CONFIG_DIR=~/config
# to determine a nice default partition name
DEVICE_NAME_PREFIX="Disk #"
# read the default setting file, if it exists
[ -e /etc/default/cryptobox ] && . /etc/default/cryptobox
[ ! -e "$CONF_FILE" ] && error_msg 1 "Could not find the configuration file: $CONF_FILE"
[ ! -e "$CONF_FILE" ] && echo "Could not find the configuration file: $CONF_FILE" >&2 && exit 1
# parse config file
source "$CONF_FILE"
[ ! -e "$CONF_FILE" ] && error_msg 1 "Could not find the distribution specific configuration file: $CONF_FILE"
[ ! -e "$CONF_FILE" ] && echo "Could not find the distribution specific configuration file: $CONF_FILE" >&2 && exit 1
# parse the distribution specific file
source "$DISTRIBUTION_CONF"
@ -45,21 +45,26 @@ source "$DISTRIBUTION_CONF"
# check for writable log file
[ -w "$LOG_FILE" ] || LOG_FILE=/tmp/$(basename "$LOG_FILE")
# retrieve configuration directory
CONFIG_DIR="$(getent passwd '$CRYPTOBOX_USER' | cut -d ':' -f 6)/config"
CONFIG_MARKER=cryptobox.marker
## configuration
CERT_TEMP=/tmp/stunnel.pem
ROOT_PERM_SCRIPT=$(dirname "$0")/cryptobox_root_wrapper
ROOT_PERM_SCRIPT="$LIB_DIR/cryptobox_root_wrapper"
# ROOT_PERM_SCRIPT needs the MNT_PARENT setting
export MNT_PARENT="$(cd ~; pwd)/mnt"
######## stuff ##########
ALL_PARTITIONS=$(cat /proc/partitions | sed '1,2d; s/ */ /g; s/^ *//' | cut -d " " -f 4)
# all partitions with a trailing number
ALL_PARTITIONS=$(cat /proc/partitions | sed '1,2d; s/ */ /g; s/^ *//' | cut -d " " -f 4 | grep '[0-9]$')
#########################
function log_msg()
{
# the log file is not writable during boot - try before writing ...
# the log file is (maybe) not writable during boot - try
# before writing ...
[ -w "$LOG_FILE" ] || return 0
echo >>"$LOG_FILE"
echo "##### `date` #####" >>"$LOG_FILE"
@ -70,6 +75,8 @@ function log_msg()
function error_msg()
# parameters: ExitCode ErrorMessage
{
local all=$@
test $# -ne 2 && error_msg 1 "*** invalid call of error_msg *** $all"
echo "[`date`] - $2" | tee -a "$LOG_FILE" >&2
# print the execution stack - not usable with busybox
# caller | sed 's/^/\t/' >&2
@ -77,16 +84,30 @@ function error_msg()
}
# Parameter: device
function is_device_allowed() {
# check for invalid characters and exit if one is found
local device=$(echo "$1" | sed 's#[^a-zA-Z0-9_\-\./]##g')
test "$1" = "$device" || return 1
# remove leading "/dev/"
device=$(echo "$device" | sed 's#^/dev/##')
# return for empty name
test -z "$device" && return 1
for a in $ALL_PARTITIONS
do echo "$device" | grep -q "^$a.*" && return 0
done
# no matching device found - exit with error
return 1
}
function config_set_value()
# parameters: SettingName [SettingValue]
# read from stdin if SettingValue is not defined
{
[ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && "$ROOT_PERM_SCRIPT" remount_config rw
if [ $# -gt 1 ]
then echo -n "$2" > "$CONFIG_DIR/$1"
then echo "$2" > "$CONFIG_DIR/$1"
else cat - >"$CONFIG_DIR/$1"
fi
[ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && "$ROOT_PERM_SCRIPT" remount_config ro
}
@ -95,66 +116,22 @@ function config_get_value()
{
# use mounted config, if it exists - otherwise use defaults
local conf_dir
if is_config_active
then conf_dir=$CONFIG_DIR
else conf_dir=$CONFIG_DEFAULTS_DIR
fi
[ -z "$1" ] && error_msg 1 "empty setting name"
# check for existence - maybe use default values (for old releases without this setting)
if [ ! -e "$conf_dir/$1" ]
then case "$1" in
test -z "$1" && error_msg 1 "empty setting name"
# check for existence - maybe use default values (even for old
# releases that did not contain this setting)
if test -e "$CONFIG_DIR/$1"
then cat "$CONFIG_DIR/$1"
elif test -e "$CONFIG_DEFAULTS_DIR/$1"
then cat "$CONFIG_DEFAULTS_DIR/$1"
else case "$1" in
# you may place default values for older versions here
# for compatibility
* )
error_msg 2 "unknown configuration value ($1)"
# empty output
;;
esac
else echo -n $(cat "$conf_dir/$1")
# this removes the trailing line break
fi
# always return without error
true
}
function create_config()
# Parameter: device
{
local device=$1
unload_config
# create the new configuration filesystem if it is not static
if [ "$USE_SEPERATE_CONFIG_PARTITION" != "1" ]
then log_msg "Using static configuration ..."
else log_msg "Creating config filesystem ..."
"$ROOT_PERM_SCRIPT" create_config "$device"
log_msg "Mounting config partition ..."
"$ROOT_PERM_SCRIPT" mount_config "$device"
"$ROOT_PERM_SCRIPT" remount_config rw
fi
log_msg "Copying configuration defaults ..."
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 "load_config"
[ "$USE_STUNNEL" = 1 ] && cp -p "$CERT_TEMP" "$CERT_FILE"
log_msg "Setting inital values ..."
# beware: config_set_value remounts the config partition read-only
config_set_value "ip" "$(get_current_ip)"
# create database of readable names
config_set_value "names.db" ""
# create a marker to recognize a cryptobox partition
# this should be the last step, to prevent a half-initialized state
config_set_value "$CONFIG_MARKER" "$(date -I)"
}
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)
return 0
}
@ -176,45 +153,73 @@ function list_partitions_of_type()
fi
done
case "$1" in
config | crypto | plaindata | unused )
# dirty hack, but it works
eval "echo \$$1"
config )
echo "$config"
;;
crypto )
echo "$crypto"
;;
plaindata )
echo "$plaindata"
;;
unused )
echo "$unused"
;;
* )
errot_msg "wrong parameter ($1) for list_partition_types in $(basename $0)"
error_msg 11 "wrong parameter ($1) for list_partition_types in $(basename $0)"
;;
esac | tr " " "\n" | grep -v '^$'
return 0
}
function get_crypto_uuid()
# Parameter: DEVICE
{
"$ROOT_PERM_SCRIPT" get_device_name "$1"
function get_device_mnt_name() {
"$ROOT_PERM_SCRIPT" get_device_mnt_name "$1"
}
function get_crypto_name()
# Parameter: DEVICE
# return the readable name of the crypto container, it it is already defined
function get_device_uuid() {
"$ROOT_PERM_SCRIPT" get_device_uuid "$1"
}
# Parameter: DEVICE
# return the readable name of the crypto container, if it is already defined
# if undefined - return the uuid
{
local uuid=$(get_crypto_uuid "$1")
function get_device_name() {
local uuid=$(get_device_uuid "$1")
local dbname=$(config_get_value "names.db" | grep "^$uuid:" | cut -d ":" -f 2-)
if [ -z "$dbname" ]
then echo -n "$uuid"
else echo -n "$dbname"
# return dbname if it exists
test -n "$dbname" && echo "$dbname" && return 0
# find a nice name for the new partition
local counter=1
local test_name
local test_uuid
local test_result
# try to find a name with the defined "prefix" followed by a number ...
while true
do test_name="$DEVICE_NAME_PREFIX$counter"
if config_get_value "names.db" | grep -q ":$test_name$"
then counter=$((counter+1))
else # save it for next time
set_device_name "$1" "$test_name"
echo "$test_name"
return 0
fi
done
}
function set_crypto_name()
function set_device_name()
# TODO: the implementation is quite ugly, but it works (tm)
# Parameter: DEVICE NAME
{
local uuid=$(get_crypto_uuid "$1")
local uuid=$(get_device_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'
local new_config=$(config_get_value 'names.db' | sed "/^$uuid:/d; /^[^:]*:$2$/d"; echo "$uuid:$2")
echo "$new_config" | config_set_value "names.db"
}
@ -252,45 +257,11 @@ function is_config_active()
}
function is_crypto_mounted()
function is_mounted()
# Parameter: DEVICE
{
local name=$(get_crypto_uuid "$1")
[ -n "$name" ] && mountpoint -q "$MNT_PARENT/$name"
}
function is_init_running()
{
check_at_command_queue " init"
}
# check if a specified command is in an at-queue
# Parameter: a regular expression of the commandline
# Return: the command is part of an at-queue (0) or not (1)
function check_at_command_queue()
{
# 1) get the available job numbers
# 2) remove empty lines (especially the last one)
# 3) check every associated command for the regexp
at -l | cut -f 1 | while read jobnum
do at -c $jobnum | sed '/^$/d' | tail -1
done | grep -q "$1"
}
function find_harddisk()
# look for the harddisk to be partitioned
{
local device=$(get_available_disks | head -1)
if [ -z "$device" ] ; then
log_msg "no valid harddisk for initialisation found!"
cat /proc/partitions >>"$LOG_FILE"
# do not return with an error, to avoid a failing of the script ('break on error')
# the caller of this function should handle an empty return string
fi
echo -n "$device"
local name=$(get_device_mnt_name "$1")
test -n "$name" && mountpoint -q "$MNT_PARENT/$name"
}
@ -299,67 +270,29 @@ function get_available_disks()
{
for scan in $SCAN_DEVICES
do for avail in $ALL_PARTITIONS
do [ "$scan" = "$avail" ] && echo "/dev/$avail"
do echo "$avail" | grep -q "^$scan[0-9]*" && echo "/dev/$avail"
done
done
return 0
}
function load_config()
{
unload_config
local status=0
# look for a configuration partition
[ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && \
list_partitions_of_type config | while read part && [ "$status" = 0 ]
do log_msg "Trying to load configuration from /dev/$part ..."
if "$ROOT_PERM_SCRIPT" is_config_partition "/dev/$part"
then log_msg "configuraton found on $part"
"$ROOT_PERM_SCRIPT" mount_config "/dev/$part"
status=1
fi
done
if is_config_active
then # copy certificate to /tmp in case of re-initialization
# /tmp should be writable, so tmpfs has to be mounted before (/etc/rcS.d)
[ "$USE_STUNNEL" = 1 ] && cp "$CERT_FILE" "$CERT_TEMP"
else log_msg "failed to locate config partition"
return 1
fi
true
}
function unload_config()
{
is_config_active || return
# only try to unmount, if it is not static (the config of a live-cd is always dynamic)
if [ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ]
then "$ROOT_PERM_SCRIPT" umount_config
else true
fi
}
function mount_crypto()
# Parameter: DEVICE
{
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
[ -z "$device" ] && error_msg 4 'No valid harddisk found!'
is_mounted "$device" && echo "The crypto filesystem is already active!" && return
# passphrase is read from stdin
log_msg "Mounting a crypto partition from $device"
"$ROOT_PERM_SCRIPT" mount "$device" >>"$LOG_FILE" 2>&1
}
function umount_crypto()
# Parameter: DEVICE
{
local device=$1
local uuid=$(get_crypto_uuid $device)
"$ROOT_PERM_SCRIPT" umount "$uuid"
function umount_partition() {
# Parameter: device
local container=$(get_device_name "$1")
"$ROOT_PERM_SCRIPT" umount "$1"
}
@ -376,26 +309,8 @@ function box_purge()
}
function init_cryptobox()
# this is only the first part of initialisation that takes no time - good for a smooth web interface
{
local device=$(find_harddisk)
[ -z "$device" ] && log_msg 'No valid harddisk found!' && return 1
turn_off_all_crypto
unload_config || true
log_msg "Partitioning the device ($device) ..."
"$ROOT_PERM_SCRIPT" partition_disk "$device" "0,1,L \n,,L\n"
log_msg "Initializing config partition on ${device}1 ..."
# TODO: this should not be hard-coded
create_config "${device}1"
}
function turn_off_all_crypto()
{
list_crypto_containers | while read a
do is_crypto_mounted "$a" && umount_crypto "$a"
done
function turn_off_all_containers() {
"$ROOT_PERM_SCRIPT" create_plain "$1"
}
@ -409,137 +324,68 @@ ACTION=help
[ $# -gt 0 ] && ACTION=$1 && shift
case "$ACTION" in
config-up )
if load_config
then echo "Cryptobox configuration successfully loaded"
else error_msg 0 "Could not find a configuration partition!"
fi
;;
config-down )
unload_config || error_msg 4 "Could not unmount configuration partition"
;;
network-up )
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
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"
fi
if [ "$EXEC_FIREWALL_RULES" = 1 ]
then log_msg "Starting the firewall ..."
"$FIREWALL_SCRIPT" start
fi
if [ "$USE_STUNNEL" = 1 ]
then # start stunnel
if [ -f "$CERT_FILE" ]
then USE_CERT=$CERT_FILE
else USE_CERT=$CERT_TEMP
$MAKE_CERT_SCRIPT "$CERT_TEMP" >>"$LOG_FILE" 2>&1
# TODO: this could be dangerous - right?
# this is necessary, to allow www-data to copy the certificate
chown "$WEB_USER" "$CERT_TEMP"
fi
log_msg "Starting stunnel ..."
stunnel -p "$USE_CERT" -r localhost:80 -d 443 \
|| echo "$USE_CERT not found - not starting stunnel"
fi
;;
network-down )
if [ "$EXEC_FIREWALL_RULES" = 1 ]
then log_msg "Stopping the firewall ..."
"$FIREWALL_SCRIPT" stop
fi
if [ "$USE_STUNNEL" = 1 ]
then log_msg "Stopping stunnel ..."
# TODO: what about a pid?
killall stunnel 2>/dev/null || true
fi
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
then log_msg "Shutting the network interface 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
# TODO: do this only for ro-filesystem
# TODO: this way of mounting is evil
if mountpoint -q "$MNT_PARENT"
then true
else mount -t tmpfs tmpfs "$MNT_PARENT"
fi
true
;;
services-down )
# this action is called as root - so we are allowed to umount
mountpoint -q "$MNT_PARENT" && umount "$MNT_PARENT"
# TODO: we should not depend on samba and thttpd
# /etc/init.d/samba stop || true
# /etc/init.d/thttpd stop || true
true
;;
crypto-up )
[ $# -ne 1 ] && error_msg "invalid number of parameters for 'crypto-up'"
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'crypto-up'"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
mount_crypto "$1"
;;
crypto-down )
[ $# -ne 1 ] && error_msg "invalid number of parameters for 'crypto-down'"
umount_crypto "$1"
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'crypto-down'"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
umount_partition "$1"
;;
init )
init_cryptobox </dev/null >>"$LOG_FILE" 2>&1
;;
crypto-create )
# Parameter: DEVICE NAME
[ $# -ne 2 ] && error_msg "invalid number of parameters for 'crypto-create'"
# do it in the background to provide a smoother web interface
# messages and errors get written to $LOG_FILE
keyfile=/tmp/$(basename "$0")-passphrase-$(basename "$1")
# read the password
cat - >"$keyfile"
# execute it in the background
echo "'$0' crypto-create-bg '$1' '$2' '$keyfile' </dev/null >>'$LOG_FILE' 2>&1" | at now
list_container )
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'list_container'"
case "$1" in
config | unused | plaindata | crypto )
list_partitions_of_type "$1"
;;
crypto-create-bg )
create_crypto "$@"
* )
return 1
;;
crypto-list )
list_partitions_of_type crypto
esac
return 0
;;
crypto-list-unused )
list_partitions_of_type unused
;;
crypto-name )
get_device_name )
# Parameter: DEVICE
get_crypto_name "$1"
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'get_device_name'"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
get_device_name "$1"
;;
is_crypto_mounted )
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'is_crypto_mounted'"
is_crypto_mounted "$1"
set_device_name )
# Parameter: DEVICE NAME
[ $# -ne 2 ] && error_msg 10 "invalid number of parameters for 'set_device_name'"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
set_device_name "$1" "$2"
;;
is_config_mounted )
is_config_active
;;
is_init_running )
is_init_running
;;
is_harddisk_available )
[ -z "$(find_harddisk)" ] && exit 1
exit 0
;;
update_ip_address )
# reconfigure the network interface to a new IP address
# wait for 5 seconds to finish present http requests
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
then echo -n "sleep 5; \"$ROOT_PERM_SCRIPT\" update_network" | at now
device_init )
# Parameter: DEVICE [KEYFILE]
test $# -lt 1 && error_msg 10 "invalid number of parameters for 'device_init' ($@)"
test $# -gt 2 && error_msg 10 "invalid number of parameters for 'device_init' ($@)"
if test $# -eq 2
then test -z "$2" -o ! -e "$2" && error_msg 11 "invalid keyfile ($2) given for 'device_init'"
fi
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
if test $# -eq 2
then "$ROOT_PERM_SCRIPT" create_crypto "$1" "$2"
else TODO "$1"
fi
true
;;
is_mounted )
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'is_mounted'"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
is_mounted "$1"
;;
check_config)
is_config_active
;;
get_available_disks )
get_available_disks
;;
get_current_ip )
get_current_ip
;;
set_config )
[ $# -ne 2 ] && error_msg 7 "'set_config' requires two parameters"
config_set_value "$1" "$2"
@ -548,53 +394,59 @@ case "$ACTION" in
[ $# -ne 1 ] && error_msg 6 "'get_config' requires exactly one parameter"
config_get_value "$1"
;;
get_capacity_info )
[ $# -ne 1 ] && error_msg 6 "'get_capacity_info' requires exactly one parameter"
is_device_allowed "$1" || error_msg 12 "invalid device: $1"
is_mounted "$1" || error_msg 13 "the device is not mounted: $1"
name=$(get_device_mnt_name "$1")
df -h "$MNT_PARENT/$name" | tail -1
;;
diskinfo )
get_available_disks | while read a
do "$ROOT_PERM_SCRIPT" diskinfo "$a"
done
done 2>/dev/null
;;
box-purge )
log_msg "Cleaning the CryptoBox ..."
turn_off_all_crypto
turn_off_all_containers
"$0" config-down
box_purge >>"$LOG_FILE" 2>&1
;;
poweroff )
log_msg "Turning off the CryptoBox ..."
turn_off_all_crypto
echo "poweroff" | at now
log_msg "Shutting down the Cryptobox ..."
turn_off_all_containers
"$ROOT_PERM_SCRIPT" poweroff
;;
reboot )
log_msg "Rebooting the CryptoBox ..."
turn_off_all_crypto
echo "reboot" | at now
log_msg "Rebooting the Cryptobox ..."
turn_off_all_containers
"$ROOT_PERM_SCRIPT" reboot
;;
umount_all )
log_msg "Unmounting all volumes ..."
turn_off_all_containers
;;
* )
echo "Syntax: `basename $0` ACTION [PARAMS]"
echo " config-up - scan for configuration partition and mount it"
echo " config-down - unmount configuration partition"
echo " network-up - enable network interface"
echo " network-down - disable network interface"
echo " services-up - run some cryptobox specific daemons"
echo " services-down - stop some cryptobox specific daemons"
echo "[$(basename $0)] - unknown action: $ACTION" >&2
echo "Syntax: $(basename $0) ACTION [PARAMS]"
echo " crypto-up - mount crypto partition"
echo " crypto-down - unmount crypto partition"
echo " box-init - initialize cryptobox (ALL data is LOST)"
echo " box-init-fg - the first part of initialization"
echo " box-init-bg - the last part of initialization (background)"
echo " is_crypto_mounted - check, if crypto partition is mounted"
echo " is_config_mounted - check, if configuration partition is mounted"
echo " is_init_running - check, if initialization is ongoing"
echo " is_harddisk_available - check, if there is a usable harddisk"
echo " get_available_disks - shows all connected and allowed disks"
echo " crypto-create - a wrapper for 'crypto-create-bg'"
echo " crypto-create-bg - create encrypted blockdevice and run mkfs"
echo " is_mounted - check, if crypto partition is mounted"
echo " check_config - check, if the configuration is usable"
echo " get_available_disks - shows all accessible disks"
echo " get_current_ip - get the current IP of the network interface"
echo " update_ip_address - update the network interface after reconfiguration"
echo " set_config NAME VALUE - change a configuration setting"
echo " get_config NAME - retrieve a configuration setting"
echo " get_device_name DEVICE - retrieve the human readable name of a partition"
echo " set_device_name DEVICE - set the human readable name of a partition"
echo " device_init DEVICE KEYFILE - initialize the filesystem of a partition (the keyfile just contains the passphrase)"
echo " get_capacity_info - print the output of 'df' for the (mounted) partition"
echo " diskinfo - show the partition table of the harddisk"
echo " box-purge - destroy partitiontable of all harddisks (delete everything)"
echo " poweroff - shutdown the cryptobox"
echo " reboot - reboot the cryptobox"
echo " box-purge - destroy the partition tables of all harddisks (delete everything)"
echo " poweroff - turn off the computer"
echo " reboot - reboot the computer"
echo
;;
esac

View file

@ -17,6 +17,9 @@
set -eu
LIB_DIR=$(dirname "$0")
LIB_DIR=$(cd "$LIB_DIR"; pwd)
[ "$(id -u)" -ne 0 ] && echo "$(basename $0) - only root may call this script" >&2 && exit 100
# read the default setting file, if it exists
@ -29,6 +32,9 @@ source "$CONF_FILE"
# parse distribution specific file
source "$DISTRIBUTION_CONF"
CB_SCRIPT="$LIB_DIR/cbox-manage.sh"
CONFIG_MARKER=cryptobox.marker
############ some useful functions ###############
@ -46,43 +52,54 @@ function is_device_allowed()
}
function get_device_name()
# return the uuid of the device
# if there is no uuid, then the device name is "flattened" and returned
# return the uuid of the partition (if possible)
# this only works for luks or ext2/3 partitions
# ignore volume-id as it may be non-unique
{
local UUID=
function get_device_uuid() {
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")
else [ -x "$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"
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"
}
function is_uuid_valid()
# every devmapper name should look like a UUID
{
function is_uuid_valid() {
local hex=[0-9a-f]
# TODO: this is very bash-specific - translate it to grep :)
[[ "$1" =~ "^$hex\{8\}-$hex\{4\}-$hex\{4\}-$hex\{4\}-$hex\{12\}$" ]]
}
function error_msg()
# parameter ExitCode ErrorMessage
{
function error_msg() {
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"
{
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)
@ -97,7 +114,7 @@ function partition_device()
function is_luks_device()
# parameter: device
{
"$CRYPTSETUP" isLuks "$1"
"$CRYPTSETUP" isLuks "$1" 2>/dev/null
}
@ -121,19 +138,19 @@ case "$ACTION" in
[ $# -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"
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" "$name" || \
then "$CRYPTSETUP" luksOpen "$1" "$mnt_name" || \
error_msg 6 "could not open encrypted device $1"
if mount "$DEV_MAPPER_DIR/$name" "$MNT_PARENT/$name"
if mount "$DEV_MAPPER_DIR/$mnt_name" "$MNT_PARENT/$mnt_name"
then true
else "$CRYPTSETUP" luksClose "$name" || true
else "$CRYPTSETUP" luksClose "$mnt_name" || true
error_msg 7 "wrong password for $1 supplied"
fi
else mount "$1" "$MNT_PARENT/$name" || \
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:
@ -145,105 +162,86 @@ case "$ACTION" in
true
;;
umount )
#parameter: name (relative mountpoint)
#parameter: device
[ $# -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"
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/$1" || true
rmdir "$MNT_PARENT/$mnt_name" || true
# set exitcode
mountpoint -q "$MNT_PARENT/$1" && exit 1
exit 0
mountpoint -q "$MNT_PARENT/$mnt_name" && exit 1
true
;;
create_crypto )
# parameter: device
# the passphrase is expected on stdin
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
# parameter: device keyfile
[ $# -ne 2 ] && error_msg 1 "wrong number of parameters"
keyfile=$2
[ -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
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" || \
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_name "$1")
echo "$key" | "$CRYPTSETUP" luksOpen "$1" "$name" || \
name=$(get_device_mnt_name "$1")
cat "$keyfile" | "$CRYPTSETUP" --batch-mode luksOpen "$1" "$name" || \
error_msg 12 "failed to open the encrypted partition"
# silent output from mkfs.ext3
# 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
( # silent output from mkfs.ext3
"$MKFS_DATA" -q "$DEV_MAPPER_DIR/$name" || \
error_msg 13 "failed to create the encrypted filesystem"
"$CRYPTSETUP" luksClose "$name" || \
"$CRYPTSETUP" --batch-mode 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"
) </dev/null &>/dev/null &
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"
create_plain )
# parameter: device
[ $# -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
( # silent output from mkfs.ext3
"$MKFS_DATA" -q "$1" || \
error_msg 15 "failed to create the plaintext filesystem"
) </dev/null &>/dev/null &
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"
get_device_mnt_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_mnt_name "$1"
;;
get_device_uuid )
# 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_uuid "$1"
;;
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
@ -306,10 +304,20 @@ case "$ACTION" in
[ -e "$CONFIG_DIR/ip" ] && ip=$(<"$CONFIG_DIR/ip")
[ -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'
@ -323,6 +331,8 @@ case "$ACTION" in
echo ' trash_device $device'
echo ' diskinfo $device'
echo ' update_network'
echo ' poweroff'
echo ' reboot'
echo ' help'
echo
[ "$ACTION" == "help" ] && exit 0

View file

@ -19,24 +19,36 @@ use ClearSilver;
use ConfigFile;
use English;
use CGI::Carp;
use IO::File;
use POSIX;
use constant CRYPTOBOX_VERSION => 0.3;
# debug levels
use constant DEBUG_NONE => 0;
use constant DEBUG_ERROR => 1;
use constant DEBUG_WARN => 2;
use constant DEBUG_INFO => 3;
# drop privileges
$UID = $EUID;
$GID = $EGID;
# necessary for suid perl scripts (see 'man perlsec' for details)
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
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, $STYLESHEET_URL);
my ($CB_SCRIPT, $LOG_FILE, $IS_DEVEL, $STYLESHEET_URL, $DEBUG_LEVEL);
# get the directory of the cryptobox scripts/binaries and untaint it
$CB_SCRIPT = $0;
$CB_SCRIPT =~ m/^(.*)\/[^\/]*$/;
$CB_SCRIPT = "$1/cbox-manage.sh";
$CB_SCRIPT = ($1)? "$1/cbox-manage.sh" : './cbox-manage.sh';
&fatal_error ("could not find configuration file ($CONFIG_FILE)") unless (-e $CONFIG_FILE);
my $config = ConfigFile::read_config_file($CONFIG_FILE);
@ -48,20 +60,18 @@ $HTML_TEMPLATE_DIR = $config->{HTML_TEMPLATE_DIR};
$DOC_DIR = $config->{DOC_DIR};
$IS_DEVEL = ( -e $config->{DEV_FEATURES_SCRIPT});
$STYLESHEET_URL = $config->{STYLESHEET_URL};
# TODO: just a quick-and-dirty hack during migration to multiple containers
my $CRYPTO_DEV = &get_available_disks();
$CRYPTO_DEV =~ m/^([\w\/_\-\.]*)$/;
$CRYPTO_DEV = "${1}2";
if (defined($config->{DEBUG_LEVEL})) {
$DEBUG_LEVEL = $config->{DEBUG_LEVEL};
} else {
$DEBUG_LEVEL = DEBUG_ERROR; # default debug level
}
my $query = new CGI;
#################### subs ######################
# for fatal errors without the chance of clearsilver-rendering
sub fatal_error()
{
sub fatal_error() {
my $message = shift;
print "Content-Type: text/html\n\n";
@ -73,8 +83,14 @@ sub fatal_error()
}
sub load_hdf
{
sub debug_msg() {
my ($level, $message) = @_;
return 0 unless ($level >= $DEBUG_LEVEL);
warn "[cryptobox]: $message";
}
sub load_hdf {
my $hdf = ClearSilver::HDF->new();
my $fname = "$HTML_TEMPLATE_DIR/main.cs";
@ -101,8 +117,7 @@ sub load_hdf
}
sub load_selected_language
{
sub load_selected_language {
my $data = shift;
my $config_language;
@ -110,7 +125,7 @@ sub load_selected_language
$data->readFile("$LANGUAGE_DIR/$DEFAULT_LANGUAGE" . ".hdf");
# load configured language, if it is valid
$config_language = &exec_cb_script("get_config","language");
$config_language = &get_cbox_config("language");
$config_language = $DEFAULT_LANGUAGE unless (&validate_language("$config_language"));
# check for preferred browser language, if the box was not initialized yet
@ -130,6 +145,9 @@ sub load_selected_language
# load the data
$config_language = "$weblang";
# add the setting to every link
# how it should be done now ...
$data->setValue('Settings.LinkAttrs.weblang', "$weblang");
# old way of doing this ... (TODO: to be removed)
$data->setValue('Data.PostData.weblang', "$weblang");
} else {
# no valid language was selected - so you may ignore it
@ -153,9 +171,8 @@ sub load_selected_language
}
sub get_available_languages
# import the names of all available languages
{
sub get_available_languages {
my $data = shift;
my ($file, @files, $hdf, $lang_name);
@ -176,8 +193,7 @@ sub get_available_languages
# look for preferred browser language setting
# this code was adapted from Per Cederberg - http://www.percederberg.net/home/perl/select.perl
# it returns an empty string, if no supported language was found
sub get_browser_language
{
sub get_browser_language {
my ($str, @langs, @res);
# Use language preference settings
@ -199,8 +215,7 @@ sub get_browser_language
}
sub log_msg
{
sub log_msg {
my $text = shift;
open(LOGFILE,">> $LOG_FILE");
print LOGFILE "$text";
@ -208,28 +223,28 @@ sub log_msg
}
sub check_ssl
{
sub check_ssl {
# check, if we are behind a proxy with ssl (e.g. pound)
return (0==0) if ($ENV{'HTTP_FRONT_END_HTTPS'} =~ m/^on$/i);
# environment variable set (e.g. via apache directive "SetEnv HTTPS On")
return (0==0) if ($ENV{'HTTPS'} =~ m/^on$/i);
# port 80 -> not encrypted
return (0==1) if ($ENV{'SERVER_PORT'} = 80);
return (0==1) if ($ENV{'SERVER_PORT'} == 80);
# other ports -> maybe ok - we accept it
return (0==0);
}
sub check_mounted
{
return (system($CB_SCRIPT,"is_crypto_mounted",$CRYPTO_DEV) == 0);
# check, if the given device is mounted/used somehow
# Paramter: device
sub check_mounted {
my ($dev) = @_;
return (system($CB_SCRIPT,"is_mounted",$dev) == 0);
}
sub check_config
{
return (system($CB_SCRIPT,"is_config_mounted") == 0);
sub check_config {
return (system($CB_SCRIPT,"check_config") == 0);
}
@ -243,50 +258,65 @@ sub exec_cb_script {
exit 0;
} else {
# parent
@result = <PROG_OUT>;
close PROG_OUT or warn "error while running $CB_SCRIPT (params:" . join(" ",@params) . "): $?";
# only read lines containing at least one non-whitespace character
@result = grep /\S/, <PROG_OUT>;
foreach (@result) { chomp; }
unless (close PROG_OUT) {
&debug_msg(DEBUG_WARN, "error while running $CB_SCRIPT (params:" . join(" ",@params) . "): $?");
return undef;
}
}
if (wantarray) {
return @result;
} else {
} elsif (@result > 0) {
return join('',@result);
} else {
return "";
}
}
sub check_init_running
{
return (system($CB_SCRIPT,"is_init_running") == 0);
sub check_init_running {
# TODO: improve this
return (0==1);
}
sub is_harddisk_available
{
return (system($CB_SCRIPT,"is_harddisk_available") == 0);
}
sub get_available_disks
# TODO: this is useful for diskselection buttons
{
return &exec_cb_script("get_available_disks");
}
sub get_current_ip
# the IP of eth0 - not the configured value of the box (only for validation)
{
return &exec_cb_script("get_current_ip");
sub is_harddisk_available {
my @all_disks = &exec_cb_script("get_available_disks");
return @all_disks > 0;
}
sub get_admin_pw
# returns the current administration password - empty, if it is not used
{
return &exec_cb_script("get_config","admin_pw");
sub get_available_disks {
my @all_disks = &exec_cb_script("get_available_disks");
my ($disk, @return_disks);
foreach $disk (@all_disks) {
$disk =~ m#^([/\._\-\w]*)$#;
push @return_disks, $1 if ($1);
}
return @return_disks;
}
sub render
{
sub get_disk_name {
my ($dev) = @_;
my $disk_name = &exec_cb_script("get_device_name", $dev);
return $disk_name;
}
# return the value of a configuration setting (timeout, language, ip, ...)
# Parameter: setting_name
sub get_cbox_config {
my ($setting) = @_;
# tell the exec function, that we want a scalar instead of an array
my $scalar = &exec_cb_script("get_config",$setting);
return $scalar;
}
sub render {
my $pagefile = "$HTML_TEMPLATE_DIR/main.cs";
print "Content-Type: text/html\n\n";
@ -297,68 +327,82 @@ sub render
}
sub mount_vol
{
my $pw = shift;
# mount an encrypted volume
# Parameter: device password
sub mount_vol {
my ($device, $pw) = @_;
if (&check_mounted) {
if (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'IsMounted');
} else {
open(PW_INPUT, "| $CB_SCRIPT crypto-up $CRYPTO_DEV");
open(PW_INPUT, "| $CB_SCRIPT crypto-up $device");
print PW_INPUT $pw;
close(PW_INPUT);
}
}
sub umount_vol
{
if (&check_mounted) {
system($CB_SCRIPT, "crypto-down",$CRYPTO_DEV);
# unmount a volume
# Parameter: device
sub umount_vol {
my ($device) = @_;
if (&check_mounted($device)) {
system($CB_SCRIPT, "crypto-down",$device);
} else {
$pagedata->setValue('Data.Warning', 'NotMounted');
}
}
sub box_init
{
my ($crypto_pw, $admin_pw) = @_;
# Parameter: device passphrase
# ignore passphrase (or leave it empty) to create a plaintext volume
sub volume_init {
my ($device, $crypto_pw) = @_;
my $result;
system($CB_SCRIPT, "init") || return 1;
# partitioning, config and initial cryptsetup
# TODO: define the name of the crypto container
open(PW_INPUT, "|$CB_SCRIPT crypto-create '$CRYPTO_DEV' default");
print PW_INPUT $crypto_pw;
close(PW_INPUT);
# set administration password
$admin_pw =~ m/^(.*)$/;
system($CB_SCRIPT, "set_config", "admin_pw", $1);
}
sub box_purge
{
system($CB_SCRIPT, "box-purge");
}
sub system_poweroff
{
&umount_vol() if (&check_mounted());
system($CB_SCRIPT, "poweroff");
# only for encrypted volumes:
# write passphrase to a file - necessary as perl in secured mode does not allow
# the 'open(FH, "|/bin/prog ....")' call because of possible shell expansion - stupid 'open' :(
if ($crypto_pw) {
my ($fh, $temp_file);
# generate a temporary filename (as suggested by the Perl Cookbook)
do { $temp_file = POSIX::tmpnam() }
# TODO: reduce the file mask to the minimum - maybe 0600 would be a good choice
until $fh = IO::File->new($temp_file, O_RDWR|O_CREAT|O_EXCL);
close $fh;
unless (open(TMP, ">$temp_file")) {
&debug_msg(DEBUG_ERROR, "could not open a temporary file");
return (1==0);
}
print TMP $crypto_pw;
close TMP;
$result = &exec_cb_script("device_init", $device, $temp_file);
unlink ($temp_file) if (-e $temp_file);
} else {
$result = &exec_cb_script("device_init", $device);
}
# just to be sure, that the file does not get left behind
# usually the script should overwrite and remove it
return defined($result);
}
sub system_reboot
{
&umount_vol() if (&check_mounted());
system($CB_SCRIPT, "reboot");
sub box_purge {
&exec_cb_script("box-purge");
}
sub validate_ip
{
sub system_poweroff {
&exec_cb_script("poweroff");
}
sub system_reboot {
&exec_cb_script("reboot");
}
sub validate_ip {
my $ip = shift;
my @octets = split /\./, $ip;
return 0 if ($#octets == 4);
@ -371,8 +415,7 @@ sub validate_ip
}
sub validate_timeout
{
sub validate_timeout {
my $timeout = shift;
return 0 if ($timeout =~ /\D/);
return 1;
@ -380,8 +423,7 @@ sub validate_timeout
# check for a valid interface language
sub validate_language
{
sub validate_language {
my $language = shift;
# check for non-alphanumeric character
return 0 if ($language =~ /\W/);
@ -392,8 +434,7 @@ sub validate_language
# check for a valid documentation language
sub validate_doc_language
{
sub validate_doc_language {
my $language = shift;
# check for non-alphanumeric character
return 0 if ($language =~ /\W/);
@ -409,6 +450,14 @@ sub validate_doc_language
$pagedata = load_hdf();
my $current_admin_pw;
my $action = $query->param('action');
$action =~ m#^([\w\._\-]*)$#;
$action = ($1)? $1 : '';
my $device = $query->param('device');
$device =~ m#^([/_\-\w\.]*)$#;
$device = ($1)? $1 : '';
# BEWARE: there are two kinds of actions:
# * some require a harddisk
# * some do not require a harddisk
@ -423,7 +472,6 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Redirect.URL', "https://" . $hostname . $ENV{'SCRIPT_NAME'});
$pagedata->setValue('Data.Redirect.Delay', "3");
} elsif ($query->param('action')) {
my $action = $query->param('action');
#--------------------------------------------------------------#
# here you may define all cases that do not require a harddisk #
# put all other cases below the harddisk check #
@ -441,8 +489,8 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'show_doc');
}
##################### poweroff ######################
} elsif ($action eq 'shutdown_ask') {
$pagedata->setValue('Data.Action', 'form_shutdown');
} elsif ($action eq 'system_ask') {
$pagedata->setValue('Data.Action', 'form_system');
##################### reboot ########################
} elsif ($action eq 'shutdown_do') {
if ($query->param('type') eq 'reboot') {
@ -465,7 +513,11 @@ if ( ! &check_ssl()) {
#-------------------------------------------------------#
################ umount_do #######################
} elsif ($action eq 'umount_do') {
if ( ! &check_config()) {
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'emptu');
} elsif ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init');
} elsif (&check_init_running()) {
@ -473,26 +525,27 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30");
} elsif ( ! &check_mounted()) {
} elsif ( ! &check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'NotMounted');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
# unmounten
&umount_vol();
if (&check_mounted()) {
&umount_vol($device);
if (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'UmountFailed');
$pagedata->setValue('Data.Action', 'form_umount');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
$pagedata->setValue('Data.Success', 'UmountDone');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
#$pagedata->setValue('Data.Success', 'UmountDone');
$pagedata->setValue('Data.Action', 'show_volume');
}
}
################ mount_do ########################
} elsif ($action eq 'mount_do') {
# mount requested
if ( ! &check_config()) {
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'empty');
} elsif ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init');
} elsif (&check_init_running()) {
@ -500,26 +553,22 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30");
} elsif (&check_mounted()) {
} elsif (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'IsMounted');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
$pagedata->setValue('Data.Action', 'show_volume');
} elsif ($query->param('crypto_password') eq '') {
# leeres Passwort
$pagedata->setValue('Data.Warning', 'EmptyCryptoPassword');
$pagedata->setValue('Data.Action', 'form_mount');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
# mounten
&mount_vol($query->param('crypto_password'));
if (!&check_mounted()) {
&mount_vol($device, $query->param('crypto_password'));
if (!&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'MountFailed');
$pagedata->setValue('Data.Action', 'form_mount');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
$pagedata->setValue('Data.Success', 'MountDone');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
#$pagedata->setValue('Data.Success', 'MountDone');
$pagedata->setValue('Data.Action', 'show_volume');
}
}
################## mount_ask #######################
@ -532,11 +581,6 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30");
} elsif (&check_mounted()) {
$pagedata->setValue('Data.Warning', 'IsMounted');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
} else {
$pagedata->setValue('Data.Action', 'form_mount');
}
@ -545,11 +589,6 @@ if ( ! &check_ssl()) {
if ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init');
} elsif ( ! &check_mounted()) {
$pagedata->setValue('Data.Warning', 'NotMounted');
$pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
} else {
$pagedata->setValue('Data.Action', 'form_umount');
}
@ -566,7 +605,7 @@ if ( ! &check_ssl()) {
}
#################### init_do ########################
} elsif ($action eq 'init_do') {
$current_admin_pw = &get_admin_pw;
$current_admin_pw = &get_cbox_config("admin_pw");
if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_init');
@ -587,13 +626,11 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Warning', 'InitNotConfirmed');
$pagedata->setValue('Data.Action', 'form_init');
} else {
# do init
&box_init($query->param('crypto_password'),$query->param('admin_password'));
if (!&check_init_running()) {
$pagedata->setValue('Data.Error', 'InitFailed');
} else {
$pagedata->setValue('Data.Success', 'InitRunning');
if (&volume_init($query->param('crypto_password'),$query->param('admin_password'))) {
#$pagedata->setValue('Data.Success', 'InitRunning');
$pagedata->setValue('Data.Action', 'form_config');
} else {
$pagedata->setValue('Data.Error', 'InitFailed');
}
}
#################### config_ask ######################
@ -606,34 +643,33 @@ if ( ! &check_ssl()) {
}
#################### config_do #######################
} elsif ($action eq 'config_do') {
my $query_language = $query->param('language');
$query_language =~ m/^(\w+)$/; $query_language = $1;
my $query_timeout = $query->param('timeout');
$query_timeout =~ m/^(\d+)$/; $query_timeout = $1;
if ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init');
} else {
$current_admin_pw = &get_admin_pw;
$current_admin_pw = &get_cbox_config("admin_pw");
if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_config');
} elsif ( ! &validate_language($query->param('language'))) {
} elsif ( ! &validate_language($query_language)) {
$pagedata->setValue('Data.Warning', 'InvalidLanguage');
$pagedata->setValue('Data.Action', 'form_config');
} elsif ( ! &validate_ip($query->param('ip'))) {
$pagedata->setValue('Data.Warning', 'InvalidIP');
$pagedata->setValue('Data.Action', 'form_config');
} elsif ( ! &validate_timeout($query->param('timeout'))) {
} elsif ( ! &validate_timeout($query_timeout)) {
$pagedata->setValue('Data.Warning', 'InvalidTimeOut');
$pagedata->setValue('Data.Action', 'form_config');
} else {
system($CB_SCRIPT, "set_config", "language", $query->param('language'));
system($CB_SCRIPT, "set_config", "language", $query_language);
&load_selected_language($pagedata);
system($CB_SCRIPT, "set_config", "timeout", $query->param('timeout'));
system($CB_SCRIPT, "set_config", "timeout", $query_timeout);
# check, if the ip was reconfigured
if ($query->param('ip') ne &exec_cb_script("get_config","ip"))
{
# TODO: IP stuff should be moved to the live-cd stuff
if (defined($query->param('ip')) && ($query->param('ip') ne &get_cbox_config("ip"))) {
# set the new value
system($CB_SCRIPT, "set_config", "ip", $query->param('ip'));
# reconfigure the network interface
system($CB_SCRIPT, "update_ip_address");
# redirect to the new address
$pagedata->setValue('Data.Redirect.URL', "https://" . $query->param('ip') . $ENV{'SCRIPT_NAME'});
$pagedata->setValue('Data.Redirect.Delay', "5");
@ -641,20 +677,106 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Warning', 'IPAddressChanged');
}
# check for success
if (&exec_cb_script("get_config","timeout") ne $query->param('timeout')) {
if (defined($query->param('timeout'))
&& (&get_cbox_config("timeout") ne $query->param('timeout'))) {
$pagedata->setValue('Data.Warning', 'ConfigTimeOutFailed');
} elsif (&exec_cb_script("get_config","ip") ne $query->param('ip')) {
} elsif (defined($query->param('ip')) &&
(&get_cbox_config("ip") ne $query->param('ip'))) {
$pagedata->setValue('Data.Warning', 'ConfigIPFailed');
} elsif (&exec_cb_script("get_config","language") ne $query->param('language')) {
} elsif (defined($query->param('language'))
&& (&get_cbox_config("language") ne $query->param('language'))) {
$pagedata->setValue('Data.Warning', 'ConfigLanguageFailed');
} else {
$pagedata->setValue('Data.Success', 'ConfigSaved');
#$pagedata->setValue('Data.Success', 'ConfigSaved');
}
$pagedata->setValue('Data.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
}
}
############## change volume name ###################
} elsif ($action eq 'volume_name_set') {
my $volume_name = $query->param('volume_name');
# remove all special characters which are not white-listed
$volume_name =~ s#[^\w \-_\#/\(\)\[\]]##g;
# untaint variable
$volume_name =~ m#^(.*)$#; $volume_name = $1;
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'show_status');
} elsif (&check_mounted($device)) {
$pagedata->setValue('Data.Warning','VolumeMayNotBeMounted');
$pagedata->setValue('Data.Action', 'show_volume');
} elsif ($volume_name eq '') {
$pagedata->setValue('Data.Warning','InvalidVolumeName');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
&exec_cb_script('set_device_name',$device,$volume_name);
my $new_volume_name = &exec_cb_script('get_device_name',$device);
$pagedata->setValue('Data.Warning','SetVolumeNameFailed') unless ($new_volume_name eq $volume_name);
$pagedata->setValue('Data.Action', 'show_volume');
}
############ initialize volume (form) ###############
} elsif ($action eq 'volume_init_ask') {
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'show_status');
} elsif (&check_mounted($device)) {
$pagedata->setValue('Data.Warning','VolumeMayNotBeMounted');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
$pagedata->setValue('Data.CurrentDisk.InitParams.encrypted',defined($query->param('encryption'))? 1 : 0);
$pagedata->setValue('Data.Action', 'form_init_partition');
}
############### initialize volume ###################
} elsif ($action eq 'volume_init_do') {
$current_admin_pw = &get_cbox_config("admin_pw");
# remember the current "encryption" setting - just in case, we want to emit a warning and
# return to the same screen
$pagedata->setValue('Data.CurrentDisk.InitParams.encrypted',defined($query->param('encryption'))? 1 : 0);
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'show_status');
} elsif (&check_mounted($device)) {
$pagedata->setValue('Data.Warning','VolumeMayNotBeMounted');
$pagedata->setValue('Data.Action', 'show_volume');
} elsif ($current_admin_pw ne ''
&& $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_init_partition');
} elsif ($query->param('crypto_password') ne $query->param('crypto_password2')) {
# different crypto-passwords
$pagedata->setValue('Data.Warning', 'DifferentCryptoPasswords');
$pagedata->setValue('Data.Action', 'form_init_partition');
} elsif ($query->param('crypto_password') eq '') {
# empty password
$pagedata->setValue('Data.Warning', 'EmptyCryptoPassword');
$pagedata->setValue('Data.Action', 'form_init_partition');
} elsif ($query->param('confirm') ne $pagedata->getValue('Lang.Text.ConfirmInit','')) {
# wrong confirm string
$pagedata->setValue('Data.Warning', 'InitNotConfirmed');
$pagedata->setValue('Data.Action', 'form_init_partition');
} else {
if (&volume_init($device,$query->param('crypto_password'))) {
#$pagedata->setValue('Data.Success', 'InitRunning');
$pagedata->setValue('Data.Action', 'show_volume');
} else {
$pagedata->setValue('Data.Error', 'InitFailed');
$pagedata->setValue('Data.Action', 'show_volume');
}
}
################## volume info ######################
} elsif ($action eq 'show_volume') {
if ($device eq '') {
&debug_msg(DEBUG_INFO, "invalid device: " . $query->param('device'));
$pagedata->setValue('Data.Warning', 'InvalidDevice');
$pagedata->setValue('Data.Action', 'show_status');
} else {
$pagedata->setValue('Data.Action', 'show_volume');
}
#################### status #########################
} elsif ($action eq 'show_status') {
if ( ! &check_config()) {
@ -674,7 +796,7 @@ if ( ! &check_ssl()) {
# if we find an existing config partition, then check the adminpw
} elsif ($action eq 'do_purge') {
if ( &check_config()) {
$current_admin_pw = &get_admin_pw;
$current_admin_pw = &get_cbox_config("admin_pw");
if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_config');
@ -710,20 +832,17 @@ if ( ! &check_ssl()) {
# check state of the cryptobox
$pagedata->setValue('Data.Status.Config', &check_config() ? 1 : 0);
$pagedata->setValue('Data.Status.InitRunning', &check_init_running() ? 1 : 0);
$pagedata->setValue('Data.Status.Mounted', &check_mounted() ? 1 : 0) if (&check_config());
my $output = &get_current_ip();
$pagedata->setValue('Data.Status.IP', "$output");
$output = &get_admin_pw();
my $output = &get_cbox_config("admin_pw");
$pagedata->setValue('Data.Config.AdminPasswordIsSet', 1) if ($output ne '');
$output = join ("<br/>", &exec_cb_script("diskinfo"));
$pagedata->setValue('Data.PartitionInfo',"$output");
# preset config settings for clearsilver
$pagedata->setValue('Data.Config.IP', &exec_cb_script("get_config","ip"));
$pagedata->setValue('Data.Config.TimeOut', &exec_cb_script("get_config","timeout"));
$pagedata->setValue('Data.Config.Language', &exec_cb_script("get_config","language"));
$pagedata->setValue('Data.Config.IP', &get_cbox_config("ip"));
$pagedata->setValue('Data.Config.TimeOut', &get_cbox_config("timeout"));
$pagedata->setValue('Data.Config.Language', &get_cbox_config("language"));
# read log and add html linebreaks
$output = '';
@ -742,6 +861,46 @@ my $querystring = $ENV{'QUERY_STRING'};
$querystring =~ s/weblang=\w\w&?//;
$pagedata->setValue('Data.QueryString', "$querystring") if ($querystring ne '');
$pagedata->setValue('Data.Version', CRYPTOBOX_VERSION);
my ($one_disk, $one_name, $isActive);
my $avail_counter = 0; my $active_counter = 0; my $passive_counter = 0;
for $one_disk (&get_available_disks()) {
$one_name = &get_disk_name($one_disk);
$pagedata->setValue("Data.Disks.available.${avail_counter}.device",$one_disk);
$pagedata->setValue("Data.Disks.available.${avail_counter}.name",$one_name);
$isActive = &check_mounted($one_disk);
if ($isActive) {
$pagedata->setValue("Data.Disks.available.${avail_counter}.isActive",1);
$pagedata->setValue("Data.Disks.active.${active_counter}.device",$one_disk);
$pagedata->setValue("Data.Disks.active.${active_counter}.name",$one_name);
$active_counter++;
} else {
$pagedata->setValue("Data.Disks.available.${avail_counter}.isActive",0);
$pagedata->setValue("Data.Disks.passive.${passive_counter}.device",$one_disk);
$pagedata->setValue("Data.Disks.passive.${passive_counter}.name",$one_name);
$passive_counter++;
}
if ($device eq $one_disk) {
$pagedata->setValue('Data.CurrentDisk.device', $one_disk);
$pagedata->setValue('Data.CurrentDisk.name', $one_name);
$pagedata->setValue('Data.CurrentDisk.active', $isActive? 1 : 0);
# retrieve capacity information if the device is mounted
if (&check_mounted($device)) {
my $cap_info = &exec_cb_script("get_capacity_info",$device);
# filter the relevant values (a simple split is not working, as the device name may
# contain spaces
$cap_info =~ m#^.*\s+([0-9\.,]+\w)\s+([0-9\.,]+\w)\s+([0-9\.,]+\w)\s+([0-9\.,]+\%)\s+#;
my ($cap_size, $cap_used, $cap_free, $cap_percent) = ($1, $2, $3, $4);
$pagedata->setValue('Data.CurrentDisk.capacity.used', $cap_used);
$pagedata->setValue('Data.CurrentDisk.capacity.free', $cap_free);
$pagedata->setValue('Data.CurrentDisk.capacity.size', $cap_size);
$pagedata->setValue('Data.CurrentDisk.capacity.percent', $cap_percent);
}
}
$avail_counter++;
}
&render();
close STDOUT;

View file

@ -40,10 +40,7 @@ case "$1" in
;;
stop )
# unmount all active containers
ls ~$CRYPTOBOX_USER/mnt/ | while read mnt_dir
do grep -q " ~$CRYPTOBOX_USER/mnt/$mnt_dir " /proc/mounts || continue
"$LIB_DIR/cbox-manage.sh" crypto-down "$mnt_dir"
done
"$LIB_DIR/cbox-manage.sh" umount_all
;;
restart )
"$0" stop

191
bin/ro-system.sh Normal file
View file

@ -0,0 +1,191 @@
function create_config()
# Parameter: device
{
local device=$1
unload_config
# create the new configuration filesystem if it is not static
if [ "$USE_SEPERATE_CONFIG_PARTITION" != "1" ]
then log_msg "Using static configuration ..."
else log_msg "Creating config filesystem ..."
"$ROOT_PERM_SCRIPT" create_config "$device"
log_msg "Mounting config partition ..."
"$ROOT_PERM_SCRIPT" mount_config "$device"
"$ROOT_PERM_SCRIPT" remount_config rw
fi
log_msg "Copying configuration defaults ..."
cp -a "$CONFIG_DEFAULTS_DIR/." "$CONFIG_DIR"
log_msg "Copying temporary certificate file to config filesystem ..."
log_msg "Setting inital values ..."
# beware: config_set_value remounts the config partition read-only
config_set_value "ip" "$(get_current_ip)"
# create database of readable names
config_set_value "names.db" ""
# create a marker to recognize a cryptobox partition
# this should be the last step, to prevent a half-initialized state
config_set_value "$CONFIG_MARKER" "$(date -I)"
}
function find_harddisk()
# look for the harddisk to be partitioned
{
local device=$(get_available_disks | head -1)
if [ -z "$device" ] ; then
log_msg "no valid harddisk for initialisation found!"
cat /proc/partitions >>"$LOG_FILE"
# do not return with an error, to avoid a failing of the script ('break on error')
# the caller of this function should handle an empty return string
fi
echo -n "$device"
}
function load_config()
{
unload_config
local status=0
# look for a configuration partition
[ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && \
list_partitions_of_type config | while read part && [ "$status" = 0 ]
do log_msg "configuraton found on $part"
# error check?
"$ROOT_PERM_SCRIPT" mount_config "/dev/$part"
status=1
done
if is_config_active
then return 0
else log_msg "failed to locate config partition"
return 1
fi
}
function unload_config()
{
is_config_active || return
# only try to unmount, if it is not static (the config of a live-cd is always dynamic)
if [ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ]
then "$ROOT_PERM_SCRIPT" umount_config
else return 0
fi
}
# rename to "prepare_cryptobox"
function init_cryptobox()
# this is only the first part of initialisation that takes no time - good for a smooth web interface
{
local device=$(find_harddisk)
[ -z "$device" ] && log_msg 'No valid harddisk found!' && return 1
turn_off_all_crypto
unload_config || true
log_msg "Partitioning the device ($device) ..."
"$ROOT_PERM_SCRIPT" partition_disk "$device" "0,1,L \n,,L\n"
log_msg "Initializing config partition on ${device}1 ..."
# TODO: this should not be hard-coded
create_config "${device}1"
}
case "$ACTION" of
network-up )
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
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"
fi
if [ "$EXEC_FIREWALL_RULES" = 1 ]
then log_msg "Starting the firewall ..."
"$FIREWALL_SCRIPT" start
fi
if [ "$USE_STUNNEL" = 1 ]
then # start stunnel
if [ -f "$CERT_FILE" ]
then USE_CERT=$CERT_FILE
else USE_CERT=$CERT_TEMP
$MAKE_CERT_SCRIPT "$CERT_TEMP" >>"$LOG_FILE" 2>&1
# TODO: this could be dangerous - right?
# this is necessary, to allow www-data to copy the certificate
chown "$WEB_USER" "$CERT_TEMP"
fi
log_msg "Starting stunnel ..."
stunnel -p "$USE_CERT" -r localhost:80 -d 443 \
|| echo "$USE_CERT not found - not starting stunnel"
fi
;;
network-down )
if [ "$EXEC_FIREWALL_RULES" = 1 ]
then log_msg "Stopping the firewall ..."
"$FIREWALL_SCRIPT" stop
fi
if [ "$USE_STUNNEL" = 1 ]
then log_msg "Stopping stunnel ..."
# TODO: what about a pid?
killall stunnel 2>/dev/null || true
fi
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
then log_msg "Shutting the network interface 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
# TODO: do this only for ro-filesystem
# TODO: this way of mounting is evil
if mountpoint -q "$MNT_PARENT"
then true
else mount -t tmpfs tmpfs "$MNT_PARENT"
fi
true
;;
services-down )
# this action is called as root - so we are allowed to umount
mountpoint -q "$MNT_PARENT" && umount "$MNT_PARENT"
# TODO: we should not depend on samba and thttpd
# /etc/init.d/samba stop || true
# /etc/init.d/thttpd stop || true
true
;;
is_harddisk_available )
[ -z "$(find_harddisk)" ] && exit 1
exit 0
;;
update_ip_address )
# reconfigure the network interface to a new IP address
# wait for 5 seconds to finish present http requests
if [ "$SKIP_NETWORK_CONFIG" != 1 ]
then echo -n "sleep 5; \"$ROOT_PERM_SCRIPT\" update_network" | at now
fi
;;
poweroff )
log_msg "Turning off the CryptoBox ..."
turn_off_all_crypto
echo "poweroff" | at now
;;
reboot )
log_msg "Rebooting the CryptoBox ..."
turn_off_all_crypto
echo "reboot" | at now
;;
* )
echo "Syntax: $(basename $0) ACTION"
echo " config-up - scan for configuration partition and mount it"
echo " config-down - unmount configuration partition"
echo " network-up - enable network interface"
echo " network-down - disable network interface"
echo " services-up - run some cryptobox specific daemons"
echo " services-down - stop some cryptobox specific daemons"
echo " update_ip_address - update the network interface after reconfiguration"
echo " is_config_mounted - check, if configuration partition is mounted"
echo " box-init - initialize cryptobox (ALL data is LOST)"
echo " box-init-fg - the first part of initialization"
echo " box-init-bg - the last part of initialization (background)"
echo " is_harddisk_available - check, if there is a usable harddisk"
echo " poweroff - shutdown the cryptobox"
echo " reboot - reboot the cryptobox"
echo
;;
esac

View file

@ -2,14 +2,8 @@
# so there should be no space around the "="
LANGUAGE=en
NET_IFACE=eth0
CRYPTOBOX_USER=cryptobox
SCAN_DEVICES="sda"
#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
SCAN_DEVICES="sd loop"
# web interface
HTML_TEMPLATE_DIR=/usr/share/cryptobox/templates
@ -22,7 +16,6 @@ CONFIG_DEFAULTS_DIR=/usr/share/cryptobox/defaults
# some files
LOG_FILE=/var/log/cryptobox.log
CONFIG_MARKER=cryptobox.marker
# crypto settings
# TODO: for now, the usual default cipher does not work on ARM, so we enable it during development
@ -33,3 +26,11 @@ DEV_MAPPER_DIR=/dev/mapper
# distribution specific configuration
# examples can be found in /usr/local/share/cryptobox/distributions
DISTRIBUTION_CONF=/etc/cryptobox/distribution.conf
# choose a debug level:
# 0 => no debug messages at all
# 1 => critical errors (default)
# 2 => warning messages
# 3 => information
DEBUG_LEVEL=1

View file

@ -6,4 +6,7 @@ CRYPTSETUP=/sbin/cryptsetup
IFCONFIG=/sbin/ifconfig
PMOUNT=/bin/pmount
PUMOUNT=/bin/pumount
DUMPE2FS=/sbin/dumpe2fs
POWEROFF=/sbin/poweroff
REBOOT=/sbin/reboot

4
debian/control vendored
View file

@ -7,9 +7,9 @@ Standards-Version: 3.6.2
Package: cryptobox
Architecture: any
Depends: bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), perl, httpd-cgi, hashalot, libconfigfile-perl, cryptsetup (>=20050111), dmsetup, at, pmount
Depends: bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), perl, httpd-cgi, hashalot, libconfigfile-perl, cryptsetup (>=20050111), dmsetup, pmount, initscripts
Recommends: perl-clearsilver
Suggests: stunnel, cron, iptables, samba
Suggests: cron, samba
Description: Web interface for an encrypting fileserver
This bundle of scripts and cgis allow you to manage an encrypted harddisk
via a web interface. The data is platform independently available

4
debian/prerm vendored
View file

@ -1,5 +1,7 @@
#!/bin/sh
# TODO: we should remove everything, except for "invoke-rc.d"
# read the default setting file, if it exists
[ -e /etc/default/cryptobox ] && . /etc/default/cryptobox
@ -8,7 +10,7 @@ CONF_FILE=${CONF_FILE:-/etc/cryptobox/cryptobox.conf}
# parse config file
if test -e "$CONF_FILE"
then . "$CONF_FILE"
then source "$CONF_FILE"
else echo "[$(basename $0)] - configuration file ($CONF_FILE) not found!" >&2
exit 1
fi

View file

@ -12,7 +12,7 @@ Lang {
Umount = Deaktivierung der Crypto-Daten
Config = Konfiguration der CryptoBox
Log = Protokoll der CryptoBox
ShutDown = System
System = System
Status = Status der CryptoBox
}
@ -44,7 +44,7 @@ Lang {
Button {
DoInit = CryptoBox initialisieren
DoInit = Initialisierung
SaveConfig = Speichere Konfiguration
Update = Aktualisieren
Mount = Crypto-Daten aktivieren
@ -52,8 +52,8 @@ Lang {
Config = Einstellungen
PowerOff = ausschalten
ReBoot = neu starten
Protocol = Protokoll
Documentation = Handbuch
Protocol = Protokoll anzeigen
Documentation = Hilfe
Status = Status
}

View file

@ -12,8 +12,9 @@ Lang {
Umount = Deactivation of encrypted data
Config = CryptoBox configuration
Log = CryptoBox logfiles
ShutDown = System
System = System
Status = Status
Volume = Properties of
}
@ -24,10 +25,10 @@ Lang {
EnterCurrentAdminPassword = Enter the current administration password:
EnterNewAdminPassword = Enter the new administration password:
EnterSameAdminPassword = Repeat the new administration password:
InitWarning = During the process of initialization ALL DATA on the hard drive WILL BE DELETED!
InitWarning = During the process of initialization ALL DATA on the disk WILL BE DELETED!
ConfirmInitHint = To confirm that you know what you are doing, please enter exactly the following sequence:
ConfirmInit = Yes, delete all data!
PartitionInfo = Current partioning of the hard drive:
PartitionInfo = Current partioning of the disk:
IPAddress = Network address (IP) of the CryptoBox:
TimeOut = Timeout for deactivation of the encrypted filesystem (in minutes):
EmptyLog = The logfiles of the CryptoBox are empty.
@ -40,11 +41,17 @@ Lang {
Configuration = Configuration
CryptoIsActive = The encrypted data is accessible.
CryptoIsDown = The encrypted data is protected from any access.
ChoosePartition = Which container do you want to enable?
ChosenPartition = The chosen container is
ActivePartitions = The following containers are enabled
PassivePartitions = The following containers are disabled
ContainerName = Container's name:
ContainerEncryption = Enable encryption
}
Button {
DoInit = Initialize CryptoBox
DoInit = Initialization
SaveConfig = Save configuration
Update = Refresh
Mount = Activate encrypted filesystem
@ -52,9 +59,12 @@ Lang {
Config = Configuration
PowerOff = Shutdown
ReBoot = Reboot
Protocol = Logfiles
Documentation = Manual
Protocol = Show logfiles
Documentation = Help
Status = Status
System = System
ContainerNameSet = Change name
InitContainer = Initialize container
}
@ -91,7 +101,7 @@ Lang {
UmountFailed {
Title = Deactivation failed
Text = The encrypted filesystem could not be activated. Probably some files are still in use. Close all unclean programs (for example that widely used word processor). In case of need just shut down the CryptoBox!
Text = The encrypted filesystem could not be deactivated. Probably some files are still in use. Close all unclean programs (for example that widely used word processor). In case of emergency just shut down the CryptoBox!
}
NotInitialized {
@ -153,6 +163,36 @@ Lang {
Title = Change of network address
Text = The network address has been changed. In a few seconds you will get redirected to the new address.
}
NoDiskAvailableForMount {
Title = No partition available
Text = There is no unused container available. Maybe all containers are already mounted?
}
NoDiskAvailableForUmount {
Title = No partition available
Text = There is no active container available for turning off. Maybe there is no active container?
}
InvalidDevice {
Title = Invalid device
Text = The device you have chosen is invalid!
}
InvalidVolumeName {
Title = Changing of container's name failed
Text = The supplied new name of the container was invalid. Please try again!
}
SetVolumeNameFailed {
Title = Changing of container's name failed
Text = Could not change the name of the container. Take a look at the log files for details.
}
VolumeMayNotBeMounted {
Title = The container is mounted
Text = This action is not available while the container is active. Please turn it off first.
}
}
@ -207,8 +247,8 @@ Lang {
}
NoHardDisk {
Title = No hard drive
Text = No hard drive suitable for saving the encrypted filesystem found. Please ensure the BIOS detected the hard drive during power-on of the comuter.
Title = No hard disk
Text = No disk suitable for an encrypted filesystem found. Please ensure the BIOS detected the disk during power-on of the computer.
}
}

26
scripts/check_languages.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/sh
#
# compare the defined fields of a language file with the english translation
#
# nice for finding unavailable definitions
#
# Parameter: LANGUAGE
# (e.g. "de")
#
set -u
LANG_DIR=$(dirname $0)/../lang
DEFAULT_LANG=en
TMP_FILE1=/tmp/$(basename $0)-$$-1
TMP_FILE2=/tmp/$(basename $0)-$$-2
[ $# -ne 1 ] && echo -e "Syntax: $(basename $0) LANGUAGE\n" >&2 && exit 1
grep "=" "$LANG_DIR/${DEFAULT_LANG}.hdf" | grep -v "^[[:space:]]*#" | cut -f 1 -d "=" >"$TMP_FILE1"
grep "=" "$LANG_DIR/${1}.hdf" | grep -v "^[[:space:]]*#" | cut -f 1 -d "=" >"$TMP_FILE2"
diff -wu "$TMP_FILE1" "$TMP_FILE2"
rm "$TMP_FILE1" "$TMP_FILE2"

View file

@ -1,3 +1,3 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<!-- what else would you expect here? -->
<?cs # what else would you expect here? ?>

View file

@ -1,3 +1,3 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<?cs call:error(Data.Error) ?>

View file

@ -1,18 +1,18 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<?cs if:Data.Redirect ?>
<p class="warning"><a href="<?cs if:Data.Redirect.URL ?><?cs var:Data.Redirect.URL ?><?cs else ?><?cs call:getSelfURL('action=' + Data.Redirect.Action, '') ?><?cs /if ?>"><?cs var:Lang.Text.RedirectNote ?></a></p>
<p class="warning"><a href="<?cs if:Data.Redirect.URL ?><?cs var:Data.Redirect.URL ?><?cs else ?><?cs call:link('action',Data.Redirect.Action,'','','','') ?><?cs /if ?>"><?cs var:Lang.Text.RedirectNote ?></a></p>
<?cs /if ?>
</div><!-- end of 'words' -->
<div id="footer">
<!-- Development or not -->
<?cs # Development or not ?>
<?cs if:(Data.Status.DevelopmentMode == 1) ?>
<div id="development">!Development Mode!</div>
<?cs /if ?>
<!-- Version -->
v0.3&nbsp;&nbsp;
<?cs # Version ?>
v<?cs var:Data.Version ?>&nbsp;&nbsp;
<a href="http://cryptobox.org" title="<?cs var:Lang.Text.ProjectHomePage ?>">CryptoBox-Home</a> <?cs var:Lang.Text.ProjectNote ?>&nbsp;<a href="https://systemausfall.org/senselab" title="systemausfall.org">sense.lab</a>
</div>
@ -29,7 +29,8 @@ Data.Status.IP=<?cs var:Data.Status.IP ?>
Data.Status.Mounted=<?cs var:Data.Status.Mounted ?>
CBOX-STATUS-end -->
<!-- $Revision$ -->
<?cs # $Revision$ ?>
</body>
</html>

View file

@ -1,31 +1,34 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<div id="config">
<h1><?cs var:Lang.Title.Config ?></h1>
<?cs call:print_form_header() ?>
<?cs if:Data.Config.AdminPasswordIsSet ?>
<p><label for="current_admin_password"><?cs call:help_popUp(Lang.Text.EnterCurrentAdminPassword,"prove_admin_pw") ?></label><br/>
<input type="password" id="current_admin_password" name="current_admin_password" size="20" tabindex="0" maxlength="40" /> </p>
<p><label for="current_admin_password"><?cs var:html_escape(Lang.Text.EnterCurrentAdminPassword) ?></label><br/>
<input type="password" id="current_admin_password" name="current_admin_password" size="20" maxlength="40" /> </p>
<?cs /if ?>
<p><label for="ip"><?cs call:help_popUp(Lang.Text.IPAddress,'set_ip_address') ?></label><br/>
<input type="text" id="ip" size="16" maxsize="15" name="ip" tabindex="1"
<!-- turned off - will get moved to system-settings
<p><label for="ip"><?cs var:html_escape(Lang.Text.IPAddress) ?></label><br/>
<input type="text" id="ip" size="16" maxsize="15" name="ip"
value="<?cs var:Data.Config.IP ?>" /><p>
-->
<p><label for="timeout"><?cs call:help_popUp(Lang.Text.TimeOut,'set_timeout') ?></label><br/>
<input type="text" id="timeout" size="5" maxsize="5" name="timeout" tabindex="2"
<p><label for="timeout"><?cs var:html_escape(Lang.Text.TimeOut) ?></label><br/>
<input type="text" id="timeout" size="5" maxsize="5" name="timeout"
value="<?cs var:Data.Config.TimeOut ?>" /></p>
<p><label for="language"><?cs call:help_popUp(Lang.Text.SelectLanguage,'set_language') ?></label><br/>
<select name="language" tabindex="3">
<p><label for="language"><?cs var:html_escape(Lang.Text.SelectLanguage) ?></label><br/>
<select name="language">
<?cs each:item = Data.Languages ?>
<option value="<?cs name:item ?>" <?cs if:(name(item) == Data.Config.Language) ?>selected="selected"<?cs /if ?>><?cs var:item ?></option>
<?cs /each ?>
</select></p>
<input type="hidden" name="action" value="config_do" />
<button type="submit" tabindex="100"><?cs var:Lang.Button.SaveConfig ?></button>
<button type="submit"><?cs var:Lang.Button.SaveConfig ?></button>
</form>
</div>

View file

@ -1,4 +1,4 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Init ?></h1>
@ -6,19 +6,7 @@
<?cs call:print_form_header() ?>
<p class="note"><?cs var:Lang.Text.InitWarning ?></p>
<?cs if:Data.Config.AdminPasswordIsSet ?>
<p><label for="current_admin_password"><?cs call:help_popUp(Lang.Text.EnterCurrentAdminPassword,"prove_admin_pw") ?></label><br/>
<input type="password" id="current_admin_password" name="current_admin_password" size="20" maxlength="40" /> </p>
<?cs /if ?>
<p><label for="admin_password"><?cs call:help_popUp(Lang.Text.EnterNewAdminPassword,"new_admin_pw") ?></label><br/>
<input type="password" id="admin_password" name="admin_password" size="20" maxlength="40" /> </p>
<p><label for="admin_password2"><?cs call:help_popUp(Lang.Text.EnterSameAdminPassword,"new_admin_pw_repeat") ?></label><br/>
<input type="password" id="admin_password2" name="admin_password2" size="20" maxlength="40" /></p>
<p><label for="crypto_password"><?cs call:help_popUp(Lang.Text.EnterNewCryptoPassword,"crypto_pw") ?></label><br/>
<input type="password" id="crypto_password" name="crypto_password" size="20" maxlength="40" /></p>
<p><label for="crypto_password2"><?cs call:help_popUp(Lang.Text.EnterSameCryptoPassword,'crypto_pw_repeat') ?></label><br/>
<input type="password" id="crypto_password2" name="crypto_password2" size="20" maxlength="40" /></p>
<p><label for="confirm"><?cs call:help_popUp(Lang.Text.ConfirmInitHint,'confirm_text') ?><br/>
<p><label for="confirm"><?cs var:html_escape(Lang.Text.ConfirmInitHint) ?><br/>
<span class="note" id="confirmtext"><?cs var:Lang.Text.ConfirmInit ?></span></label><br/>
<input type="text" id="confirm" name="confirm" size="30" maxlength="50" /></p>
<input type="hidden" name="action" value="init_do" />
@ -28,7 +16,11 @@
<hr/>
<!-- TODO: maybe place here some kind of initialization information
this should be open for different kinds of init methods (live-cd, ???)
<div class="partition_info">
<h2><?cs var:Lang.Text.PartitionInfo ?></h2>
<p><?cs var:Data.PartitionInfo ?></p>
</div>
-->

View file

@ -0,0 +1,33 @@
<?cs # $Id$ ?>
<h1><?cs var:html_escape(Lang.Title.Init) ?></h1>
<?cs call:print_form_header() ?>
<p class="note"><?cs var:Lang.Text.InitWarning ?></p>
<?cs if:Data.Config.AdminPasswordIsSet ?>
<p><label for="current_admin_password"><?cs
var:html_escape(Lang.Text.EnterCurrentAdminPassword) ?></label><br/>
<input type="password" id="current_admin_password" name="current_admin_password"
size="20" maxlength="40" /></p><?cs /if ?>
<?cs if:Data.CurrentDisk.InitParams.encrypted ?>
<p><label for="crypto_password"><?cs var:html_escape(Lang.Text.EnterNewCryptoPassword)
?></label><br/>
<input type="password" id="crypto_password" name="crypto_password"
size="20" maxlength="40" /></p>
<p><label for="crypto_password2"><?cs var:html_escape(Lang.Text.EnterSameCryptoPassword)
?></label><br/>
<input type="password" id="crypto_password2" name="crypto_password2"
size="20" maxlength="40" />
<input type="hidden" name="encryption" value="selected" /></p>
<?cs /if ?>
<p><label for="confirm"><?cs var:html_escape(Lang.Text.ConfirmInitHint) ?><br/>
<span class="note" id="confirmtext"><?cs var:html_escape(Lang.Text.ConfirmInit) ?></span></label><br/>
<input type="text" id="confirm" name="confirm" size="30" maxlength="50" /></p>
<p><input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="volume_init_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.InitContainer) ?></button></p>
</form>

View file

@ -1,15 +1,39 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Mount ?></h1>
<?cs if:subcount(Data.Disks.passive) == 0 ?>
<?cs call:warning('NoDiskAvailableForMount') ?>
<?cs else ?>
<h1><?cs var:Lang.Title.Mount ?></h1>
<div align="center">
<div align="center">
<?cs call:print_form_header() ?>
<?cs if:subcount(Data.Disks.passive) > 1 ?>
<p><label for="device"><?cs var:Lang.Text.ChoosePartition ?></label>
<select name="device" id="device" size="0">
<?cs each:partition = Data.Disks.passive ?><option value="<?cs
var:partition.device ?>"><?cs
var:partition.name ?></option>
<?cs /each ?>
</select></p>
<?cs else ?>
<p><?cs var:html_escape(Lang.Text.ChosenPartition) ?>: <?cs
var:Data.Disks.passive.0.name ?></p>
<input type="hidden" name="device" value="<?cs
var:Data.Disks.passive.0.device ?>"/>
<?cs /if ?>
<p><label for="crypto_passwort"><?cs var:Lang.Text.EnterCurrentCryptoPassword ?></label>
<input type="password" id="crypto_password" name="crypto_password" size="20" tabindex="0" maxlength="40" /></p>
<input type="password" id="crypto_password" name="crypto_password" size="20" maxlength="40" /></p>
<input type="hidden" name="action" value="mount_do" />
<button type="submit" tabindex="100"><?cs var:Lang.Button.Mount ?></button>
<button type="submit"><?cs var:Lang.Button.Mount ?></button>
</form>
</div>
</div>
<?cs /if ?>

View file

@ -1,19 +0,0 @@
<!-- $Id$ -->
<h1><?cs var:Lang.Title.ShutDown ?></h1>
<div align="center">
<?cs call:print_form_header() ?>
<input type="hidden" name="action" value="shutdown_do" />
<input type="hidden" name="type" value="poweroff" />
<button type="submit"><?cs var:Lang.Button.PowerOff ?></button>
</form>
&nbsp;
<?cs call:print_form_header() ?>
<input type="hidden" name="action" value="shutdown_do" />
<input type="hidden" name="type" value="reboot" />
<button type="submit"><?cs var:Lang.Button.ReBoot ?></button>
</form>
</div>

29
templates/form_system.cs Normal file
View file

@ -0,0 +1,29 @@
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.System ?></h1>
<p><ul>
<?cs # poweroff ?>
<li><a href="<?cs call:link('action','shutdown_do','type','poweroff','','') ?>" title="<?cs
var:Lang.Button.PowerOff ?>"><?cs var:Lang.Button.PowerOff ?></a></li>
<?cs # reboot ?>
<li><a href="<?cs call:link('action','shutdown_do','type','reboot','','') ?>" title="<?cs
var:Lang.Button.ReBoot ?>"><?cs var:Lang.Button.ReBoot ?></a></li>
<?cs # config ?>
<li><a href="<?cs call:link('action','config_ask','','','','') ?>" title="<?cs
var:Lang.Button.Config ?>"><?cs var:Lang.Button.Config ?></a></li>
<?cs # initialize ?>
<li><a href="<?cs call:link('action','init_ask','','','','') ?>" title="<?cs
var:Lang.Button.DoInit ?>"><?cs var:Lang.Button.DoInit ?></a></li>
<?cs # show log files ?>
<li><a href="<?cs call:link('action','show_log','','','','') ?>" title="<?cs
var:Lang.Button.Protocol ?>"><?cs var:Lang.Button.Protocol ?></a></li>
</ul></p>
</div>

View file

@ -1,12 +1,37 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Umount ?></h1>
<?cs if:subcount(Data.Disks.active) == 0 ?>
<div align="center">
<?cs call:warning('NoDiskAvailableForUmount') ?>
<?cs else ?>
<h1><?cs var:Lang.Title.Umount ?></h1>
<div align="center">
<?cs call:print_form_header() ?>
<?cs if:subcount(Data.Disks.active) > 1 ?>
<p><label for="device"><?cs var:Lang.Text.ChoosePartition ?></label>
<select name="device" id="device" size="0">
<?cs each:partition = Data.Disks.active ?><option value="<?cs
var:partition.device ?>"><?cs
var:partition.name ?></option>
<?cs /each ?>
</select></p>
<?cs else ?>
<?cs # the perl code should take care, that there is at least
one mounted disk - otherwise it should display a warning ?>
<p><?cs var:html_escape(Lang.Text.ChosenPartition) ?>: <?cs
var:Data.Disks.active.0.name ?></p>
<input type="hidden" name="device" value="<?cs
var:Data.Disks.active.0.device ?>"/>
<?cs /if ?>
<input type="hidden" name="action" value="umount_do" />
<button type="submit"><?cs var:Lang.Button.Umount ?></button>
</form>
</div>
</div>
<?cs /if ?>

View file

@ -1,4 +1,4 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -12,20 +12,26 @@
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="stylesheet" media="screen" href="<?cs var:Settings.Stylesheet ?>" type="text/css" />
<?cs if:Data.Redirect.URL ?><meta http-equiv="refresh" content="<?cs var:Data.Redirect.Delay ?>;url=<?cs var:Data.Redirect.URL ?>" /><?cs
elif:Data.Redirect.Action ?><meta http-equiv="refresh" content="<?cs var:Data.Redirect.Delay ?>;url=<?cs call:getSelfURL('action=' + Data.Redirect.Action, '') ?>" /><?cs /if ?>
elif:Data.Redirect.Action ?><meta http-equiv="refresh" content="<?cs var:Data.Redirect.Delay ?>;url=<?cs call:link('action',Data.Redirect.Action,'','','','') ?>" /><?cs /if ?>
</head>
<body>
<?cs if:subcount(Data.Disks.available) > 0 ?>
<div id="volumes">
<?cs include:Settings.TemplateDir + '/show_volumes.cs' ?>
</div>
<?cs /if ?>
<div id="lang">
<?cs each:item = Data.Languages ?>
<a href="<?cs call:getSelfURL('weblang=' + name(item),'weblang') ?><?cs
<a href="<?cs call:link('weblang',name(item),'','','','') ?><?cs
if:Data.QueryString ?>&<?cs var:Data.QueryString ?><?cs /if ?>"><?cs
var:item ?></a><br/>
<?cs /each ?>
</div>
<div id="main">
<?cs if:(Data.Status.Mounted == 1) ?>
<?cs if:subcount(Data.Disks.active) > 0 ?>
<div id="head_red">
<?cs else ?>
<div id="head_green">
@ -37,7 +43,7 @@
<div id="content">
<div id="menu">
<?cs if:Data.Redirect.URL ?>
<!-- the menu bar is disabled if redirection has been suggested -->
<?cs # the menu bar is disabled if redirection has been suggested ?>
&nbsp;
<?cs else ?>
<?cs include:Settings.TemplateDir + '/nav.cs' ?>
@ -45,3 +51,4 @@
</div>
<div id="words">

View file

@ -1,42 +1,45 @@
<!-- $Id$ -->
<?cs # $Id$ ?><?cs
<?cs def:warning(warnname) ?><?cs
each:item = Lang.WarningMessage ?><?cs
if:(name(item) == warnname)
?><div class="warning">
<h1><?cs var:item.Title ?></h1>
<p><?cs var:item.Text ?></p></div>
<?cs
/if ?><?cs
/each ?><?cs
/def ?>
def:warning(warnname)
?><div class="warning"><?cs
if:?Lang.WarningMessage[warnname].Title
?>
<h1><?cs var:Lang.WarningMessage[warnname].Title ?></h1>
<p><?cs var:Lang.WarningMessage[warnname].Text ?></p>
<?cs else ?>
<h1>unknown warning message</h1>
<p>could not find warning message: '<?cs var:warnname ?>'</p>
<?cs /if ?></div><?cs
/def ?><?cs
<?cs def:error(errname) ?><?cs
each:item = Lang.ErrorMessage ?><?cs
if:(name(item) == errname)
?><div class="error">
<h1><?cs var:item.Title ?></h1>
<p><?cs var:item.Text ?></p></div>
<?cs
/if ?><?cs
/each ?><?cs
/def ?>
def:error(errname)
?><div class="error"><?cs
if:?Lang.ErrorMessage[errname].Title
?>
<h1><?cs var:Lang.ErrorMessage[errname].Title ?></h1>
<p><?cs var:Lang.ErrorMessage[errname].Text ?></p>
<?cs else ?>
<h1>unknown error message</h1>
<p>could not find error message: '<?cs var:errname ?>'</p>
<?cs /if ?></div><?cs
/def ?><?cs
<?cs def:success(succname) ?><?cs
each:item = Lang.SuccessMessage ?><?cs
if:(name(item) == succname)
?><div class="success">
<h1><?cs var:item.Title ?></h1>
<p><?cs var:item.Text ?></p></div>
<?cs
/if ?><?cs
/each ?><?cs
/def ?>
def:success(succname)
?><div class="success"><?cs
if:?Lang.SuccessMessage[succname].Title
?>
<h1><?cs var:Lang.SuccessMessage[succname].Title ?></h1>
<p><?cs var:Lang.SuccessMessage[succname].Text ?></p>
<?cs else ?>
<h1>unknown success message</h1>
<p>could not find success message: '<?cs var:succname ?>'</p>
<?cs /if ?></div><?cs
/def ?><?cs
<?cs def:parseTree(root) ?><?cs #
def:parseTree(root) ?><?cs #
# the output looks quite ugly and is not very helpful as there are
# only a few values
?><!-- data tree
@ -44,50 +47,36 @@
name:item ?>: <?cs var:item ?><?cs
each:subitem = item ?> / <?cs name:subitem ?>=<?cs var:subitem ?><?cs /each ?>
<?cs /each ?>
-->
<?cs /def ?>
--><?cs
/def ?><?cs
def:link(attr1, value1, attr2, value2, attr3, value3)
?><?cs each:attrs = Temp
?><?cs set:attrs = ""
?><?cs /each
?><?cs each:attrs = Settings.LinkAttrs
?><?cs set:Temp[url_escape(name(attrs))] = url_escape(attrs)
?><?cs /each
?><?cs if:attr1 != "" ?><?cs set:Temp[attr1] = value1 ?><?cs /if
?><?cs if:attr2 != "" ?><?cs set:Temp[attr2] = value2 ?><?cs /if
?><?cs if:attr3 != "" ?><?cs set:Temp[attr3] = value3 ?><?cs /if
?><?cs var:ScriptName
?><?cs set:first_each = 1
?><?cs if:subcount(Temp) > 0
?><?cs each:attrs = Temp
?><?cs if:(name(attrs) != "") && (attrs != "")
?><?cs if:first_each == 1 ?><?cs
set:first_each = 0 ?>?<?cs
else
?>&amp;<?cs /if
?><?cs var:url_escape(name(attrs)) ?>=<?cs var:url_escape(attrs)
?><?cs /if
?><?cs /each
?><?cs /if ?><?cs
/def ?><?cs
<?cs def:getSelfURL(append,exclude) ?><?cs #
# construct the URL of the script out of the ScriptName, Data.PostData
# (except for the value mentioned in 'exclude') and a possible
# suffix (append)
# e.g.:
# - 'append' is 'weblang=de'
# - 'exclude' is 'weblang'
# BEWARE: both parameters have to be defined!
?><?cs set:PostSuffix='' ?><?cs
set:tmp_concat='?' ?><?cs
each:item = Data.PostData ?><?cs
if:(name(item) != exclude) ?><?cs
set:PostSuffix=PostSuffix + tmp_concat + name(item) + '=' + item ?><?cs
set:tmp_concat='&' ?><?cs
/if ?><?cs
/each ?><?cs
if:(append != '') ?><?cs set:PostSuffix=PostSuffix + tmp_concat + append ?><?cs
/if ?><?cs
var:ScriptName ?><?cs var:PostSuffix ?><?cs
def:print_form_header() ?><?cs #
# the header of a form - including Setting.LinkAttrs
?><form action="<?cs call:link("","","","","","") ?>" method="post" enctype="application/x-www-from-urlencoded" accept-charset="utf-8"><?cs
/def ?>
<?cs def:help_popUp_broken(text,filename) ?><?cs #
# show a pop-up information block on the right side of the screen
# usually good for small explanatory texts
# does not work for ie?
?><a class="popup"><?cs
var:text ?><span><?cs
linclude:Settings.DocDir + '/' + Settings.DocLang + '/hints/' + filename + '.html' ?></span></a><?cs
/def ?>
<?cs def:help_popUp(text,filename) ?><?cs #
# TODO: remove this, if on-screen help will die :)
?><?cs var:text ?><?cs
/def ?>
<?cs def:print_form_header() ?><?cs #
# the header of a form - including Data.PostData values as hidden fields
?><form action="<?cs var:ScriptName ?>" method="post" enctype="application/x-www-from-urlencoded" accept-charset="utf-8">
<?cs each:item = Data.PostData
?><input type="hidden" name="<?cs name:item ?>" value="<?cs var:item ?>" /><?cs
/each ?><?cs
/def ?>

View file

@ -1,9 +1,9 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<?cs include:Settings.TemplateDir + '/macros.cs' ?>
<?cs include:Settings.TemplateDir + '/header.cs' ?>
<!-- this cryptobox template follows: <?cs var:Data.Action ?> -->
<!-- chosen cryptobox template: <?cs var:Data.Action ?> -->
<?cs if:Data.Error ?>
<?cs include:Settings.TemplateDir + '/error.cs' ?>

View file

@ -1,22 +1,26 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<!-- mounting possible? -->
<?cs # mounting possible? ?>
<?cs if:((Data.Status.Config == 1) && (Data.Status.InitRunning == 0)) ?>
<?cs if:(Data.Status.Mounted == 1) ?>
<a href="<?cs call:getSelfURL('action=umount_do','action') ?>" title="<?cs var:Lang.Text.DoUmount ?>"><?cs var:Lang.Button.Umount ?></a>
<?cs else ?>
<a href="<?cs call:getSelfURL('action=mount_ask','action') ?>" title="<?cs var:Lang.Text.DoMount ?>"><?cs var:Lang.Button.Mount ?></a>
<?cs /if ?>
<a href="<?cs call:getSelfURL('action=show_status','action') ?>" title="<?cs var:Lang.Button.Status ?>"><?cs var:Lang.Button.Status ?></a>
<!-- TODO: remove the following lines, as soon as we completely switched to the volume-based user interface
<?cs if:subcount(Data.Disks.passive) > 0 ?>
<a href="<?cs call:link('action','mount_ask','','','','') ?>" title="<?cs var:Lang.Text.DoMount ?>"><?cs var:Lang.Button.Mount ?></a><?cs /if ?>
<?cs if:subcount(Data.Disks.active) > 0 ?>
<a href="<?cs call:link('action','umount_ask','','','','') ?>" title="<?cs var:Lang.Text.DoUmount ?>"><?cs var:Lang.Button.Umount ?></a><?cs /if ?>
-->
<a href="<?cs if:subcount(Data.Disks.available) > 1
?><?cs call:link('action','show_status','','','','')
?><?cs else
?><?cs call:link('action','show_volume','device',Data.Disks.available.0.device,'','')
?><?cs /if
?>" title="<?cs var:Lang.Button.Status ?>"><?cs var:Lang.Button.Status ?></a>
<?cs /if ?>
<!-- already initialized (or at least in progress)? -->
<?cs if:(Data.Status.Config == 1) ?>
<a href="<?cs call:getSelfURL('action=config_ask','action') ?>" title="<?cs var:Lang.Text.Configuration ?>"><?cs var:Lang.Button.Config ?></a>
<?cs /if ?>
<?cs # manual ?>
<a href="<?cs call:link('action','doc','','','','') ?>" title="<?cs var:Lang.Button.Documentation ?>"><?cs var:Lang.Button.Documentation ?></a>
<a href="<?cs call:getSelfURL('action=init_ask','action') ?>" title="<?cs var:Lang.Button.DoInit ?>"><?cs var:Lang.Button.DoInit ?></a>
<a href="<?cs call:getSelfURL('action=show_log','action') ?>" title="<?cs var:Lang.Button.Protocol ?>"><?cs var:Lang.Button.Protocol ?></a>
<a href="<?cs call:getSelfURL('action=doc','action') ?>" title="<?cs var:Lang.Button.Documentation ?>"><?cs var:Lang.Button.Documentation ?></a>
<a href="<?cs call:getSelfURL('action=shutdown_ask','action') ?>" title="<?cs var:Lang.Button.PowerOff ?>"><?cs var:Lang.Button.PowerOff ?></a>
<?cs # system ?>
<a href="<?cs call:link('action','system_ask','','','','') ?>" title="<?cs var:Lang.Button.System ?>"><?cs var:Lang.Button.System ?></a>

View file

@ -1,4 +1,4 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<div id="doc">

View file

@ -1,4 +1,4 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<div id="log">

View file

@ -1,5 +1,28 @@
<!-- $Id$ -->
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Status ?></h1>
<p><?cs if:(Data.Status.Mounted == 1) ?><?cs var:Lang.Text.CryptoIsActive ?>
<?cs else ?><?cs var:Lang.Text.CryptoIsDown ?><?cs /if ?></p>
<?cs if:subcount(Data.Disks.available) == 0 ?>
<?cs # there are no partitions available ?>
<?cs # this case may never be true, as it should trigger a warning before ?>
<p>Sorry - you should have never seen this ...</p>
<?cs # elif:subcount(Data.Disks.active) == subcount(Data.Disks.available) ?>
<?cs # all available disks are mounted ?>
<?cs # we do not use this special condition now - or should we? ?>
<?cs # elif:subcount(Data.Disks.passive) == subcount(Data.Disks.available) ?>
<?cs # no available disk is mounted ?>
<?cs # we do not use this special condition now - or should we? ?>
<?cs else ?>
<?cs # some are mounted - and some are not ... ?>
<?cs if:subcount(Data.Disks.active) > 0 ?>
<p><?cs var:html_escape(Lang.Text.ActivePartitions) ?>:
<ul><?cs each:partition = Data.Disks.active ?>
<li><a href="<?cs call:link('action','show_volume','device',partition.device,'','')
?>"><?cs var:partition.name ?></a></li><?cs /each ?></ul><?cs /if ?>
<?cs if:subcount(Data.Disks.passive) > 0 ?>
<p><?cs var:html_escape(Lang.Text.PassivePartitions) ?>:
<ul><?cs each:partition = Data.Disks.passive ?>
<li><a href="<?cs call:link('action','show_volume','device',partition.device,'','')
?>"><?cs var:partition.name ?></a></li><?cs /each ?></ul><?cs /if ?>
<?cs /if ?>

64
templates/show_volume.cs Normal file
View file

@ -0,0 +1,64 @@
<?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Volume ?> <i><?cs var:html_escape(Data.CurrentDisk.name) ?></i></h1>
<?cs # is the disc active? ?>
<?cs if:!Data.CurrentDisk.active ?>
<h2>Mount container</h2>
<?cs call:print_form_header() ?>
<p><label for="crypto_passwort"><?cs var:html_escape(Lang.Text.EnterCurrentCryptoPassword) ?></label>
<input type="password" id="crypto_password" name="crypto_password" size="20" maxlength="40" />
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="mount_do" />
<button type="submit"><?cs var:Lang.Button.Mount ?></button></p>
</form>
<?cs else ?>
<h2>Unmount container</h2>
<?cs call:print_form_header() ?>
<p><input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="umount_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.Umount) ?></button></p>
</form>
<?cs /if ?>
<?cs # name change is only possible if the volume is not mounted ?>
<?cs if:!Data.CurrentDisk.active ?>
<h2>Change the name of the container</h2>
<?cs call:print_form_header() ?>
<p><label for="vol_name"><?cs var:html_escape(Lang.Text.ContainerName) ?></label>
<input type="text" name="volume_name" size="20" id="volume_name" value="<?cs var:html_escape(Data.CurrentDisk.name) ?>" />
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="volume_name_set" />
<button type="submit"><?cs var:html_escape(Lang.Button.ContainerNameSet) ?></button></p>
</form>
<?cs /if ?>
<?cs # move initialization to the "system" menu ?>
<?cs if:!Data.CurrentDisk.active ?>
<h2>Reinitialize container</h2>
<?cs call:print_form_header() ?>
<p><input type="checkbox" name="encryption" id="encryption" value="selected" checked="checked" />
<label for="encryption"><?cs var:html_escape(Lang.Text.ContainerEncryption) ?></label>
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="volume_init_ask" />
<button type="submit"><?cs var:html_escape(Lang.Button.InitContainer) ?></button></p>
</form>
<?cs /if ?>
<h2>Some more stuff</h2>
<p>For example: changing password? / backup? / access control?</p>
<h2>Details</h2>
<p><ul>
<li>Name of container: <?cs var:html_escape(Data.CurrentDisk.name) ?></li>
<li>Name of device: <?cs var:html_escape(Data.CurrentDisk.device) ?></li>
<li>Current status: <?cs if:Data.CurrentDisk.active ?>active<?cs else ?>passive<?cs /if ?></li>
<?cs if:Data.CurrentDisk.active ?>
<li>Size of container: <?cs var:html_escape(Data.CurrentDisk.capacity.size) ?></li>
<li>Available space of container: <?cs var:html_escape(Data.CurrentDisk.capacity.free) ?></li>
<li>Used space of container: <?cs var:html_escape(Data.CurrentDisk.capacity.used)
?> / <?cs var:html_escape(Data.CurrentDisk.capacity.percent) ?></li>
<?cs /if ?>
</ul></p>

15
templates/show_volumes.cs Normal file
View file

@ -0,0 +1,15 @@
<?cs # $Id$ ?>
<?cs each:volume = Data.Disks.available ?>
<a href="<?cs call:link('action','show_volume','device',volume.device,'','') ?>" title="<?cs
var:volume.name ?>">
<?cs # the "div" is the container for the background image ?>
<div class="<?cs if:volume.isActive ?>active<?cs else ?>passive<?cs /if ?><?cs
if:volume.device == Data.CurrentDisk.device ?> current<?cs /if ?>">
<p><?cs var:volume.name ?></p>
</div>
</a>
<?cs /each ?>

View file

@ -273,6 +273,7 @@ button {
font-size: 0.8em;
font-weight: bold;
cursor: pointer;
margin: 2px 10px 2px 10px;
}
button:hover {
@ -292,6 +293,38 @@ button:hover {
text-align: center;
}
/* -------------=-=-=- volume selection -=-=-=-------------- */
#volumes {
position: absolute;
float: left;
right: 5px;
left: 5px;
width: 140px;
}
#volumes div {
height: 80px;
padding: 5px;
margin: 5px;
background-repeat: no-repeat;
background-position: center;
}
#volumes div.active {
background-image: url(disc_red.png);
}
#volumes div.passive {
background-image: url(disc_green.png);
}
#volumes div.current {
border-style: dashed;
border-width: 2px;
border-color: gray;
}
/* ------------=-=-=- language selection -=-=-=------------- */
#lang {

BIN
www-data/disc_green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
www-data/disc_red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB