#!/bin/sh

OPENSSL="${OPENSSL:-openssl}"
OPENSSL_CONFIG="${OPENSSL_CONFIG:-openssl-config}"
SSLDIR="${SSLDIR:-$($OPENSSL_CONFIG --openssldir)}"
SSLDIR="${SSLDIR:-/var/lib/ssl}"

SSL_KEYDIR="$SSLDIR/private"
SSL_CERTDIR="$SSLDIR/certs"
SSL_CSRDIR="$SSLDIR/certs"

#certificate config template
DEFAULT_CERT="
[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no

[ req_dn ]
CN=@HOSTNAME@
O=@PRODUCT@

[ cert_type ]
nsCertType = server
"

TEMP_CERT=

ssl_exit_handler()
{
	local rc=$?
	trap - EXIT
	[ -z "$TERM_CERT" ] ||
	    rm -f "$TEMP_CERT"
	exit $rc
}

ssl_fatal()
{
    printf >&2 '%s\n' "${0##*/}: $*"
    exit 1
}

#private key

ssl_check_key()
{
    [ -n "$1" -a -f "$SSL_KEYDIR/$1.key" ]
}

ssl_make_key()
{
    ssl_check_key "$@" && return
    [ -n "$1" ] ||
	ssl_fatal 'Insufficient arguments.'

    "$OPENSSL" genrsa -out "$SSL_KEYDIR/$1.key" 1024 >/dev/null 2>&1 ||
	ssl_fatal "Unable to create private key"
}

#certificate request

ssl_make_req2()
{
    "$OPENSSL" req -new -config "$2" -key "$SSL_KEYDIR/$1.key" -out "$SSL_CSRDIR/$1.csr" ||
	ssl_fatal "Unable to create sign request"
}

ssl_check_req()
{
    [ -n "$1" -a -f "$SSL_CSRDIR/$1.csr" ]
}

ssl_make_req()
{
    ssl_check_req "$@" && return
    [ -n "$1" ] ||
	ssl_fatal 'Insufficient arguments.'

    if [ -f "$2" ]; then
	ssl_make_req2 "$1" "$2"
    else
	local HOSTNAME="$(hostname)"
        HOSTNAME="${HOSTNAME:-localhost.localdomain}"

	trap ssl_exit_handler HUP INT QUIT TERM EXIT
	TEMP_CERT="$(mktemp -t default.cnf.XXXXXX)"
	echo "$DEFAULT_CERT" |
	    sed -e "s|@HOSTNAME@|$HOSTNAME|" -e "s|@PRODUCT@|$1|" >"$TEMP_CERT"

	ssl_make_req2 "$1" "$TEMP_CERT"
	rm -f "$TEMP_CERT"
	TEMP_CERT=
    fi
}

#certificate

ssl_check_cert()
{
    [ -n "$1" -a -f "$SSL_CERTDIR/$1.cert" ]
}

ssl_make_cert()
{
    ssl_check_cert "$@" && return
    [ -n "$1" ] ||
	ssl_fatal 'Insufficient arguments.'


    "$OPENSSL" x509 -req -days 365 -in "$SSL_CSRDIR/$1.csr" -signkey "$SSL_KEYDIR/$1.key" -out "$SSL_CERTDIR/$1.cert" >/dev/null 2>&1 ||
	ssl_fatal 'Unable to create certificate'
}

ssl_action()
{
    local fun="$1"; shift
    local msg="$1"; shift

    printf $"Generating %s %s: " "$1" "$msg" 

    if "$fun" "$@"; then
	success "$1 $msg generation"
	echo
    else
	failure "$1 $msg generation"
	echo
	exit 1
    fi
}

ssl_generate()
{
    [ -n "$1" ] ||
	ssl_fatal 'Insufficient arguments.'

    ssl_check_key "$@" ||
	ssl_action ssl_make_key "SSL private key" "$@"

    ssl_check_req "$@" ||
	ssl_action ssl_make_req "SSL certificate request" "$@"

    ssl_check_cert "$@" ||
	ssl_action ssl_make_cert "SSL self-signed certificate" "$@"
}
