#!/bin/sh

set -eu

revoke=
san=

base_dir="$1"

export OPENSSL_CONFIG="$base_dir/openssl.cnf"
export OPENSSL_SAN_CONFIG="$base_dir/openssl.cnf"

while [ "${2##--}" != "$2" ]; do
    case "$2" in
        --revoke)
            revoke=1
            ;;
        --san)
            san=1
            # need an extra configuration file for that
            export OPENSSL_SAN_CONFIG="$base_dir/openssl.san.cnf"
            ;;
        *)
            echo "E: Unknown option '$2'"
            exit 1
            ;;
    esac
    shift
done

ca_name="$2"
server_name="$3"

if [ "${server_name##--}" != "$server_name" ]; then
    echo "F: Parameter mismatch"
    exit 1
fi
if [ -z "$server_name" ]; then
    echo "Usage: $(dirname "$0") <base-directory> <CA name> <server name>"
    exit 1
fi

dh_params="$base_dir/dhparams.pem"

if [ ! -f "$dh_params" ]; then
    echo 'I: Generating dh parameter file. This may take some time.'
    openssl dhparam -2 -out "$dh_params" 2048
fi

export KEY_SIZE=4096

export KEY_COUNTRY=DE
export KEY_PROVINCE=Badenia
export KEY_CITY=Littenweiler
export KEY_ORG='A ngIRCd test site'

export CA_DIR="$base_dir/$ca_name"

export SERVER_DIR="$base_dir/$server_name"

CRL_FILE="$CA_DIR/crl.pem"

if [ ! -d "$CA_DIR" ]; then
    echo 'I: Setting up CA first'

    mkdir -p "$CA_DIR"

    touch "$CA_DIR/index.txt"
    echo '01' >"$CA_DIR/serial"

    export KEY_COMMON='CA'
    export KEY_EMAIL='ca@invalid.invalid'

    openssl req \
        -batch \
        -days 10 \
        -nodes \
        -new \
        -x509 \
        -sha1 \
        -newkey rsa:4096 \
        -keyout "$CA_DIR/root-ca.key" \
        -out "$CA_DIR/root-ca.crt" \
        -config "$OPENSSL_CONFIG"
    chmod 400 "$CA_DIR/root-ca.key"

    openssl ca \
        -gencrl \
        -out "$CRL_FILE" \
        -config "$OPENSSL_CONFIG"
fi

if [ "$san" ]; then
    export KEY_COMMON="$server_name.bogus"
    export SUBJ_ALT_NAME="$server_name"
else
    export KEY_COMMON="$server_name"
fi
export KEY_EMAIL='ca@invalid.invalid'

server_csr="$CA_DIR/$server_name.csr"
server_crt="$CA_DIR/$server_name.crt"
server_key="$CA_DIR/$server_name.key"

if [ -f "$server_crt" ]; then
    echo "I: Certificate for '$server_name' already exists"
    exit 1
fi

echo 'I: Creating CSR'
openssl req \
    -batch \
    -days 10 \
    -nodes \
    -new \
    -sha1 \
    -newkey rsa:4096 \
    -keyout "$server_key" \
    -out "$server_csr" \
    -config "$OPENSSL_SAN_CONFIG"

echo 'I: Signing certificate'
openssl ca \
    -extensions v3_ca \
    -batch \
    -days 10 \
    -out "$server_crt" \
    -in "$server_csr" \
    -config "$OPENSSL_SAN_CONFIG"

if [ "$revoke" ]; then
    echo 'I: Revoking certificate'
    openssl ca \
        -revoke "$server_crt" \
        -config "$OPENSSL_CONFIG"
    openssl ca \
        -gencrl \
        -out "$CRL_FILE" \
        -config "$OPENSSL_CONFIG"
fi

exit 0
