#!/bin/sh

set -e

check_cert () {
    echo "Checking certificate on $(hostname -f):443"
    if ! openssl s_client -connect $(hostname -f):443 -CAfile /etc/ssl/certs/ca-certificates.crt < /dev/null > /tmp/openssl.out 2>&1 \
            || ! grep 'Verify return code: 0 (ok)' /tmp/openssl.out > /dev/null; then
        echo "Cert check failed"
        cat /tmp/openssl.out
        return 1
    fi
    echo "Cert check suceeded"
    return 0
}

appliance_type=$(cat /var/lib/lastline/product_codename)

new_cert_sha256='0bfb2dd67bf34c898fef8b9857030c4e5d0d6aae2665ba0ddd9339329b2b7825'
new_root_cert_sha256='1bee5bc7f7cf9d968dbf788c21bd625f07c8581eea0bdc2ce2a43560c9ed8bc6'
new_chain_sha256='bb9df52b6ec3430f7b262c03dcb1ba42c70d1c910d2fccd2a6d18ab8d7952b30'
cert_file='/etc/anonvpn/lastline_anonvpn.crt'
puppet_cert_file='/usr/share/appliance-config/modules/anonvpn/templates/lastline-ca-openvpn-02.crt.erb'
puppet_root_cert_file='/usr/share/appliance-config/modules/anonvpn/templates/lastline-ca.crt.erb'
root_cert_file='/usr/local/share/ca-certificates/lastline-root-ca-2.crt'

new_key_sha256='369cb700317b1e5b0374ea2f45ea7d2dd4cdc96c3166732a6b9371a5d8388da8'
key_file='/var/lib/lastline/9AFD8DA3.asc'
puppet_key_file='/usr/share/appliance-config/modules/appliance_update/files/9AFD8DA3.asc'

cert_needs_update=0
puppet_cert_needs_update=0
root_ca_missing=0

key_needs_update=0
puppet_key_needs_update=0

if ! [ -f $root_cert_file ]; then
    echo "*** Root cert ${root_cert_file} is missing"
    root_ca_missing=1
else
    echo "Root cert ${root_cert_file} is present"
fi

case "${appliance_type}" in
manager | analyst | pinbox | sensor)
    ;;
*)
    echo "*** Unsupported appliance type: ${appliance_type}"
    exit 1
    ;;
esac

if [ $appliance_type != "sensor" ]; then
    current_cert_sha256=$(sha256sum $cert_file | cut -d ' ' -f 1)
    current_puppet_cert_sha256=$(sha256sum $puppet_cert_file | cut -d ' ' -f 1)
    current_puppet_root_cert_sha256=$(sha256sum $puppet_root_cert_file | cut -d ' ' -f 1)

    if [ "${current_cert_sha256}" = "${new_chain_sha256}" ]; then
        echo "cert is up-to-date in ${cert_file}"
    else
        cert_needs_update=1
        echo "*** Old/unknown cert found in ${cert_file}"
    fi
    if [ "${current_puppet_cert_sha256}" = "${new_cert_sha256}" ]; then
        echo "cert is up-to-date in ${puppet_cert_file}"
    else
        puppet_cert_needs_update=1
        echo "*** Old/unknown cert found in ${puppet_cert_file}"
    fi
    if [ "${current_puppet_root_cert_sha256}" = "${new_root_cert_sha256}" ]; then
        echo "cert is up-to-date in ${puppet_root_cert_file}"
    else
        puppet_cert_needs_update=1
        echo "*** Old/unknown cert found in ${puppet_root_cert_file}"
    fi

    http_cert_needs_update=''
    for user_cert_file in /etc/ssl/certs/user.*.pem /etc/puppet/files/ssl-cert/user.*.pem; do
        if ! [ -f "$user_cert_file" ]; then
            echo "*** Cannot find /etc/ssl/certs/user.*.pem"
            exit 1
        fi

        if grep 'Serial Number: 15955383886438364209 ' $user_cert_file > /dev/null; then
            echo "*** Found old CA_signing04 in $user_cert_file"
            http_cert_needs_update="${http_cert_needs_update} $user_cert_file"
        else
            echo "Lastline-signed http certificate not in use for $user_cert_file"
        fi
    done
fi

current_key_sha256=$(sha256sum $key_file | cut -d ' ' -f 1)
current_puppet_key_sha256=$(sha256sum $puppet_key_file | cut -d ' ' -f 1)

