#!/usr/bin/env bash
#
# Copyright: Patrick Koppen
# License:   GPLv3
# Version:   1.2
# Date:      29.12.2012

# Locking code to try to make sure that two instances do not run together and
# corrupt the CA files.
LOCKDIR="/tmp/burp_ca.lockdir"
PIDFILE="$LOCKDIR/pid"

lock()
{
	# Originally from http://wiki.bash-hackers.org/howto/mutex, and
	# adjusted somewhat.
	if mkdir "$LOCKDIR" 2>/dev/null ; then
		trap 'rm -rf "$LOCKDIR"; exit $?' INT TERM EXIT
		echo $$ > "$PIDFILE" || return 1
		return 0
	else
		oldpid="$(cat "$PIDFILE")" || return 1

		if ! ps -p "$oldpid" &>/dev/null; then
			echo "Removing stale lock with pid $oldpid" 1>&2
			rm -rf "$LOCKDIR" || return 1
			echo "Restarting myself" 1>&2
			exec "$0" "$@"
		fi
		return 1
	fi
}

maxwait=60
sleeptime=1
slept=0

while ! lock; do
	sleep $sleeptime
	let slept+=$sleeptime
	let sleeptime*=2
	if [ $slept -ge $maxwait ]; then
		echo "Failed to acquire lock $LOCKDIR in $slept seconds" 1>&2
		exit 1
	fi
done

name=$(hostname -f 2>/dev/null)
# Try NetBSD style.
[ -n "$name" ] || name=$(hostname 2>/dev/null)
if [ -z "$name" ] ; then
	echo "Could not determine hostname" 1>&2
	exit 1
fi

set -e

etc=/etc/burp
dir=${etc}/CA
conf=${etc}/CA.cnf
ca_days=7300
size=2048

def_umask=022
sec_umask=077

function help() {
  cat <<EOF
$0: Help:
    -h|--help               show help
    -i|--init               inititalize CA
    -k|--key                generate new key
    -K|--keypath <path>     path to new key
    -r|--request            generate certificate sign request
    -R|--requestpath <path> path to certificate sign request
    -s|--sign               sign csr (use --ca <ca> and --name <name>)
       --batch              do not prompt for anything
       --revoke <number>    revoke certificate with serial number
       --crl                generate certificate revoke list
    -d|--dir <dir>          ca output dir (default: $dir)
    -c|--config             config file (default: $conf)
    -n|--name               name (default: $name)
    -D|--days               valid days for certificate (default in config file)
       --ca_days            valid days for CA certificate (default: $ca_days)
    -S|--size               key size (default: $size)
    -a|--ca                 ca name if different from name
    -f|--dhfile <path>      generate Diffie-Hellman file
    -A|--altname            subjectAltName
EOF
}

check_second_arg()
{
	if [ "$1" -eq 0 ] ; then
		help
		exit 1
	fi
}

while [ $# -gt 0 ]
do
	case $1 in
		-h|--help) help; exit 0 ;;
		-i|--init) init=yes ;;
		-k|--key) key=yes ;;
		-K|--keypath) check_second_arg $#; keypath=$2; shift ;;
		-r|--request) request=yes ;;
		-R|--requestpath) check_second_arg $#; requestpath=$2; shift ;;
		-s|--sign) sign=yes ;;
		   --batch) batch="-batch" ;;
		   --revoke) check_second_arg $#; revoke=$2; shift ;;
		   --crl) crl=yes ;;
		-d|--dir) check_second_arg $#; dir=$2; shift ;;
		-c|--config) check_second_arg $#; conf=$2; shift ;;
		-n|--name) check_second_arg $#; name=$2; shift ;;
		-D|--days) check_second_arg $#; days="-days $2"; shift ;;
		   --ca_days) check_second_arg $#; ca_days=$2; shift ;;
		-S|--size) check_second_arg $#; size=$2; shift ;;
		-a|--ca) check_second_arg $#; ca=$2; shift ;;
		-f|--dhfile) check_second_arg $#; dhfile=$2; shift ;;
		-A|--altname) check_second_arg $#; altname=$2; shift ;;
		--) shift; break;;
		-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
		*) break;;
	esac
	shift
done

if [ -n "$dhfile" ] ; then
	openssl dhparam -dsaparam -out "$dhfile" 2048
	r=$?
	chmod 600 "$dhfile"
	exit $r
fi

if [ -z "$ca" ]; then
	ca=${name}
fi

if [ -n "$altname" ]; then
	altname="subjectAltName=$altname"
fi

# init CA
if [ "$init" = "yes" ]; then
	echo "Init... ${ca}"
	if [ ! -f ${conf} ]; then
		echo "$0: error - config ${conf} missing" 1>&2
		exit 1
	fi
	if [ -d ${dir} ]; then
		echo "$0: error - ${dir} exists, ca initialized" 1>&2
		exit 1
	fi
  
	mkdir ${dir}
	mkdir ${dir}/certs
	mkdir ${dir}/newcerts

	umask ${sec_umask}
	openssl genrsa -out ${dir}/CA_${ca}.key ${size}
	umask ${def_umask}
	TEMP=$(mktemp /tmp/b                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          