#!/bin/bash
set -e

create_csr()
{
	local time="$1"
	local name="$2"
	shift 2
	faketime "$time" openssl req -new -config "${name}.cnf" -key "${name}key.pem" -out "${name}req.pem" "$@"
}

create_ca_cert()
{
	local time="$1"
	local name="$2"
	shift 2
	faketime "$time" openssl req -nodes -x509 -config "${name}caconf.cnf" -key "${name}cakey.pem" -out "${name}cacert.pem" "$@"
}

sign_certificate()
{
	local time="$1"
	local name="$2"
	local ca="$3"
	shift 3
	faketime "$time" openssl ca -batch -config "${ca}caconf.cnf" -in "${name}req.pem" -notext -out "${name}cert.pem" "$@"
}

revoke_certificate()
{
	local time="$1"
	local name="$2"
	local ca="$3"
	shift 3
	faketime "$time" openssl ca -config "${ca}caconf.cnf" -revoke "${name}cert.pem"
	faketime "$time" openssl ca -config "${ca}caconf.cnf" -gencrl -out "${ca}crl.pem"
}

sourcedir=test/certs
transport_sourcedir=test/unittest/transport/certs
destdir=debian/snakeoil-certs

[[ -d "$sourcedir" ]] || (echo>&2 "source directory $sourcedir not found"; exit 1)

mkdir -p "$destdir" "$destdir/certs" "$destdir/crl" "$destdir/certs_sec" "$destdir/crl_sec"
echo 'BAD00000' > "$destdir/serial"
echo 'BAD20000' > "$destdir/serial_sec"
echo 'BAD30000' > "$destdir/serial_other"
touch "$destdir/index.txt" "$destdir/index_sec.txt" "$destdir/index_other.txt"
echo "unique_subject = yes" > "$destdir/index.txt.attr"
echo "00" > "$destdir/crlnumber"
echo "00" > "$destdir/crlnumber_sec"


cp -v "$sourcedir"/*{.cnf,key.pem,.xml,param} "$destdir"

# Transport CA
echo 'BADF0000' > "$destdir/ca.srl"
cp -v "$transport_sourcedir"/*.{cnf,key,pem} "$destdir"

pushd "$destdir"

echo>&2 "[*] Generating CA certificates"
create_ca_cert "1 month ago" main -days 90
create_ca_cert "1 month ago" sec -days 90
create_ca_cert "1 month ago" other -days 90

for name in mainpub mainsub pwdpub expiredpub revokedpub othersub
do
	echo>&2 "[*] Generating certificate $name"
	ca=main
	csr_options=()
	if [[ "$name" =~ ^pwd ]]
	then
		csr_options+=("-passin" "pass:testkey")
	fi
	create_csr "1 week ago" "$name" "${csr_options[@]}"
	valid_for=14
	if [[ "$name" =~ ^expire ]]
	then
		valid_for=1
	fi
	if [[ "$name" =~ ^other ]]
	then
		ca=other
	fi
	sign_certificate "1 week ago" "$name" "$ca" -days $valid_for
	if [[ "$name" =~ ^revoke ]]
	then
		revoke_certificate "1 day ago" "$name" "$ca"
	fi
done
cat maincacert.pem maincrl.pem > joinedcacertcrl.pem

# Fix expiry date in permission grants not to trigger the Y2K38 bug
sed -i -e 's/<not_after>2038/<not_after>2037/g' *.xml

# Sign permission grants
for xmlfile in *.xml
do
	smimefile="${xmlfile%.xml}"
	smimefile="${smimefile%_dds_sec}.smime"
	signer_cert=maincacert.pem
	signer_key=maincakey.pem
	if [[ "$smimefile" == *malicious* ]]
	then
		signer_cert=mainpubcert.pem
		signer_key=mainpubkey.pem
	fi
	if [[ "$smimefile" == *other_ca* ]]
	then
		signer_cert=othercacert.pem
		signer_key=othercakey.pem
	fi
	openssl smime -sign -in "$xmlfile" -text -out "$smimefile" -signer "$signer_cert" -inkey "$signer_key"
done

# Sign permission grants for other CA
for xmlfile in governance_allow_unauth_all_disabled_access_none.xml governance_allow_unauth_all_disabled_read_write_enabled.xml
do
	smimefile="${xmlfile%.xml}_other_ca.smime"
	openssl smime -sign -in "$xmlfile" -text -out "$smimefile" -signer othercacert.pem -inkey othercakey.pem
done

# Transport CA
faketime "1 month ago" openssl req -nodes -x509 -config "ca.cnf" -key "ca.key" -out "ca.crt" -days 90
faketime "1 week ago" openssl req -new -key fastdds.key -passin pass:fastddspwd -out fastdds.csr -config fastdds.cnf
faketime "1 week ago" openssl x509 -req -in fastdds.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out fastdds.crt -days 14

popd

echo>&2 "[*] Running sanity check to see if we missed any additions"
shopt -s nullglob
ret=0
for srcdir in "$sourcedir" "$transport_sourcedir"
do
	for filename in "$srcdir"/*.{pem,smime,key,crt}
	do
		filename="${filename##*/}"
		if [ ! -f "$destdir/$filename" ]
		then
			echo>&2 "****** MISSING $filename"
			ret=1
		fi
	done
done
exit $ret

