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 set -eu
# define reasonable defaults
USE_STUNNEL=0 # default location of config file
EXEC_FIREWALL_RULES=0
SKIP_NETWORK_CONFIG=1
CONF_FILE=/etc/cryptobox/cryptobox.conf CONF_FILE=/etc/cryptobox/cryptobox.conf
LIB_DIR=$(dirname "$0") 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 # read the default setting file, if it exists
[ -e /etc/default/cryptobox ] && . /etc/default/cryptobox [ -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 # parse config file
source "$CONF_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 # parse the distribution specific file
source "$DISTRIBUTION_CONF" source "$DISTRIBUTION_CONF"
@ -45,21 +45,26 @@ source "$DISTRIBUTION_CONF"
# check for writable log file # check for writable log file
[ -w "$LOG_FILE" ] || LOG_FILE=/tmp/$(basename "$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 ## configuration
CERT_TEMP=/tmp/stunnel.pem ROOT_PERM_SCRIPT="$LIB_DIR/cryptobox_root_wrapper"
ROOT_PERM_SCRIPT=$(dirname "$0")/cryptobox_root_wrapper
# ROOT_PERM_SCRIPT needs the MNT_PARENT setting # ROOT_PERM_SCRIPT needs the MNT_PARENT setting
export MNT_PARENT="$(cd ~; pwd)/mnt" export MNT_PARENT="$(cd ~; pwd)/mnt"
######## stuff ########## ######## 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() 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 [ -w "$LOG_FILE" ] || return 0
echo >>"$LOG_FILE" echo >>"$LOG_FILE"
echo "##### `date` #####" >>"$LOG_FILE" echo "##### `date` #####" >>"$LOG_FILE"
@ -70,6 +75,8 @@ function log_msg()
function error_msg() function error_msg()
# parameters: ExitCode ErrorMessage # 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 echo "[`date`] - $2" | tee -a "$LOG_FILE" >&2
# print the execution stack - not usable with busybox # print the execution stack - not usable with busybox
# caller | sed 's/^/\t/' >&2 # 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() function config_set_value()
# parameters: SettingName [SettingValue] # parameters: SettingName [SettingValue]
# read from stdin if SettingValue is not defined # read from stdin if SettingValue is not defined
{ {
[ "$USE_SEPERATE_CONFIG_PARTITION" = "1" ] && "$ROOT_PERM_SCRIPT" remount_config rw
if [ $# -gt 1 ] if [ $# -gt 1 ]
then echo -n "$2" > "$CONFIG_DIR/$1" then echo "$2" > "$CONFIG_DIR/$1"
else cat - >"$CONFIG_DIR/$1" else cat - >"$CONFIG_DIR/$1"
fi 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 # use mounted config, if it exists - otherwise use defaults
local conf_dir local conf_dir
if is_config_active test -z "$1" && error_msg 1 "empty setting name"
then conf_dir=$CONFIG_DIR # check for existence - maybe use default values (even for old
else conf_dir=$CONFIG_DEFAULTS_DIR # releases that did not contain this setting)
fi if test -e "$CONFIG_DIR/$1"
[ -z "$1" ] && error_msg 1 "empty setting name" then cat "$CONFIG_DIR/$1"
# check for existence - maybe use default values (for old releases without this setting) elif test -e "$CONFIG_DEFAULTS_DIR/$1"
if [ ! -e "$conf_dir/$1" ] then cat "$CONFIG_DEFAULTS_DIR/$1"
then case "$1" in else case "$1" in
# you may place default values for older versions here # you may place default values for older versions here
# for compatibility # for compatibility
* ) * )
error_msg 2 "unknown configuration value ($1)" error_msg 2 "unknown configuration value ($1)"
# empty output
;; ;;
esac esac
else echo -n $(cat "$conf_dir/$1") fi
# this removes the trailing line break return 0
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)
} }
@ -176,45 +153,73 @@ function list_partitions_of_type()
fi fi
done done
case "$1" in case "$1" in
config | crypto | plaindata | unused ) config )
# dirty hack, but it works echo "$config"
eval "echo \$$1" ;;
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 '^$' esac | tr " " "\n" | grep -v '^$'
return 0
} }
function get_crypto_uuid()
# Parameter: DEVICE # Parameter: DEVICE
{ function get_device_mnt_name() {
"$ROOT_PERM_SCRIPT" get_device_name "$1" "$ROOT_PERM_SCRIPT" get_device_mnt_name "$1"
} }
function get_crypto_name()
# Parameter: DEVICE # 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 # if undefined - return the uuid
{ function get_device_name() {
local uuid=$(get_crypto_uuid "$1") local uuid=$(get_device_uuid "$1")
local dbname=$(config_get_value "names.db" | grep "^$uuid:" | cut -d ":" -f 2-) local dbname=$(config_get_value "names.db" | grep "^$uuid:" | cut -d ":" -f 2-)
if [ -z "$dbname" ] # return dbname if it exists
then echo -n "$uuid" test -n "$dbname" && echo "$dbname" && return 0
else echo -n "$dbname" # find a nice name for the new partition
fi 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) # TODO: the implementation is quite ugly, but it works (tm)
# Parameter: DEVICE NAME # 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 # 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 # Parameter: DEVICE
{ {
local name=$(get_crypto_uuid "$1") local name=$(get_device_mnt_name "$1")
[ -n "$name" ] && mountpoint -q "$MNT_PARENT/$name" test -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"
} }
@ -299,67 +270,29 @@ function get_available_disks()
{ {
for scan in $SCAN_DEVICES for scan in $SCAN_DEVICES
do for avail in $ALL_PARTITIONS 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
done done
return 0 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() function mount_crypto()
# Parameter: DEVICE # Parameter: DEVICE
{ {
local device=$1 local device=$1
[ -z "$device" ] && error_msg 4 'No valid harddisk found!' && return 1 [ -z "$device" ] && error_msg 4 'No valid harddisk found!'
is_crypto_mounted "$device" && echo "The crypto filesystem is already active!" && return is_mounted "$device" && echo "The crypto filesystem is already active!" && return
# passphrase is read from stdin # passphrase is read from stdin
log_msg "Mounting a crypto partition from $device" log_msg "Mounting a crypto partition from $device"
"$ROOT_PERM_SCRIPT" mount "$device" >>"$LOG_FILE" 2>&1 "$ROOT_PERM_SCRIPT" mount "$device" >>"$LOG_FILE" 2>&1
} }
function umount_crypto() function umount_partition() {
# Parameter: DEVICE # Parameter: device
{ local container=$(get_device_name "$1")
local device=$1 "$ROOT_PERM_SCRIPT" umount "$1"
local uuid=$(get_crypto_uuid $device)
"$ROOT_PERM_SCRIPT" umount "$uuid"
} }
@ -375,27 +308,9 @@ function box_purge()
done done
} }
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_containers() {
function turn_off_all_crypto() "$ROOT_PERM_SCRIPT" create_plain "$1"
{
list_crypto_containers | while read a
do is_crypto_mounted "$a" && umount_crypto "$a"
done
} }
@ -409,137 +324,68 @@ ACTION=help
[ $# -gt 0 ] && ACTION=$1 && shift [ $# -gt 0 ] && ACTION=$1 && shift
case "$ACTION" in 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 ) 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" mount_crypto "$1"
;; ;;
crypto-down ) crypto-down )
[ $# -ne 1 ] && error_msg "invalid number of parameters for 'crypto-down'" [ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'crypto-down'"
umount_crypto "$1" is_device_allowed "$1" || error_msg 12 "invalid device: $1"
umount_partition "$1"
;; ;;
init ) init )
init_cryptobox </dev/null >>"$LOG_FILE" 2>&1 init_cryptobox </dev/null >>"$LOG_FILE" 2>&1
;; ;;
crypto-create ) list_container )
# Parameter: DEVICE NAME [ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'list_container'"
[ $# -ne 2 ] && error_msg "invalid number of parameters for 'crypto-create'" case "$1" in
# do it in the background to provide a smoother web interface config | unused | plaindata | crypto )
# messages and errors get written to $LOG_FILE list_partitions_of_type "$1"
keyfile=/tmp/$(basename "$0")-passphrase-$(basename "$1") ;;
# read the password * )
cat - >"$keyfile" return 1
# execute it in the background ;;
echo "'$0' crypto-create-bg '$1' '$2' '$keyfile' </dev/null >>'$LOG_FILE' 2>&1" | at now esac
return 0
;; ;;
crypto-create-bg ) get_device_name )
create_crypto "$@"
;;
crypto-list )
list_partitions_of_type crypto
;;
crypto-list-unused )
list_partitions_of_type unused
;;
crypto-name )
# Parameter: DEVICE # 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 ) set_device_name )
[ $# -ne 1 ] && error_msg 10 "invalid number of parameters for 'is_crypto_mounted'" # Parameter: DEVICE NAME
is_crypto_mounted "$1" [ $# -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 ) 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 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
fi
;;
get_available_disks ) get_available_disks )
get_available_disks get_available_disks
;; ;;
get_current_ip )
get_current_ip
;;
set_config ) set_config )
[ $# -ne 2 ] && error_msg 7 "'set_config' requires two parameters" [ $# -ne 2 ] && error_msg 7 "'set_config' requires two parameters"
config_set_value "$1" "$2" config_set_value "$1" "$2"
@ -548,53 +394,59 @@ case "$ACTION" in
[ $# -ne 1 ] && error_msg 6 "'get_config' requires exactly one parameter" [ $# -ne 1 ] && error_msg 6 "'get_config' requires exactly one parameter"
config_get_value "$1" 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 ) diskinfo )
get_available_disks | while read a get_available_disks | while read a
do "$ROOT_PERM_SCRIPT" diskinfo "$a" do "$ROOT_PERM_SCRIPT" diskinfo "$a"
done done 2>/dev/null
;; ;;
box-purge ) box-purge )
log_msg "Cleaning the CryptoBox ..." log_msg "Cleaning the CryptoBox ..."
turn_off_all_crypto turn_off_all_containers
"$0" config-down "$0" config-down
box_purge >>"$LOG_FILE" 2>&1 box_purge >>"$LOG_FILE" 2>&1
;; ;;
poweroff ) poweroff )
log_msg "Turning off the CryptoBox ..." log_msg "Shutting down the Cryptobox ..."
turn_off_all_crypto turn_off_all_containers
echo "poweroff" | at now "$ROOT_PERM_SCRIPT" poweroff
;; ;;
reboot ) reboot )
log_msg "Rebooting the CryptoBox ..." log_msg "Rebooting the Cryptobox ..."
turn_off_all_crypto turn_off_all_containers
echo "reboot" | at now "$ROOT_PERM_SCRIPT" reboot
;;
umount_all )
log_msg "Unmounting all volumes ..."
turn_off_all_containers
;; ;;
* ) * )
echo "Syntax: `basename $0` ACTION [PARAMS]" echo "[$(basename $0)] - unknown action: $ACTION" >&2
echo " config-up - scan for configuration partition and mount it" echo "Syntax: $(basename $0) ACTION [PARAMS]"
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 " crypto-up - mount crypto partition" echo " crypto-up - mount crypto partition"
echo " crypto-down - unmount crypto partition" echo " crypto-down - unmount crypto partition"
echo " box-init - initialize cryptobox (ALL data is LOST)" echo " crypto-create - a wrapper for 'crypto-create-bg'"
echo " box-init-fg - the first part of initialization" echo " crypto-create-bg - create encrypted blockdevice and run mkfs"
echo " box-init-bg - the last part of initialization (background)" echo " is_mounted - check, if crypto partition is mounted"
echo " is_crypto_mounted - check, if crypto partition is mounted" echo " check_config - check, if the configuration is usable"
echo " is_config_mounted - check, if configuration partition is mounted" echo " get_available_disks - shows all accessible disks"
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 " get_current_ip - get the current IP of the network interface" 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 " set_config NAME VALUE - change a configuration setting"
echo " get_config NAME - retrieve 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 " diskinfo - show the partition table of the harddisk"
echo " box-purge - destroy partitiontable of all harddisks (delete everything)" echo " box-purge - destroy the partition tables of all harddisks (delete everything)"
echo " poweroff - shutdown the cryptobox" echo " poweroff - turn off the computer"
echo " reboot - reboot the cryptobox" echo " reboot - reboot the computer"
echo echo
;; ;;
esac esac

