#!/usr/bin/bash if [ $(/usr/bin/id -u) != 0 ]; then echo "only root can do that"; exit 2; fi # # Copyright 2015-2017 Senderek Web Security, Ireland. All rights reserved. # # # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # # Author: Ralf Senderek # # license: GNU General Public License version 3 or higher # description: Activates the cryptobone daemon during the boot process # processname: cryptoboned # config: none # date: 8 November 2016 # ### BEGIN INIT INFO # Provides: cryptoboned # Required-Start: $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Activates the cryptobone daemon during the boot process ### END INIT INFO # chkconfig: 2345 90 60 if [ -f /lib/lsb/init-functions ] then . /lib/lsb/init-functions fi KEYS="/usr/lib/cryptobone/keys" REAL="none" SOCK="/usr/lib/cryptobone/secrets.sock" ########################################################################## log_debug() { # make sure, non-sensitive information is stored for debugging purposes # if a file /root/.cryptobone.debug exists with permissions 0600 for the # root user DEB=/root/.cryptobone.debug if /bin/ls $DEB 2> /dev/null > /dev/null ; then PERM=$(/bin/ls -l $DEB | cut -c2-10) TIME=$(date '+%T %N') if [[ $PERM = "rw-------" ]] ; then if [[ x$1 = xclean ]] ; then echo -n > $DEB fi echo "$TIME $1 $2" >> $DEB fi fi } ########################################################################## start() { if ! df | grep /usr/lib/cryptobone/keys 2> /dev/null > /dev/null then # we're booting # the package rng-tools should be installed and the rngd enabled by default # starting rngd here will slow down the shutdown / stop job for cryptoboned #/usr/sbin/rngd -b -r /dev/hwrnd 2> /dev/null # load the SELinux policy for the daemon log_debug "clean" if selinuxenabled ; then log_debug "start selinux module" semodule -i /usr/lib/cryptobone/selinux/cryptobone.pp semodule -e cryptobone log_debug "end selinux module" fi SWITCH=/usr/lib/cryptobone/bootswitch if [ ! -f $SWITCH ] then touch $SWITCH fi chattr -i $SWITCH chmod 600 $SWITCH chmod 700 $KEYS if [ ! -L /usr/lib/cryptobone/masterkey ] then # initialize database and create a master key and local key /usr/lib/cryptobone/createmasterkey # now there is $KEYS/random and both file systems (boot.fs and permanent.fs) fi /bin/rm /usr/lib/cryptobone/UPLOADED 2> /dev/null # record evidence that we're really booting typeset -i BOOTTIME=$(cat /proc/stat | grep btime | cut -f2 -d" ") typeset -i NOW=$(date +%s) typeset -i DIFF=$NOW-$BOOTTIME echo $DIFF > $SWITCH log_debug "booting" DIR=$(echo -n $(cat $KEYS/random) $(stat -c "directory %i" $KEYS) | sha256sum | cut -c-64) FILE=$(echo -n $DIR $(stat -c "file %i" $KEYS/random) | sha256sum | cut -c-64) # establish the boot file system L=$(losetup -f) losetup $L $KEYS/boot.fs cat $KEYS/$DIR/$FILE | cryptsetup create cryptobone $L if mount /dev/mapper/cryptobone $KEYS then # start the daemon unless there is a non-empty database if [ ! -s /usr/lib/cryptobone/database ] ; then /bin/rm /usr/lib/cryptobone/database log_debug "performing database initialisation" systemctl start cryptobone-dbinit /bin/sleep 1 typeset -i x=0 while [ $x -lt 8 ] do if [ ! -s /usr/lib/cryptobone/database ] ; then log_debug "restarting database initialisation" systemctl stop cryptobone-dbinit /bin/rm /usr/lib/cryptobone/database systemctl start cryptobone-dbinit /bin/sleep 1 x=$x+1 else x=10 fi done fi rm -f /usr/lib/cryptobone/ssh.sock rm -f /usr/lib/cryptobone/secrets.sock log_debug "starting daemon ... " /usr/lib/cryptobone/cryptoboned log_debug "daemon started" ssh-agent -s -a /usr/lib/cryptobone/ssh.sock export SSH_AUTH_SOCK=/usr/lib/cryptobone/ssh.sock 2>/dev/null > /dev/null OVERWRITE=$(echo "get-element EXTERN.OVERWRITE" | socat - UNIX-connect:$SOCK 2> /dev/null) if [ x$OVERWRITE = "xyes" ] then rm -f $KEYS/real.key $KEYS/cbb fi if [ ! -r $KEYS/real.key ] then # check if external keys are stored in the encrypted database REALKEY=$(echo "get-element EXTERN.real.key" | socat - UNIX-connect:$SOCK 2> /dev/null) if [ x$REALKEY != "x" ] then echo $REALKEY > $KEYS/real.key chmod 600 $KEYS/real.key log_debug "overwriting master key" REALKEY="000000000000000000000000000000000000000000" unset REALKEY fi fi if [ ! -r $KEYS/cbb ] then SSHKEY=$(echo "get-element EXTERN.cbb" | socat - UNIX-connect:$SOCK 2> /dev/null) if [ x$SSHKEY != "x" ] then echo "$SSHKEY" | base64 -d > $KEYS/cbb chmod 600 $KEYS/cbb SSHKEY=$(/bin/dd if=/dev/zero bs=1K count=4 2>/dev/null) unset SSHKEY fi fi echo -n "replace EXTERN.OVERWRITE no" | socat - UNIX-connect:$SOCK 2> /dev/null if [ -f $KEYS/cbb ] then ssh-add $KEYS/cbb REAL=$(cat /usr/lib/cryptobone/keys/real.key) 2> /dev/null fi fi # remove the boot file system umount /dev/mapper/cryptobone cryptsetup remove cryptobone losetup -d $L # mount the permanent file system L=$(losetup -f) losetup $L $KEYS/permanent.fs mount $L $KEYS chmod 700 $KEYS echo 9999 > $SWITCH chattr +i $SWITCH log_debug "secrets become invisible" if [ ! -L /usr/lib/cryptobone/ALLINONE ] then # we're using a real Crypto Bone log_debug "Trying to contact the external device" if [ -f /usr/lib/cryptobone/cbb.config ] then chmod 600 /usr/lib/cryptobone/cbb.config . /usr/lib/cryptobone/cbb.config log_debug "reading the config file cbb.config" # wait for BONEIP to come up typeset -i count=0 while [ $count -lt 20 ] do log_debug "waiting for the external device to ping" /bin/sleep 2 count=$count+1 /bin/ping -w1 -c1 ${BONEIP} 2>/dev/null > /dev/null if [ $? -eq 0 ] then count=21 fi done /bin/ping -w1 -c1 ${BONEIP} 2>/dev/null > /dev/null if [ $? -eq 0 ] then # upload the master key to the real crypto bone log_debug "external device is reachable" echo $(/usr/lib/cryptobone/getlocalsecret) SYSTEM UPLOAD $(echo $REAL) | /usr/bin/ssh -l cryptobone ${BONEIP} /cbb/cbcontrol log_debug "master key sent" count=0 while [ $count -lt 8 ] do /bin/sleep 2 count=$count+1 /bin/ping -w1 -c1 ${BONEIP} 2>/dev/null > /dev/null RES=$(echo $(/usr/lib/cryptobone/getlocalsecret) STATUS | /usr/bin/ssh -l cryptobone ${BONEIP} /cbb/cbcontrol) if [ "${RES}x" = "activex" ] then log_debug "device becomes active" echo "EXTERNAL is active now." touch /usr/lib/cryptobone/UPLOADED count=11 RES=$(echo $(/usr/lib/cryptobone/getlocalsecret) SYSTEM RESTART | /usr/bin/ssh -l cryptobone ${BONEIP} /cbb/cbcontrol) else log_debug "device inactive [$RES]" RES=$(echo $(/usr/lib/cryptobone/getlocalsecret) SYSTEM UPLOAD $(echo $REAL) | /usr/bin/ssh -l cryptobone ${BONEIP} /cbb/cbcontrol) log_debug "uploading master key again [$RES]" fi log_debug "$count" "sending master key" echo $(/usr/lib/cryptobone/getlocalsecret) SYSTEM UPLOAD $(echo $REAL) >> /root/deb done echo "EXTERNAL finished." REAL="000000000000000000000000000000000000000000" unset REAL fi fi else echo "ALL-IN-ONE finished." fi REAL="000000000000000000000000000000000000000000" unset REAL fi } ########################################################################## stop() { if [ -d /dev/shm/RAM ] then /usr/lib/cryptobone/bin/savemessages fi killall cryptoboned } ########################################################################## case "$1" in start) start ;; stop) stop ;; restart) echo "deliberately not implemented" ;; status) echo "deliberately not implemented" ;; force-reload) echo "deliberately not implemented" ;; *) echo "Usage: /usr/lib/cryptobone/init.d/cryptoboned {start|stop}" exit 1 esac exit 0