#!/bin/bash
# info: generate self signed certificate and CSR request
# options: DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT]
#
# example: v-generate-ssl-cert example.com mail@yahoo.com USA California Monterey ACME.COM IT
#
# This function generates self signed SSL certificate and CSR request

#----------------------------------------------------------#
#                Variables & Functions                     #
#----------------------------------------------------------#

# Argument definition
domain=$1
domain=$(echo $domain | sed -e 's/\.*$//g' -e 's/^\.*//g')
domain_alias=$domain
email=$2
country=$3
state=$4
city=$5
org=$6
org_unit=$7
aliases=$8
format=${9-shell}
KEY_SIZE=4096
DAYS=365

# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf
# shellcheck source=/usr/local/hestia/func/main.sh
source $HESTIA/func/main.sh
# load config file
source_conf "$HESTIA/conf/hestia.conf"

# Json function
json_list_ssl() {
	i='1' # iterator
	echo '{'
	echo -e "\t\"$domain\": {"
	echo "        \"CRT\": \"$crt\","
	echo "        \"KEY\": \"$key\","
	echo "        \"CSR\": \"$csr\","
	echo "        \"DIR\": \"$workdir\""
	echo -e "\t}\n}"
}

# Shell function
shell_list_ssl() {
	if [ -n "$crt" ]; then
		echo -e "$crt"
	fi
	if [ -n "$key" ]; then
		echo -e "\n$key"
	fi
	if [ -n "$csr" ]; then
		echo -e "\n$csr"
	fi
	echo -e "\nDirectory: $workdir"
}

# Additional argument formatting
format_domain_idn
if [[ "$email" = *[![:ascii:]]* ]]; then
	email=$(idn2 --quiet $email)
fi

#----------------------------------------------------------#
#                    Verifications                         #
#----------------------------------------------------------#

args_usage='DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT]'
check_args '7' "$#" "$args_usage"
is_format_valid 'domain' 'aliases' 'format' 'email'
is_common_format_valid $country "country"
is_common_format_valid $state "state"
is_common_format_valid $org "org"
is_common_format_valid $unit "unit"

if [ ! -f '/etc/redhat-release' ]; then
	release="$(lsb_release -s -r)"
fi

if [ -z "$email" ] && [ "$release" = "18.04" ]; then
	echo "Email address is required"
	exit 2
fi
if [ ! -f /root/.rnd ]; then
	touch /root/.rnd
fi

# Perform verification if read-only mode is enabled
check_hestia_demo_mode

#----------------------------------------------------------#
#                       Action                             #
#----------------------------------------------------------#

# Create temporary work directory
workdir=$(mktemp -d)
cd $workdir

# Generate private key
openssl genrsa "$KEY_SIZE" > "$domain.key" 2> /dev/null

subj=""
# Generate the CSR
if [ -n "$email" ]; then
	subj="/emailAddress=$email"
fi

subj="$subj/C=$country/ST=$state/L=$city/O=$org"
subj="$subj/OU=$org_unit/CN=$domain_idn"

if [ -z "$aliases" ]; then
	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-out $domain.csr > /dev/null 2>&1
else
	for alias in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
		if [[ "$alias" = *[![:ascii:]]* ]]; then
			alias=$(idn2 --quiet $alias)
		fi
		dns_aliases="${dns_aliases}DNS:$alias,"
	done
	dns_aliases=$(echo $dns_aliases | sed "s/,$//")
	if [ -e "/etc/ssl/openssl.cnf" ]; then
		ssl_conf='/etc/ssl/openssl.cnf'
	else
		ssl_conf="/etc/pki/tls/openssl.cnf"
	fi

	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-reqexts SAN \
		-config <(cat $ssl_conf \
			<(printf "[SAN]\nsubjectAltName=$dns_aliases")) \
		-out $domain.csr > /dev/null 2>&1
fi

# Generate the cert 1 year
openssl x509 -req -sha256 \
	-days $DAYS \
	-in $domain.csr \
	-signkey $domain.key \
	-out $domain.crt > /dev/null 2>&1

# Listing certificates
if [ -e "$domain.crt" ]; then
	crt=$(cat $domain.crt | sed ':a;N;$!ba;s/\n/\\n/g')
fi

if [ -e "$domain.key" ]; then
	key=$(cat $domain.key | sed ':a;N;$!ba;s/\n/\\n/g')
fi

if [ -e "$domain.csr" ]; then
	csr=$(cat $domain.csr | sed ':a;N;$!ba;s/\n/\\n/g')
fi

case $format in
	json) json_list_ssl ;;
	plain)
		nohead=1
		shell_list_ssl
		;;
	shell) shell_list_ssl ;;
	*) check_args '1' '0' '[FORMAT]' ;;
esac

# Don't allow non root users view folder
chmod 660 $workdir
# Clean up the mess
echo "rm -rf $workdir" | at -M "now +15 minute" > /dev/null 2>&1
# Delete tmp dir
#rm -rf $workdir

#----------------------------------------------------------#
#                       Hestia                             #
#----------------------------------------------------------#

# Logging
log_event "$OK" "$ARGUMENTS"

exit