View File

@ -17,6 +17,9 @@
set -eu 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 [ "$(id -u)" -ne 0 ] && echo "$(basename $0) - only root may call this script" >&2 && exit 100
# read the default setting file, if it exists # read the default setting file, if it exists
@ -29,6 +32,9 @@ source "$CONF_FILE"
# parse distribution specific file # parse distribution specific file
source "$DISTRIBUTION_CONF" source "$DISTRIBUTION_CONF"
CB_SCRIPT="$LIB_DIR/cbox-manage.sh"
CONFIG_MARKER=cryptobox.marker
############ some useful functions ############### ############ some useful functions ###############
@ -46,43 +52,54 @@ function is_device_allowed()
} }
function get_device_name() # return the uuid of the partition (if possible)
# return the uuid of the device # this only works for luks or ext2/3 partitions
# if there is no uuid, then the device name is "flattened" and returned
# ignore volume-id as it may be non-unique # ignore volume-id as it may be non-unique
{ function get_device_uuid() {
local UUID= local UUID
# check for luksUUID or ext2/3-uuid # check for luksUUID or ext2/3-uuid
if is_luks_device "$1" if is_luks_device "$1"
then UUID=$("$CRYPTSETUP" luksUUID "$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 fi
# if there is no valid UUUD, then take the flattened device name if test -z "$UUID"
is_uuid_valid "$UUID" || UUID=${1//\//_} then get_device_flat_name "$1"
echo "$UUID" 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 # every devmapper name should look like a UUID
{ function is_uuid_valid() {
local hex=[0-9a-f] 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\}$" ]] [[ "$1" =~ "^$hex\{8\}-$hex\{4\}-$hex\{4\}-$hex\{4\}-$hex\{12\}$" ]]
} }
function error_msg()
# parameter ExitCode ErrorMessage # parameter ExitCode ErrorMessage
{ function error_msg() {
echo "CBOX-ERROR: [$(basename $0) - $ACTION] - $2" >&2 echo "CBOX-ERROR: [$(basename $0) - $ACTION] - $2" >&2
exit $1 exit $1
} }
function partition_device()
# parameter: device sfdisk_layout_setup # parameter: device sfdisk_layout_setup
# e.g.: /dev/hda "0,1,L \n,,L\n" # e.g.: /dev/hda "0,1,L \n,,L\n"
{ function partition_device() {
# TODO: allow different layouts # TODO: allow different layouts
# TODO: skip config partition if a configuration is already active # TODO: skip config partition if a configuration is already active
# sfdisk -n doesn't actually write (for testing purpose) # sfdisk -n doesn't actually write (for testing purpose)
@ -97,7 +114,7 @@ function partition_device()
function is_luks_device() function is_luks_device()
# parameter: 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" [ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
is_device_allowed "$1" || \ is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
name=$(get_device_name "$1") mnt_name=$(get_device_mnt_name "$1")
mountpoint -q "$MNT_PARENT/$name" && \ mountpoint -q "$MNT_PARENT/$mnt_name" && \
error_msg 5 "a device with the same name ($name) is already mounted" error_msg 5 "a device with the same name ($mnt_name) is already mounted"
mkdir -p "$MNT_PARENT/$name" mkdir -p "$MNT_PARENT/$mnt_name"
if is_luks_device "$1" 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" 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 then true
else "$CRYPTSETUP" luksClose "$name" || true else "$CRYPTSETUP" luksClose "$mnt_name" || true
error_msg 7 "wrong password for $1 supplied" error_msg 7 "wrong password for $1 supplied"
fi fi
else mount "$1" "$MNT_PARENT/$name" || \ else mount "$1" "$MNT_PARENT/$mnt_name" || \
error_msg 8 "invalid filesystem on device $1" error_msg 8 "invalid filesystem on device $1"
fi fi
# just in case, that there is no ext2/3 filesystem: # just in case, that there is no ext2/3 filesystem:
@ -145,105 +162,86 @@ case "$ACTION" in
true true
;; ;;
umount ) umount )
#parameter: name (relative mountpoint) #parameter: device
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters" [ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
is_uuid_valid "$1" || [[ "$1" =~ "^[_a-z0-9]*$" ]] || \ is_device_allowed "$1" || \
error_msg 4 "invalid UUID ($1)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
mountpoint -q "$MNT_PARENT/$1" || \ mnt_name=$(get_device_mnt_name "$1")
error_msg 9 "the device with the UUID ($1) is not mounted" mountpoint -q "$MNT_PARENT/$mnt_name" || \
# try to unmount - continue even on errors error_msg 9 "the device ($1) is not mounted as '$mnt_name'"
umount "$MNT_PARENT/$1" || \ # try to unmount - do it in lazy mode
error_msg 0 "unmount of device $1 failed - device is busy" umount -l "$MNT_PARENT/$mnt_name"
# remove (if necessary) the dev mapping # TODO: check, what happens, if there are open files - does the device gets mapping removed?
[ -e "$DEV_MAPPER_DIR/$1" ] && "$CRYPTSETUP" luksClose "$1" || \ # remove (if necessary) the device mapping
error_msg 11 "could not remove the device mapper for device $1" 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 # try to remove the mountpoint - a failure is not important
rmdir "$MNT_PARENT/$1" || true rmdir "$MNT_PARENT/$mnt_name" || true
# set exitcode # set exitcode
mountpoint -q "$MNT_PARENT/$1" && exit 1 mountpoint -q "$MNT_PARENT/$mnt_name" && exit 1
exit 0 true
;; ;;
create_crypto ) create_crypto )
# parameter: device # parameter: device keyfile
# the passphrase is expected on stdin [ $# -ne 2 ] && error_msg 1 "wrong number of parameters"
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters" keyfile=$2
[ -e "$keyfile" ] || error_msg 2 "keyfile ($keyfile) not found"
is_device_allowed "$1" || \ is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
# read the passphrase from stdin # read the passphrase from stdin
key=$(cat -)
# the iter-time is in milliseconds - keep it low for fast mounting # the iter-time is in milliseconds - keep it low for fast mounting
echo "$key" | \ cat "$keyfile" | \
"$CRYPTSETUP" --cipher "$DEFAULT_CIPHER" --iter-time 2000 luksFormat "$1" || \ "$CRYPTSETUP" --cipher "$DEFAULT_CIPHER" --iter-time 2000 --batch-mode luksFormat "$1" || \
error_msg 11 "failed to create the encrypted partition" error_msg 11 "failed to create the encrypted partition"
name=$(get_device_name "$1") name=$(get_device_mnt_name "$1")
echo "$key" | "$CRYPTSETUP" luksOpen "$1" "$name" || \ cat "$keyfile" | "$CRYPTSETUP" --batch-mode luksOpen "$1" "$name" || \
error_msg 12 "failed to open the encrypted partition" error_msg 12 "failed to open the encrypted partition"
# silent output from mkfs.ext3 # trash the passphrase in keyfile
"$MKFS_DATA" -q "$DEV_MAPPER_DIR/$name" || \ echo "0123456789abcdefghijklmnopqrstuvwxyz" > "$keyfile"
error_msg 13 "failed to create the encrypted filesystem" # the disk cache surely prevents the previous line from being written, but we do it anyway ...
"$CRYPTSETUP" luksClose "$name" || \ echo "zyxwvutsrqponmlkjihgfedcba9876543210" > "$keyfile"
error_msg 14 "failed to close the encrypted mapped device" rm "$keyfile"
;; # complete in background
get_device_name ) ( # silent output from mkfs.ext3
# parameter: device "$MKFS_DATA" -q "$DEV_MAPPER_DIR/$name" || \
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters" error_msg 13 "failed to create the encrypted filesystem"
is_device_allowed "$1" || \ "$CRYPTSETUP" --batch-mode luksClose "$name" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" error_msg 14 "failed to close the encrypted mapped device"
get_device_name "$1" ) </dev/null &>/dev/null &
;;
mount_config )
# parameter: device
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
[ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \
error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)"
is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
mountpoint -q "$CONFIG_DIR" && \
error_msg 0 "the configuration partition is already mounted"
"$MKFS_CONFIG" -q "$1" || \
error_msg 20 "failed to create config partition filesystem"
;;
mount_config )
# parameter: device
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
[ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \
error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)"
is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
mountpoint -q "$CONFIG_DIR" && \
error_msg 0 "the configuration partition is already mounted"
mount "$1" "$CONFIG_DIR" || \
error_msg 16 "failed to mount configuration partition"
# chown to fix permissions - may fail for non-ext2/3 filesystems
chown -R "$WEB_USER" "$CONFIG_DIR" || true
mount -o remount,ro "$CONFIG_DIR" || \
error_msg 18 "failed to remount configuration partition"
true true
;; ;;
remount_config ) create_plain )
# parameter: { ro | rw } # parameter: device
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters" [ $# -ne 1 ] && error_msg 1 "wrong number of parameters for 'create_plain'"
[ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ is_device_allowed "$1" || \
error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
[[ "$1" =~ "^r[ow]$" ]] || error_msg 17 "only 'rw' and 'ro' are allowed" # complete in background
mount -o "remount,$1" "$CONFIG_DIR" || \ ( # silent output from mkfs.ext3
error_msg 18 "failed to remount configuration partition" "$MKFS_DATA" -q "$1" || \
error_msg 15 "failed to create the plaintext filesystem"
) </dev/null &>/dev/null &
true true
;; ;;
umount_config ) get_device_mnt_name )
# no parameters # parameter: device
[ $# -ne 0 ] && error_msg 1 "wrong number of parameters" [ $# -ne 1 ] && error_msg 1 "wrong number of parameters"
[ "$USE_SEPERATE_CONFIG_DIR" != "1" ] && \ is_device_allowed "$1" || \
error_msg 19 "I am configured to work without a seperate config partition (see $CONF_FILE)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
mountpoint -q "$CONFIG_DIR" && umount "$CONFIG_DIR" || \ get_device_mnt_name "$1"
error_msg 18 "failed to unmount configuration partition" ;;
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 ) is_config_partition )
# parameter: device # parameter: device
# returns exitcode 0 if the device contains a configuration # returns exitcode 0 if the device contains a configuration
[ $# -ne 1 ] && error_msg 1 "wrong number of parameters" [ $# -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" || \ is_device_allowed "$1" || \
error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)" error_msg 3 "this device ($1) is not listed in SCAN_DEVICES (see $CONF_FILE)"
is_config=0 is_config=0
@ -306,10 +304,20 @@ case "$ACTION" in
[ -e "$CONFIG_DIR/ip" ] && ip=$(<"$CONFIG_DIR/ip") [ -e "$CONFIG_DIR/ip" ] && ip=$(<"$CONFIG_DIR/ip")
[ -n "$z" ] && ifconfig "$NET_IFACE" "$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 "Syntax: $(basename $0) ACTION PARAMETERS"
echo ' partition_disk $device $disk_layout' echo ' partition_disk $device $disk_layout'
echo ' get_device_name $device' echo ' get_device_name $device'
echo ' get_device_uuid $device'
echo ' create_crypto $device' echo ' create_crypto $device'
echo ' mount $device' echo ' mount $device'
echo ' umount $name' echo ' umount $name'
@ -323,6 +331,8 @@ case "$ACTION" in
echo ' trash_device $device' echo ' trash_device $device'
echo ' diskinfo $device' echo ' diskinfo $device'
echo ' update_network' echo ' update_network'
echo ' poweroff'
echo ' reboot'
echo ' help' echo ' help'
echo echo
[ "$ACTION" == "help" ] && exit 0 [ "$ACTION" == "help" ] && exit 0

