diff --git a/doc/50-certidude b/doc/50-certidude new file mode 100644 index 0000000..7498784 --- /dev/null +++ b/doc/50-certidude @@ -0,0 +1,197 @@ +#!/bin/sh + +# To paste, press Ctrl-D to finish: cat > /etc/hotplug.d/iface/50-certidude +# To test: ACTION=ifup INTERFACE=wan sh /etc/hotplug.d/iface/50-certidude + +# TODO: renewal + +[ $ACTION == "ifup" ] || exit 0 +[ $INTERFACE == "wan" ] || exit 0 + +# TODO: iterate over all authorities + +AUTHORITY=certidude.@authority[0] +URL=$(uci get $AUTHORITY.url) +GATEWAY=$(uci get $AUTHORITY.gateway) + +COMMON_NAME=$(uci get $AUTHORITY.common_name) +if [ $? -ne 0 ]; then + COMMON_NAME=$(uci get system.@system[0].hostname) +fi + +KEY_PATH=$(uci get $AUTHORITY.key_path) +KEY_TYPE=$(uci get $AUTHORITY.key_type) +KEY_LENGTH=$(uci get $AUTHORITY.key_length) + +CERTIFICATE_PATH=$(uci get $AUTHORITY.certificate_path) +REQUEST_PATH=$(uci get $AUTHORITY.request_path) +AUTHORITY_PATH=$(uci get $AUTHORITY.authority_path) + +RED_LED=/sys/class/leds/$(uci get $AUTHORITY.red_led) +GREEN_LED=/sys/class/leds/$(uci get $AUTHORITY.green_led) + +NTP_SERVERS=$(uci get system.ntp.server) + +logger -t certidude -s "Fetching time from NTP servers: $NTP_SERVERS" +ntpd -q -n -d -p $NTP_SERVERS + +logger -t certidude -s "Time is now: $(date)" + +# If certificate file is there assume everything's set up +if [ -f $CERTIFICATE_PATH ]; then + SERIAL=$(openssl x509 -in $CERTIFICATE_PATH -noout -serial | cut -d "=" -f 2 | tr [A-F] [a-f]) + logger -t certidude -s "Certificate with serial $SERIAL already exists, attempting to bring up IPsec tunnel..." + ipsec up client-to-site + exit 0 +fi + +# Turn green off and red on +if [ -d $GREEN_LED ] && [ -d $RED_LED ]; then + echo timer > $GREEN_LED/trigger + echo 100 | tee $GREEN_LED/delay_* + echo none > $RED_LED/trigger +fi + + +######################################### +### Generate private key if necessary ### +######################################### + +if [ ! -f $KEY_PATH ]; then + KEY_TEMP=$(mktemp -u) + + logger -t certidude -s "Generating RSA key for IPsec..." + if [ -d $GREEN_LED ]; then + echo 250 | tee $GREEN_LED/delay_* + fi + + openssl gen$KEY_TYPE -out $KEY_TEMP $KEY_LENGTH + chmod 0600 $KEY_TEMP + mv $KEY_TEMP $KEY_PATH +fi + + +############################ +### Fetch CA certificate ### +############################ + +if [ ! -f $AUTHORITY_PATH ]; then + AUTHORITY_TEMP=$(mktemp -u) + + logger -t certidude -s "Fetching CA certificate from $URL/api/certificate/" + curl -f -s $URL/api/certificate/ > $AUTHORITY_TEMP + if [ $? -ne 0 ]; then + logger -t certidude -s "Failed to receive CA certificate, server responded: $(cat $AUTHORITY_TEMP)" + + if [ -d $GREEN_LED ] && [ -d $RED_LED ]; then + echo none > $GREEN_LED/trigger + echo timer > $RED_LED/trigger + echo 100 | tee $RED_LED/delay_* + fi + + exit 10 + fi + + openssl x509 -in $AUTHORITY_TEMP -noout + if [ $? -ne 0 ]; then + logger -t certidude -s "Received invalid CA certificate" + + if [ -d $GREEN_LED ] && [ -d $RED_LED ]; then + echo none > $GREEN_LED/trigger + echo timer > $RED_LED/trigger + echo 250 | tee $RED_LED/delay_* + fi + + exit 11 + fi + + mv $AUTHORITY_TEMP $AUTHORITY_PATH +fi + +logger -t certidude -s "CA certificate md5sum: $(md5sum -b $AUTHORITY_PATH)" + + +##################################### +### Generate request if necessary ### +##################################### + +if [ ! -f $REQUEST_PATH ]; then + REQUEST_TEMP=$(mktemp -u) + openssl req -new -sha256 -key $KEY_PATH -out $REQUEST_TEMP -subj "/CN=$COMMON_NAME" + mv $REQUEST_TEMP $REQUEST_PATH +fi + +logger -t certidude -s "Request md5sum is $(md5sum -b $REQUEST_PATH)" + +# Wait for certificate +if [ -d $GREEN_LED ]; then + echo 500 | tee $GREEN_LED/delay_* +fi + +CERTIFICATE_TEMP=$(mktemp -u) + +curl -f -L \ + -H "Content-Type: application/pkcs10" \ + --data-binary @$REQUEST_PATH \ + $URL/api/request/?autosign=true\&wait=yes > $CERTIFICATE_TEMP + +# TODO: Loop until we get exitcode 0 +# TODO: Use backoff time $((2\*X)) + +if [ $? -ne 0 ]; then + echo "Failed to fetch certificate" + + if [ -d $GREEN_LED ] && [ -d $RED_LED ]; then + echo none > $GREEN_LED/trigger + echo timer > $RED_LED/trigger + echo 500 | tee $RED_LED/delay_* + fi + + exit 21 +fi + +# Verify certificate +openssl verify -CAfile $AUTHORITY_PATH $CERTIFICATE_TEMP + +if [ $? -ne 0 ]; then + logger -t certidude -s "Received bogus certificate!" + + if [ -d $GREEN_LED ] && [ -d $RED_LED ]; then + echo none > $GREEN_LED/trigger + echo timer > $RED_LED/trigger + echo 1000 | tee $RED_LED/delay_* + fi + + exit 22 +fi + +logger -t certidude -s "Certificate md5sum: $(md5sum -b $CERTIFICATE_TEMP)" + + + + +################################### +### Generate /etc/ipsec.secrets ### +################################### + +SECRETS_TEMP=$(mktemp -u) + +for filename in /etc/ipsec.d/private/*.pem; do + echo ": RSA $filename" >> $SECRETS_TEMP +done + +uci commit + +mv $SECRETS_TEMP /etc/ipsec.secrets +mv $IPSEC_TEMP /etc/ipsec.conf +mv $CERTIFICATE_TEMP $CERTIFICATE_PATH + +# Enable services +/etc/init.d/ipsec enable + +# Restart services +/etc/init.d/ipsec restart + +sleep 2 + +ipsec up client-to-site