if [ "${current_key_sha256}" = "${new_key_sha256}" ]; then
    echo "Key is up-to-date in ${key_file}"
else
    echo "*** Old/unknown key found in ${key_file}"
    key_needs_update=1
fi
if [ "${current_puppet_key_sha256}" = "${new_key_sha256}" ]; then
    echo "Key is up-to-date in ${puppet_key_file}"
else
    echo "*** Old/unknown key found in ${puppet_key_file}"
    puppet_key_needs_update=1
fi

if [ \
        $cert_needs_update = 0 -a \
        $puppet_cert_needs_update = 0 -a \
        "$http_cert_needs_update" = '' -a \
        $root_ca_missing = 0 -a \
        $key_needs_update = 0 -a \
        $puppet_key_needs_update = 0 \
    ]; then
    check_cert
    exit $?
fi

if [ "$1" != "update" ]; then
    echo "Pass 'update' as first argument to this script in order to perform an update"
    exit 1
fi

if [ $root_ca_missing = 1 ]; then
    echo "Creating ${root_cert_file}"
    cat > $root_cert_file <<EOF
-----BEGIN CERTIFICATE-----
[payload removed: 1908 characters in 30 lines]
-----END CERTIFICATE-----
EOF
    echo "Updating ca-certificates"
    update-ca-certificates
fi

if [ $puppet_cert_needs_update = 1 ]; then
    echo "Updating cert in ${puppet_cert_file}"
    cat > ${puppet_cert_file} <<EOF
-----BEGIN CERTIFICATE-----
[payload removed: 1352 characters in 22 lines]
-----END CERTIFICATE-----
EOF
    echo "Updating cert in ${puppet_root_cert_file}"
    cp ${root_cert_file} ${puppet_root_cert_file}
fi

openvpn_crt1='/usr/share/appliance-config/modules/anonvpn/templates/openvpn-crt-anonvpn.lastline.com.erb'
openvpn_crt2='/usr/share/appliance-config/templates/analyst/vpn/openvpn-crt-anonvpn.lastline.com.erb'

if [ $cert_needs_update = 1 ]; then
    echo "Updating cert in ${cert_file}"
    if [ -e $openvpn_crt1 ]; then
        openpvn_crt_file=$openvpn_crt1
    elif [ -e $openvpn_crt2 ]; then
        openpvn_crt_file=$openvpn_crt2
    else
        echo "*** Cannot find openvpn-crt-anonvpn.lastline.com.erb"
        exit 1
    fi
    cat \
        $openpvn_crt_file \
        $puppet_cert_file \
        $puppet_root_cert_file \
        > $cert_file
    if grep 'anonvpn::mode.*lastline' /etc/appliance-config/local-settings.yaml > /dev/null && \
        [ "$(cat /var/lib/lastline/appliance_state)" = 'active' ]; then
        echo "Restarting anonvpn client"
        ifdown llanonvpn0
        ifup llanonvpn0
    else
        echo "Appliance not using anonvpn, or standby manager, not restarting the client"
    fi
fi

if [ "$http_cert_needs_update" != '' ]; then
    for user_cert_file in $http_cert_needs_update; do
        user_cert_file_backup="${user_cert_file}.$(date +%s)"
        echo "Saving ${user_cert_file} to ${user_cert_file_backup}"
        cp $user_cert_file $user_cert_file_backup
        sed '/-----END CERTIFICATE-----/q' $user_cert_file_backup > $user_cert_file
        cat >> $user_cert_file <<EOF
-----BEGIN CERTIFICATE-----
[payload removed: 1516 characters in 24 lines]
-----END CERTIFICATE-----
EOF
    done
    echo "Reloading nginx configuration"
    nginx -s reload
    echo "Updating ca-certificates"
    update-ca-certificates
    sleep 3
fi

if [ $puppet_key_needs_update = 1 ]; then
    echo "Updating key in ${puppet_key_file}"
    cat > ${puppet_key_file} <<EOF
-----BEGIN PGP PUBLIC KEY BLOCK-----

[payload removed: 1656 characters in 26 lines]
=OCjD
-----END PGP PUBLIC KEY BLOCK-----
EOF
fi

if [ $key_needs_update = 1 ]; then
    echo "Updating key in ${key_file}"
    cp $puppet_key_file $key_file
    echo "Scheduling restart of appliance-update daemon"
    touch /tmp/appliance_update.restart
fi

if [ $appliance_type != 'sensor' ]; then
    check_cert
fi
exit $?