View File

@ -19,24 +19,36 @@ use ClearSilver;
use ConfigFile; use ConfigFile;
use English; use English;
use CGI::Carp; 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 # drop privileges
$UID = $EUID; $UID = $EUID;
$GID = $EGID; $GID = $EGID;
# necessary for suid perl scripts (see 'man perlsec' for details)
$ENV{'PATH'} = '/bin:/usr/bin'; $ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
my $CONFIG_FILE = '/etc/cryptobox/cryptobox.conf'; my $CONFIG_FILE = '/etc/cryptobox/cryptobox.conf';
my $pagedata; my $pagedata;
my ($LANGUAGE_DIR, $DEFAULT_LANGUAGE, $HTML_TEMPLATE_DIR, $DOC_DIR); 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 # get the directory of the cryptobox scripts/binaries and untaint it
$CB_SCRIPT = $0; $CB_SCRIPT = $0;
$CB_SCRIPT =~ m/^(.*)\/[^\/]*$/; $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); &fatal_error ("could not find configuration file ($CONFIG_FILE)") unless (-e $CONFIG_FILE);
my $config = ConfigFile::read_config_file($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}; $DOC_DIR = $config->{DOC_DIR};
$IS_DEVEL = ( -e $config->{DEV_FEATURES_SCRIPT}); $IS_DEVEL = ( -e $config->{DEV_FEATURES_SCRIPT});
$STYLESHEET_URL = $config->{STYLESHEET_URL}; $STYLESHEET_URL = $config->{STYLESHEET_URL};
if (defined($config->{DEBUG_LEVEL})) {
# TODO: just a quick-and-dirty hack during migration to multiple containers $DEBUG_LEVEL = $config->{DEBUG_LEVEL};
my $CRYPTO_DEV = &get_available_disks(); } else {
$CRYPTO_DEV =~ m/^([\w\/_\-\.]*)$/; $DEBUG_LEVEL = DEBUG_ERROR; # default debug level
$CRYPTO_DEV = "${1}2"; }
my $query = new CGI; my $query = new CGI;
#################### subs ###################### #################### subs ######################
# for fatal errors without the chance of clearsilver-rendering # for fatal errors without the chance of clearsilver-rendering
sub fatal_error() sub fatal_error() {
{
my $message = shift; my $message = shift;
print "Content-Type: text/html\n\n"; 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 $hdf = ClearSilver::HDF->new();
my $fname = "$HTML_TEMPLATE_DIR/main.cs"; 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 $data = shift;
my $config_language; my $config_language;
@ -110,7 +125,7 @@ sub load_selected_language
$data->readFile("$LANGUAGE_DIR/$DEFAULT_LANGUAGE" . ".hdf"); $data->readFile("$LANGUAGE_DIR/$DEFAULT_LANGUAGE" . ".hdf");
# load configured language, if it is valid # 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")); $config_language = $DEFAULT_LANGUAGE unless (&validate_language("$config_language"));
# check for preferred browser language, if the box was not initialized yet # check for preferred browser language, if the box was not initialized yet
@ -130,6 +145,9 @@ sub load_selected_language
# load the data # load the data
$config_language = "$weblang"; $config_language = "$weblang";
# add the setting to every link # 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"); $data->setValue('Data.PostData.weblang', "$weblang");
} else { } else {
# no valid language was selected - so you may ignore it # 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 # import the names of all available languages
{ sub get_available_languages {
my $data = shift; my $data = shift;
my ($file, @files, $hdf, $lang_name); my ($file, @files, $hdf, $lang_name);
@ -176,8 +193,7 @@ sub get_available_languages
# look for preferred browser language setting # look for preferred browser language setting
# this code was adapted from Per Cederberg - http://www.percederberg.net/home/perl/select.perl # 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 # it returns an empty string, if no supported language was found
sub get_browser_language sub get_browser_language {
{
my ($str, @langs, @res); my ($str, @langs, @res);
# Use language preference settings # Use language preference settings
@ -199,8 +215,7 @@ sub get_browser_language
} }
sub log_msg sub log_msg {
{
my $text = shift; my $text = shift;
open(LOGFILE,">> $LOG_FILE"); open(LOGFILE,">> $LOG_FILE");
print LOGFILE "$text"; 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) # check, if we are behind a proxy with ssl (e.g. pound)
return (0==0) if ($ENV{'HTTP_FRONT_END_HTTPS'} =~ m/^on$/i); return (0==0) if ($ENV{'HTTP_FRONT_END_HTTPS'} =~ m/^on$/i);
# environment variable set (e.g. via apache directive "SetEnv HTTPS On") # environment variable set (e.g. via apache directive "SetEnv HTTPS On")
return (0==0) if ($ENV{'HTTPS'} =~ m/^on$/i); return (0==0) if ($ENV{'HTTPS'} =~ m/^on$/i);
# port 80 -> not encrypted # 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 # other ports -> maybe ok - we accept it
return (0==0); return (0==0);
} }
sub check_mounted # check, if the given device is mounted/used somehow
{ # Paramter: device
return (system($CB_SCRIPT,"is_crypto_mounted",$CRYPTO_DEV) == 0); sub check_mounted {
my ($dev) = @_;
return (system($CB_SCRIPT,"is_mounted",$dev) == 0);
} }
sub check_config sub check_config {
{ return (system($CB_SCRIPT,"check_config") == 0);
return (system($CB_SCRIPT,"is_config_mounted") == 0);
} }
@ -243,50 +258,65 @@ sub exec_cb_script {
exit 0; exit 0;
} else { } else {
# parent # parent
@result = <PROG_OUT>; # only read lines containing at least one non-whitespace character
close PROG_OUT or warn "error while running $CB_SCRIPT (params:" . join(" ",@params) . "): $?"; @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) { if (wantarray) {
return @result; return @result;
} else { } elsif (@result > 0) {
return join('',@result); return join('',@result);
} else {
return "";
} }
} }
sub check_init_running sub check_init_running {
{ # TODO: improve this
return (system($CB_SCRIPT,"is_init_running") == 0); return (0==1);
} }
sub is_harddisk_available sub is_harddisk_available {
{ my @all_disks = &exec_cb_script("get_available_disks");
return (system($CB_SCRIPT,"is_harddisk_available") == 0); return @all_disks > 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 get_admin_pw sub get_available_disks {
# returns the current administration password - empty, if it is not used my @all_disks = &exec_cb_script("get_available_disks");
{ my ($disk, @return_disks);
return &exec_cb_script("get_config","admin_pw"); 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"; my $pagefile = "$HTML_TEMPLATE_DIR/main.cs";
print "Content-Type: text/html\n\n"; print "Content-Type: text/html\n\n";
@ -297,68 +327,82 @@ sub render
} }
sub mount_vol # mount an encrypted volume
{ # Parameter: device password
my $pw = shift; sub mount_vol {
my ($device, $pw) = @_;
if (&check_mounted) { if (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'IsMounted'); $pagedata->setValue('Data.Warning', 'IsMounted');
} else { } else {
open(PW_INPUT, "| $CB_SCRIPT crypto-up $CRYPTO_DEV"); open(PW_INPUT, "| $CB_SCRIPT crypto-up $device");
print PW_INPUT $pw; print PW_INPUT $pw;
close(PW_INPUT); close(PW_INPUT);
} }
} }
sub umount_vol # unmount a volume
{ # Parameter: device
if (&check_mounted) { sub umount_vol {
system($CB_SCRIPT, "crypto-down",$CRYPTO_DEV); my ($device) = @_;
if (&check_mounted($device)) {
system($CB_SCRIPT, "crypto-down",$device);
} else { } else {
$pagedata->setValue('Data.Warning', 'NotMounted'); $pagedata->setValue('Data.Warning', 'NotMounted');
} }
} }
sub box_init # Parameter: device passphrase
{ # ignore passphrase (or leave it empty) to create a plaintext volume
my ($crypto_pw, $admin_pw) = @_; sub volume_init {
my ($device, $crypto_pw) = @_;
my $result;
system($CB_SCRIPT, "init") || return 1; # only for encrypted volumes:
# write passphrase to a file - necessary as perl in secured mode does not allow
# partitioning, config and initial cryptsetup # the 'open(FH, "|/bin/prog ....")' call because of possible shell expansion - stupid 'open' :(
# TODO: define the name of the crypto container if ($crypto_pw) {
open(PW_INPUT, "|$CB_SCRIPT crypto-create '$CRYPTO_DEV' default"); my ($fh, $temp_file);
print PW_INPUT $crypto_pw; # generate a temporary filename (as suggested by the Perl Cookbook)
close(PW_INPUT); do { $temp_file = POSIX::tmpnam() }
# TODO: reduce the file mask to the minimum - maybe 0600 would be a good choice
# set administration password until $fh = IO::File->new($temp_file, O_RDWR|O_CREAT|O_EXCL);
$admin_pw =~ m/^(.*)$/; close $fh;
system($CB_SCRIPT, "set_config", "admin_pw", $1); unless (open(TMP, ">$temp_file")) {
} &debug_msg(DEBUG_ERROR, "could not open a temporary file");
return (1==0);
sub box_purge }
{ print TMP $crypto_pw;
system($CB_SCRIPT, "box-purge"); close TMP;
} $result = &exec_cb_script("device_init", $device, $temp_file);
unlink ($temp_file) if (-e $temp_file);
sub system_poweroff } else {
{ $result = &exec_cb_script("device_init", $device);
&umount_vol() if (&check_mounted()); }
system($CB_SCRIPT, "poweroff"); # 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 sub box_purge {
{ &exec_cb_script("box-purge");
&umount_vol() if (&check_mounted());
system($CB_SCRIPT, "reboot");
} }
sub validate_ip sub system_poweroff {
{ &exec_cb_script("poweroff");
}
sub system_reboot {
&exec_cb_script("reboot");
}
sub validate_ip {
my $ip = shift; my $ip = shift;
my @octets = split /\./, $ip; my @octets = split /\./, $ip;
return 0 if ($#octets == 4); return 0 if ($#octets == 4);
@ -371,8 +415,7 @@ sub validate_ip
} }
sub validate_timeout sub validate_timeout {
{
my $timeout = shift; my $timeout = shift;
return 0 if ($timeout =~ /\D/); return 0 if ($timeout =~ /\D/);
return 1; return 1;
@ -380,8 +423,7 @@ sub validate_timeout
# check for a valid interface language # check for a valid interface language
sub validate_language sub validate_language {
{
my $language = shift; my $language = shift;
# check for non-alphanumeric character # check for non-alphanumeric character
return 0 if ($language =~ /\W/); return 0 if ($language =~ /\W/);
@ -392,8 +434,7 @@ sub validate_language
# check for a valid documentation language # check for a valid documentation language
sub validate_doc_language sub validate_doc_language {
{
my $language = shift; my $language = shift;
# check for non-alphanumeric character # check for non-alphanumeric character
return 0 if ($language =~ /\W/); return 0 if ($language =~ /\W/);
@ -409,6 +450,14 @@ sub validate_doc_language
$pagedata = load_hdf(); $pagedata = load_hdf();
my $current_admin_pw; 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: # BEWARE: there are two kinds of actions:
# * some require a harddisk # * some require a harddisk
# * some do not 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.URL', "https://" . $hostname . $ENV{'SCRIPT_NAME'});
$pagedata->setValue('Data.Redirect.Delay', "3"); $pagedata->setValue('Data.Redirect.Delay', "3");
} elsif ($query->param('action')) { } elsif ($query->param('action')) {
my $action = $query->param('action');
#--------------------------------------------------------------# #--------------------------------------------------------------#
# here you may define all cases that do not require a harddisk # # here you may define all cases that do not require a harddisk #
# put all other cases below the harddisk check # # put all other cases below the harddisk check #
@ -441,8 +489,8 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'show_doc'); $pagedata->setValue('Data.Action', 'show_doc');
} }
##################### poweroff ###################### ##################### poweroff ######################
} elsif ($action eq 'shutdown_ask') { } elsif ($action eq 'system_ask') {
$pagedata->setValue('Data.Action', 'form_shutdown'); $pagedata->setValue('Data.Action', 'form_system');
##################### reboot ######################## ##################### reboot ########################
} elsif ($action eq 'shutdown_do') { } elsif ($action eq 'shutdown_do') {
if ($query->param('type') eq 'reboot') { if ($query->param('type') eq 'reboot') {
@ -465,7 +513,11 @@ if ( ! &check_ssl()) {
#-------------------------------------------------------# #-------------------------------------------------------#
################ umount_do ####################### ################ umount_do #######################
} elsif ($action eq '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.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init'); $pagedata->setValue('Data.Action', 'form_init');
} elsif (&check_init_running()) { } elsif (&check_init_running()) {
@ -473,26 +525,27 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config'); $pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30"); $pagedata->setValue('Data.Redirect.Delay', "30");
} elsif ( ! &check_mounted()) { } elsif ( ! &check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'NotMounted'); $pagedata->setValue('Data.Warning', 'NotMounted');
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'show_volume');
} else { } else {
# unmounten # unmounten
&umount_vol(); &umount_vol($device);
if (&check_mounted()) { if (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'UmountFailed'); $pagedata->setValue('Data.Warning', 'UmountFailed');
$pagedata->setValue('Data.Action', 'form_umount'); $pagedata->setValue('Data.Action', 'show_volume');
} else { } else {
$pagedata->setValue('Data.Success', 'UmountDone'); #$pagedata->setValue('Data.Success', 'UmountDone');
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'show_volume');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
} }
} }
################ mount_do ######################## ################ mount_do ########################
} elsif ($action eq 'mount_do') { } elsif ($action eq 'mount_do') {
# mount requested if ($device eq '') {
if ( ! &check_config()) { &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.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init'); $pagedata->setValue('Data.Action', 'form_init');
} elsif (&check_init_running()) { } elsif (&check_init_running()) {
@ -500,26 +553,22 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config'); $pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30"); $pagedata->setValue('Data.Redirect.Delay', "30");
} elsif (&check_mounted()) { } elsif (&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'IsMounted'); $pagedata->setValue('Data.Warning', 'IsMounted');
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'show_volume');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
} elsif ($query->param('crypto_password') eq '') { } elsif ($query->param('crypto_password') eq '') {
# leeres Passwort # leeres Passwort
$pagedata->setValue('Data.Warning', 'EmptyCryptoPassword'); $pagedata->setValue('Data.Warning', 'EmptyCryptoPassword');
$pagedata->setValue('Data.Action', 'form_mount'); $pagedata->setValue('Data.Action', 'show_volume');
} else { } else {
# mounten # mounten
&mount_vol($query->param('crypto_password')); &mount_vol($device, $query->param('crypto_password'));
if (!&check_mounted()) { if (!&check_mounted($device)) {
$pagedata->setValue('Data.Warning', 'MountFailed'); $pagedata->setValue('Data.Warning', 'MountFailed');
$pagedata->setValue('Data.Action', 'form_mount'); $pagedata->setValue('Data.Action', 'show_volume');
} else { } else {
$pagedata->setValue('Data.Success', 'MountDone'); #$pagedata->setValue('Data.Success', 'MountDone');
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'show_volume');
$pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30");
} }
} }
################## mount_ask ####################### ################## mount_ask #######################
@ -532,11 +581,6 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Action', 'empty'); $pagedata->setValue('Data.Action', 'empty');
$pagedata->setValue('Data.Redirect.Action', 'form_config'); $pagedata->setValue('Data.Redirect.Action', 'form_config');
$pagedata->setValue('Data.Redirect.Delay', "30"); $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 { } else {
$pagedata->setValue('Data.Action', 'form_mount'); $pagedata->setValue('Data.Action', 'form_mount');
} }
@ -545,11 +589,6 @@ if ( ! &check_ssl()) {
if ( ! &check_config()) { if ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized'); $pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init'); $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 { } else {
$pagedata->setValue('Data.Action', 'form_umount'); $pagedata->setValue('Data.Action', 'form_umount');
} }
@ -566,7 +605,7 @@ if ( ! &check_ssl()) {
} }
#################### init_do ######################## #################### init_do ########################
} elsif ($action eq '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')) { if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword'); $pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_init'); $pagedata->setValue('Data.Action', 'form_init');
@ -587,13 +626,11 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Warning', 'InitNotConfirmed'); $pagedata->setValue('Data.Warning', 'InitNotConfirmed');
$pagedata->setValue('Data.Action', 'form_init'); $pagedata->setValue('Data.Action', 'form_init');
} else { } else {
# do init if (&volume_init($query->param('crypto_password'),$query->param('admin_password'))) {
&box_init($query->param('crypto_password'),$query->param('admin_password')); #$pagedata->setValue('Data.Success', 'InitRunning');
if (!&check_init_running()) {
$pagedata->setValue('Data.Error', 'InitFailed');
} else {
$pagedata->setValue('Data.Success', 'InitRunning');
$pagedata->setValue('Data.Action', 'form_config'); $pagedata->setValue('Data.Action', 'form_config');
} else {
$pagedata->setValue('Data.Error', 'InitFailed');
} }
} }
#################### config_ask ###################### #################### config_ask ######################
@ -606,34 +643,33 @@ if ( ! &check_ssl()) {
} }
#################### config_do ####################### #################### config_do #######################
} elsif ($action eq '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()) { if ( ! &check_config()) {
$pagedata->setValue('Data.Warning', 'NotInitialized'); $pagedata->setValue('Data.Warning', 'NotInitialized');
$pagedata->setValue('Data.Action', 'form_init'); $pagedata->setValue('Data.Action', 'form_init');
} else { } 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')) { if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword'); $pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_config'); $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.Warning', 'InvalidLanguage');
$pagedata->setValue('Data.Action', 'form_config'); $pagedata->setValue('Data.Action', 'form_config');
} elsif ( ! &validate_ip($query->param('ip'))) { } elsif ( ! &validate_timeout($query_timeout)) {
$pagedata->setValue('Data.Warning', 'InvalidIP');
$pagedata->setValue('Data.Action', 'form_config');
} elsif ( ! &validate_timeout($query->param('timeout'))) {
$pagedata->setValue('Data.Warning', 'InvalidTimeOut'); $pagedata->setValue('Data.Warning', 'InvalidTimeOut');
$pagedata->setValue('Data.Action', 'form_config'); $pagedata->setValue('Data.Action', 'form_config');
} else { } else {
system($CB_SCRIPT, "set_config", "language", $query->param('language')); system($CB_SCRIPT, "set_config", "language", $query_language);
&load_selected_language($pagedata); &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 # 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 # set the new value
system($CB_SCRIPT, "set_config", "ip", $query->param('ip')); system($CB_SCRIPT, "set_config", "ip", $query->param('ip'));
# reconfigure the network interface
system($CB_SCRIPT, "update_ip_address");
# redirect to the new address # redirect to the new address
$pagedata->setValue('Data.Redirect.URL', "https://" . $query->param('ip') . $ENV{'SCRIPT_NAME'}); $pagedata->setValue('Data.Redirect.URL', "https://" . $query->param('ip') . $ENV{'SCRIPT_NAME'});
$pagedata->setValue('Data.Redirect.Delay', "5"); $pagedata->setValue('Data.Redirect.Delay', "5");
@ -641,20 +677,106 @@ if ( ! &check_ssl()) {
$pagedata->setValue('Data.Warning', 'IPAddressChanged'); $pagedata->setValue('Data.Warning', 'IPAddressChanged');
} }
# check for success # 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'); $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'); $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'); $pagedata->setValue('Data.Warning', 'ConfigLanguageFailed');
} else { } else {
$pagedata->setValue('Data.Success', 'ConfigSaved'); #$pagedata->setValue('Data.Success', 'ConfigSaved');
} }
$pagedata->setValue('Data.Action', 'show_status'); $pagedata->setValue('Data.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Action', 'show_status'); $pagedata->setValue('Data.Redirect.Action', 'show_status');
$pagedata->setValue('Data.Redirect.Delay', "30"); $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 ######################### #################### status #########################
} elsif ($action eq 'show_status') { } elsif ($action eq 'show_status') {
if ( ! &check_config()) { if ( ! &check_config()) {
@ -674,7 +796,7 @@ if ( ! &check_ssl()) {
# if we find an existing config partition, then check the adminpw # if we find an existing config partition, then check the adminpw
} elsif ($action eq 'do_purge') { } elsif ($action eq 'do_purge') {
if ( &check_config()) { 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')) { if ($current_admin_pw ne '' && $current_admin_pw ne $query->param('current_admin_password')) {
$pagedata->setValue('Data.Warning', 'WrongAdminPassword'); $pagedata->setValue('Data.Warning', 'WrongAdminPassword');
$pagedata->setValue('Data.Action', 'form_config'); $pagedata->setValue('Data.Action', 'form_config');
@ -710,20 +832,17 @@ if ( ! &check_ssl()) {
# check state of the cryptobox # check state of the cryptobox
$pagedata->setValue('Data.Status.Config', &check_config() ? 1 : 0); $pagedata->setValue('Data.Status.Config', &check_config() ? 1 : 0);
$pagedata->setValue('Data.Status.InitRunning', &check_init_running() ? 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 ''); $pagedata->setValue('Data.Config.AdminPasswordIsSet', 1) if ($output ne '');
$output = join ("<br/>", &exec_cb_script("diskinfo")); $output = join ("<br/>", &exec_cb_script("diskinfo"));
$pagedata->setValue('Data.PartitionInfo',"$output"); $pagedata->setValue('Data.PartitionInfo',"$output");
# preset config settings for clearsilver # preset config settings for clearsilver
$pagedata->setValue('Data.Config.IP', &exec_cb_script("get_config","ip")); $pagedata->setValue('Data.Config.IP', &get_cbox_config("ip"));
$pagedata->setValue('Data.Config.TimeOut', &exec_cb_script("get_config","timeout")); $pagedata->setValue('Data.Config.TimeOut', &get_cbox_config("timeout"));
$pagedata->setValue('Data.Config.Language', &exec_cb_script("get_config","language")); $pagedata->setValue('Data.Config.Language', &get_cbox_config("language"));
# read log and add html linebreaks # read log and add html linebreaks
$output = ''; $output = '';
@ -742,6 +861,46 @@ my $querystring = $ENV{'QUERY_STRING'};
$querystring =~ s/weblang=\w\w&?//; $querystring =~ s/weblang=\w\w&?//;
$pagedata->setValue('Data.QueryString', "$querystring") if ($querystring ne ''); $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(); &render();
close STDOUT; close STDOUT;

View File

@ -40,10 +40,7 @@ case "$1" in
;; ;;
stop ) stop )
# unmount all active containers # unmount all active containers
ls ~$CRYPTOBOX_USER/mnt/ | while read mnt_dir "$LIB_DIR/cbox-manage.sh" umount_all
do grep -q " ~$CRYPTOBOX_USER/mnt/$mnt_dir " /proc/mounts || continue
"$LIB_DIR/cbox-manage.sh" crypto-down "$mnt_dir"
done
;; ;;
restart ) restart )
"$0" stop "$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 "=" # so there should be no space around the "="
LANGUAGE=en LANGUAGE=en
NET_IFACE=eth0
CRYPTOBOX_USER=cryptobox CRYPTOBOX_USER=cryptobox
SCAN_DEVICES="sda" SCAN_DEVICES="sd loop"
#SCAN_DEVICES="hda hdb hdc hdd hde hdf hdg scd sg sda sdb sdc sdd"
# set this to "1" to create a dedicated configuration partition (very small)
# this should only be necessary, if your root filesystem is read-only (as for a live-cd)
USE_SEPERATE_CONFIG_PARTITION=0
# web interface # web interface
HTML_TEMPLATE_DIR=/usr/share/cryptobox/templates HTML_TEMPLATE_DIR=/usr/share/cryptobox/templates
@ -22,7 +16,6 @@ CONFIG_DEFAULTS_DIR=/usr/share/cryptobox/defaults
# some files # some files
LOG_FILE=/var/log/cryptobox.log LOG_FILE=/var/log/cryptobox.log
CONFIG_MARKER=cryptobox.marker
# crypto settings # crypto settings
# TODO: for now, the usual default cipher does not work on ARM, so we enable it during development # 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 # distribution specific configuration
# examples can be found in /usr/local/share/cryptobox/distributions # examples can be found in /usr/local/share/cryptobox/distributions
DISTRIBUTION_CONF=/etc/cryptobox/distribution.conf 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 IFCONFIG=/sbin/ifconfig
PMOUNT=/bin/pmount PMOUNT=/bin/pmount
PUMOUNT=/bin/pumount 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 Package: cryptobox
Architecture: any 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 Recommends: perl-clearsilver
Suggests: stunnel, cron, iptables, samba Suggests: cron, samba
Description: Web interface for an encrypting fileserver Description: Web interface for an encrypting fileserver
This bundle of scripts and cgis allow you to manage an encrypted harddisk This bundle of scripts and cgis allow you to manage an encrypted harddisk
via a web interface. The data is platform independently available via a web interface. The data is platform independently available

4
debian/prerm vendored
View File

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

View File

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

View File

@ -12,8 +12,9 @@ Lang {
Umount = Deactivation of encrypted data Umount = Deactivation of encrypted data
Config = CryptoBox configuration Config = CryptoBox configuration
Log = CryptoBox logfiles Log = CryptoBox logfiles
ShutDown = System System = System
Status = Status Status = Status
Volume = Properties of
} }
@ -24,10 +25,10 @@ Lang {
EnterCurrentAdminPassword = Enter the current administration password: EnterCurrentAdminPassword = Enter the current administration password:
EnterNewAdminPassword = Enter the new administration password: EnterNewAdminPassword = Enter the new administration password:
EnterSameAdminPassword = Repeat 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: ConfirmInitHint = To confirm that you know what you are doing, please enter exactly the following sequence:
ConfirmInit = Yes, delete all data! 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: IPAddress = Network address (IP) of the CryptoBox:
TimeOut = Timeout for deactivation of the encrypted filesystem (in minutes): TimeOut = Timeout for deactivation of the encrypted filesystem (in minutes):
EmptyLog = The logfiles of the CryptoBox are empty. EmptyLog = The logfiles of the CryptoBox are empty.
@ -40,11 +41,17 @@ Lang {
Configuration = Configuration Configuration = Configuration
CryptoIsActive = The encrypted data is accessible. CryptoIsActive = The encrypted data is accessible.
CryptoIsDown = The encrypted data is protected from any access. 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 { Button {
DoInit = Initialize CryptoBox DoInit = Initialization
SaveConfig = Save configuration SaveConfig = Save configuration
Update = Refresh Update = Refresh
Mount = Activate encrypted filesystem Mount = Activate encrypted filesystem
@ -52,9 +59,12 @@ Lang {
Config = Configuration Config = Configuration
PowerOff = Shutdown PowerOff = Shutdown
ReBoot = Reboot ReBoot = Reboot
Protocol = Logfiles Protocol = Show logfiles
Documentation = Manual Documentation = Help
Status = Status Status = Status
System = System
ContainerNameSet = Change name
InitContainer = Initialize container
} }
@ -91,7 +101,7 @@ Lang {
UmountFailed { UmountFailed {
Title = Deactivation failed 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 { NotInitialized {
@ -153,6 +163,36 @@ Lang {
Title = Change of network address Title = Change of network address
Text = The network address has been changed. In a few seconds you will get redirected to the new 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 { NoHardDisk {
Title = No hard drive Title = No hard disk
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. 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) ?> <?cs call:error(Data.Error) ?>

View File

@ -1,18 +1,18 @@
<!-- $Id$ --> <?cs # $Id$ ?>
<?cs if:Data.Redirect ?> <?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 ?> <?cs /if ?>
</div><!-- end of 'words' --> </div><!-- end of 'words' -->
<div id="footer"> <div id="footer">
<!-- Development or not --> <?cs # Development or not ?>
<?cs if:(Data.Status.DevelopmentMode == 1) ?> <?cs if:(Data.Status.DevelopmentMode == 1) ?>
<div id="development">!Development Mode!</div> <div id="development">!Development Mode!</div>
<?cs /if ?> <?cs /if ?>
<!-- Version --> <?cs # Version ?>
v0.3&nbsp;&nbsp; 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> <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> </div>
@ -29,7 +29,8 @@ Data.Status.IP=<?cs var:Data.Status.IP ?>
Data.Status.Mounted=<?cs var:Data.Status.Mounted ?> Data.Status.Mounted=<?cs var:Data.Status.Mounted ?>
CBOX-STATUS-end --> CBOX-STATUS-end -->
<!-- $Revision$ --> <?cs # $Revision$ ?>
</body> </body>
</html> </html>

View File

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

View File

@ -1,4 +1,4 @@
<!-- $Id$ --> <?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Init ?></h1> <h1><?cs var:Lang.Title.Init ?></h1>
@ -6,19 +6,7 @@
<?cs call:print_form_header() ?> <?cs call:print_form_header() ?>
<p class="note"><?cs var:Lang.Text.InitWarning ?></p> <p class="note"><?cs var:Lang.Text.InitWarning ?></p>
<?cs if:Data.Config.AdminPasswordIsSet ?> <p><label for="confirm"><?cs var:html_escape(Lang.Text.ConfirmInitHint) ?><br/>
<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/>
<span class="note" id="confirmtext"><?cs var:Lang.Text.ConfirmInit ?></span></label><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="text" id="confirm" name="confirm" size="30" maxlength="50" /></p>
<input type="hidden" name="action" value="init_do" /> <input type="hidden" name="action" value="init_do" />
@ -28,7 +16,11 @@
<hr/> <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"> <div class="partition_info">
<h2><?cs var:Lang.Text.PartitionInfo ?></h2> <h2><?cs var:Lang.Text.PartitionInfo ?></h2>
<p><?cs var:Data.PartitionInfo ?></p> <p><?cs var:Data.PartitionInfo ?></p>
</div> </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 ?>
<div align="center"> <?cs call:warning('NoDiskAvailableForMount') ?>
<?cs call:print_form_header() ?>
<p><label for="crypto_passwort"><?cs var:Lang.Text.EnterCurrentCryptoPassword ?></label> <?cs else ?>
<input type="password" id="crypto_password" name="crypto_password" size="20" tabindex="0" maxlength="40" /></p>
<input type="hidden" name="action" value="mount_do" /> <h1><?cs var:Lang.Title.Mount ?></h1>
<button type="submit" tabindex="100"><?cs var:Lang.Button.Mount ?></button>
<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" maxlength="40" /></p>
<input type="hidden" name="action" value="mount_do" />
<button type="submit"><?cs var:Lang.Button.Mount ?></button>
</form>
</div>
<?cs /if ?>
</form>
</div>

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 call:print_form_header() ?>
<input type="hidden" name="action" value="umount_do" /> <?cs else ?>
<button type="submit"><?cs var:Lang.Button.Umount ?></button>
<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>
<?cs /if ?>
</form>
</div>

View File

@ -1,4 +1,4 @@
<!-- $Id$ --> <?cs # $Id$ ?>
<?xml version="1.0" encoding="utf-8"?> <?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"> <!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="shortcut icon" href="/favicon.ico" />
<link rel="stylesheet" media="screen" href="<?cs var:Settings.Stylesheet ?>" type="text/css" /> <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 <?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> </head>
<body> <body>
<?cs if:subcount(Data.Disks.available) > 0 ?>
<div id="volumes">
<?cs include:Settings.TemplateDir + '/show_volumes.cs' ?>
</div>
<?cs /if ?>
<div id="lang"> <div id="lang">
<?cs each:item = Data.Languages ?> <?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 if:Data.QueryString ?>&<?cs var:Data.QueryString ?><?cs /if ?>"><?cs
var:item ?></a><br/> var:item ?></a><br/>
<?cs /each ?> <?cs /each ?>
</div> </div>
<div id="main"> <div id="main">
<?cs if:(Data.Status.Mounted == 1) ?> <?cs if:subcount(Data.Disks.active) > 0 ?>
<div id="head_red"> <div id="head_red">
<?cs else ?> <?cs else ?>
<div id="head_green"> <div id="head_green">
@ -37,7 +43,7 @@
<div id="content"> <div id="content">
<div id="menu"> <div id="menu">
<?cs if:Data.Redirect.URL ?> <?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; &nbsp;
<?cs else ?> <?cs else ?>
<?cs include:Settings.TemplateDir + '/nav.cs' ?> <?cs include:Settings.TemplateDir + '/nav.cs' ?>
@ -45,3 +51,4 @@
</div> </div>
<div id="words"> <div id="words">

View File

@ -1,42 +1,45 @@
<!-- $Id$ --> <?cs # $Id$ ?><?cs
<?cs def:warning(warnname) ?><?cs def:warning(warnname)
each:item = Lang.WarningMessage ?><?cs ?><div class="warning"><?cs
if:(name(item) == warnname) if:?Lang.WarningMessage[warnname].Title
?><div class="warning"> ?>
<h1><?cs var:item.Title ?></h1> <h1><?cs var:Lang.WarningMessage[warnname].Title ?></h1>
<p><?cs var:item.Text ?></p></div> <p><?cs var:Lang.WarningMessage[warnname].Text ?></p>
<?cs <?cs else ?>
/if ?><?cs <h1>unknown warning message</h1>
/each ?><?cs <p>could not find warning message: '<?cs var:warnname ?>'</p>
/def ?> <?cs /if ?></div><?cs
/def ?><?cs
<?cs def:error(errname) ?><?cs def:error(errname)
each:item = Lang.ErrorMessage ?><?cs ?><div class="error"><?cs
if:(name(item) == errname) if:?Lang.ErrorMessage[errname].Title
?><div class="error"> ?>
<h1><?cs var:item.Title ?></h1> <h1><?cs var:Lang.ErrorMessage[errname].Title ?></h1>
<p><?cs var:item.Text ?></p></div> <p><?cs var:Lang.ErrorMessage[errname].Text ?></p>
<?cs <?cs else ?>
/if ?><?cs <h1>unknown error message</h1>
/each ?><?cs <p>could not find error message: '<?cs var:errname ?>'</p>
/def ?> <?cs /if ?></div><?cs
/def ?><?cs
<?cs def:success(succname) ?><?cs def:success(succname)
each:item = Lang.SuccessMessage ?><?cs ?><div class="success"><?cs
if:(name(item) == succname) if:?Lang.SuccessMessage[succname].Title
?><div class="success"> ?>
<h1><?cs var:item.Title ?></h1> <h1><?cs var:Lang.SuccessMessage[succname].Title ?></h1>
<p><?cs var:item.Text ?></p></div> <p><?cs var:Lang.SuccessMessage[succname].Text ?></p>
<?cs <?cs else ?>
/if ?><?cs <h1>unknown success message</h1>
/each ?><?cs <p>could not find success message: '<?cs var:succname ?>'</p>
/def ?> <?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 # the output looks quite ugly and is not very helpful as there are
# only a few values # only a few values
?><!-- data tree ?><!-- data tree
@ -44,50 +47,36 @@
name:item ?>: <?cs var:item ?><?cs name:item ?>: <?cs var:item ?><?cs
each:subitem = item ?> / <?cs name:subitem ?>=<?cs var:subitem ?><?cs /each ?> each:subitem = item ?> / <?cs name:subitem ?>=<?cs var:subitem ?><?cs /each ?>
<?cs /each ?> <?cs /each ?>
--> --><?cs
<?cs /def ?> /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 # def:print_form_header() ?><?cs #
# construct the URL of the script out of the ScriptName, Data.PostData # the header of a form - including Setting.LinkAttrs
# (except for the value mentioned in 'exclude') and a possible ?><form action="<?cs call:link("","","","","","") ?>" method="post" enctype="application/x-www-from-urlencoded" accept-charset="utf-8"><?cs
# 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 ?> /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 + '/macros.cs' ?>
<?cs include:Settings.TemplateDir + '/header.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 if:Data.Error ?>
<?cs include:Settings.TemplateDir + '/error.cs' ?> <?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.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> <!-- TODO: remove the following lines, as soon as we completely switched to the volume-based user interface
<?cs else ?> <?cs if:subcount(Data.Disks.passive) > 0 ?>
<a href="<?cs call:getSelfURL('action=mount_ask','action') ?>" title="<?cs var:Lang.Text.DoMount ?>"><?cs var:Lang.Button.Mount ?></a> <a href="<?cs call:link('action','mount_ask','','','','') ?>" title="<?cs var:Lang.Text.DoMount ?>"><?cs var:Lang.Button.Mount ?></a><?cs /if ?>
<?cs /if ?> <?cs if:subcount(Data.Disks.active) > 0 ?>
<a href="<?cs call:getSelfURL('action=show_status','action') ?>" title="<?cs var:Lang.Button.Status ?>"><?cs var:Lang.Button.Status ?></a> <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 ?> <?cs /if ?>
<!-- already initialized (or at least in progress)? --> <?cs # manual ?>
<?cs if:(Data.Status.Config == 1) ?> <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=config_ask','action') ?>" title="<?cs var:Lang.Text.Configuration ?>"><?cs var:Lang.Button.Config ?></a>
<?cs /if ?>
<a href="<?cs call:getSelfURL('action=init_ask','action') ?>" title="<?cs var:Lang.Button.DoInit ?>"><?cs var:Lang.Button.DoInit ?></a> <?cs # system ?>
<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:link('action','system_ask','','','','') ?>" title="<?cs var:Lang.Button.System ?>"><?cs var:Lang.Button.System ?></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>

View File

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

View File

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

View File

@ -1,5 +1,28 @@
<!-- $Id$ --> <?cs # $Id$ ?>
<h1><?cs var:Lang.Title.Status ?></h1> <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-size: 0.8em;
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
margin: 2px 10px 2px 10px;
} }
button:hover { button:hover {
@ -292,6 +293,38 @@ button:hover {
text-align: center; 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 -=-=-=------------- */ /* ------------=-=-=- language selection -=-=-=------------- */
#lang { #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