Bläddra i källkod

Initial commit

JDierkse 4 år sedan
incheckning
bbcea2a5ae
4 ändrade filer med 1007 tillägg och 0 borttagningar
  1. 0 0
      .gitignore
  2. 787 0
      certificate.sh
  3. 50 0
      expiryCheck.sh
  4. 170 0
      openssl.cnf

+ 0 - 0
.gitignore


+ 787 - 0
certificate.sh

@@ -0,0 +1,787 @@
+#!/bin/bash
+
+#------ Settings ------
+
+OPENSSL="openssl"
+CONFIG="./openssl.cnf"
+
+ROOTCADAYS="-days 3650"		# 10 years
+CADAYS="-days 1825"		#  5 years
+#CADAYS="-days 825"		#  2 years
+DAYS="-days 397"		#  1 year
+
+CONFIGOPTION="-config ${CONFIG}"
+REQ="${OPENSSL} req ${CONFIGOPTION}"
+CA="${OPENSSL} ca ${CONFIGOPTION}"
+VERIFY="${OPENSSL} verify"
+X509="${OPENSSL} x509"
+PKCS12="${OPENSSL} pkcs12"
+
+CAFOLDER="./CA"
+CAKEY="./cakey.pem"
+CAREQ="./careq.pem"
+CACERT="./cacert.pem"
+PASSEXTENSION="keyfile"
+PASSFILE="./${PASSEXTENSION}"
+TYPEFILE="./type"
+CHAINFILE="./cachain.pem"
+
+C="NL"
+ST="Noord-Brabant"
+L="Veldhoven"
+O="Dierkse DataManagement"
+OU="Secure Digital Certificate Signing"
+#CN="CommonName"
+E="certification@dierkse.nl"
+
+#------ Functions ------
+
+execute() {
+	COMMAND=$@
+
+	eval ${COMMAND}
+	RETURNVALUE=$?
+
+	if [ "${RETURNVALUE}" -ne "0" ]; then
+		exit ${RETURNVALUE}
+	fi
+}
+
+writeRandomString() {
+	SIZE=$1
+	FILE=$2
+
+	tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' < /dev/urandom | head -c ${SIZE} > "${FILE}"
+}
+
+validateType() {
+	TYPE=$1
+	VALIDTYPE=""
+
+	if [[ "${TYPE}" == "ROOTCA" ||
+	      "${TYPE}" == "INTERMEDIATECA" ||
+	      "${TYPE}" == "VPNCA" ||
+	      "${TYPE}" == "WEBSERVER" ||
+	      "${TYPE}" == "WEBCLIENT" ||
+	      "${TYPE}" == "APPLICATIONCLIENT" ||
+	      "${TYPE}" == "EMAIL" ||
+	      "${TYPE}" == "VPN" ]]; then
+		VALIDTYPE=${TYPE}
+	fi
+
+}
+
+copyPem() {
+	INFILE=$1
+	OUTFILE=$2
+	BOUND=$3
+	FLAG=0
+
+	if [ ! -f "${INFILE}" ]; then
+		echo "Missing File ${INFILE}"
+		exit -1
+	fi
+
+	if [[ -z "$BOUND" ]]; then
+		echo "Missing Boundary"
+		exit -1
+	fi
+
+	exec < "${INFILE}";
+	while read LINE; do
+		if [ ${FLAG} -eq 1 ]; then
+			echo ${LINE}|grep "^-----END.*${BOUND}"  2>/dev/null 1>/dev/null
+			if [ $? -eq 0 ] ; then
+				echo ${LINE} >> "${OUTFILE}"
+				break
+			else
+				echo ${LINE} >> "${OUTFILE}"
+			fi
+		fi
+
+		echo ${LINE} | grep "^-----BEGIN.*${BOUND}"  2>/dev/null 1>/dev/null
+		if [ $? -eq 0 ]; then
+			echo ${LINE} > "${OUTFILE}"
+			FLAG=1
+		fi
+	done
+}
+
+newCertificate() {
+	KEYBITS=2048
+
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [[ "${TYPE}" == "WEBSERVER" ]]; then
+		EXTENSIONS="server_cert -nodes"
+
+		SAN=()
+		if [ ! -z "${CN}" ]; then
+			SAN+=("${CN}")
+			SAN+=("*.${CN}")
+		fi
+		SAN+=("${EXTRASAN[@]}")
+
+		IP=("${EXTRAIP[@]}")
+	fi
+
+	if [[ "${TYPE}" == "WEBCLIENT" ]]; then
+		EXTENSIONS="client_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
+		EXTENSIONS="application_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "EMAIL" ]]; then
+		EXTENSIONS="email_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "VPN" ]]; then
+		EXTENSIONS="vpn_cert -nodes"
+
+		SAN=()
+		if [ ! -z "${CN}" ]; then
+			SAN+=("${CN}")
+		fi
+	fi
+
+	if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
+		KEYBITS=4096
+		DAYS=${CADAYS}
+		EXTENSIONS="intermediate_extensions"
+	fi
+
+	COMMAND="${REQ} -new -x509 -newkey rsa:${KEYBITS} -extensions server_cert -keyout \"${FILENAME}.key\" -out \"${FILENAME}.crt\" ${DAYS}"
+
+	if [ ! -z "${CN}" ]; then
+		SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
+		COMMAND+=" -subj \"${SUBJECT}\""
+	fi
+
+	if [[ "${TYPE}" == "WEBSERVER" || "${TYPE}" == "VPN" || ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
+		COMMAND+=" -addext \"subjectAltName="
+		INDEX=0
+		for S in "${SAN[@]}"
+		do
+			((INDEX+=1))
+			COMMAND+="DNS.${INDEX}: ${S},"
+		done
+
+		INDEX=0
+		for I in "${IP[@]}"
+		do
+			((INDEX+=1))
+			COMMAND+="IP.${INDEX}: ${I},"
+		done
+
+		COMMAND=${COMMAND%?}
+		COMMAND+="\""
+	fi
+
+	execute ${COMMAND}
+}
+
+newRequest() {
+	KEYBITS=2048
+
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [[ "${TYPE}" == "WEBSERVER" ]]; then
+		EXTENSIONS="server_cert -nodes"
+
+		SAN=()
+		if [ ! -z "${CN}" ]; then
+			SAN+=("${CN}")
+			SAN+=("*.${CN}")
+		fi
+		SAN+=("${EXTRASAN[@]}")
+
+		IP=("${EXTRAIP[@]}")
+	fi
+
+	if [[ "${TYPE}" == "WEBCLIENT" ]]; then
+		EXTENSIONS="client_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
+		EXTENSIONS="application_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "EMAIL" ]]; then
+		EXTENSIONS="email_cert -nodes"
+	fi
+
+	if [[ "${TYPE}" == "VPN" ]]; then
+		EXTENSIONS="vpn_cert -nodes"
+
+		SAN=()
+		if [ ! -z "${CN}" ]; then
+			SAN+=("${CN}")
+		fi
+	fi
+
+	if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
+		KEYBITS=4096
+		writeRandomString 128 "${FILENAME}.${PASSEXTENSION}"
+		chmod 000 "${FILENAME}.${PASSEXTENSION}"
+		EXTENSIONS="intermediate_extensions -passout file:\"${FILENAME}.${PASSEXTENSION}\""
+	fi
+
+	COMMAND="${REQ} -new -newkey rsa:${KEYBITS} -extensions ${EXTENSIONS} -keyout \"${FILENAME}.key\" -out \"${FILENAME}.csr\""
+
+	if [ ! -z "${CN}" ]; then
+		SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
+		COMMAND+=" -subj \"${SUBJECT}\""
+	fi
+
+	if [[ "${TYPE}" == "WEBSERVER" || "${TYPE}" == "VPN" || ${#SAN[@]} -ne "0" || ${#IP[@]} -ne "0" ]]; then
+		COMMAND+=" -addext \"subjectAltName="
+		INDEX=0
+		for S in "${SAN[@]}"
+		do
+			((INDEX+=1))
+			COMMAND+="DNS.${INDEX}: ${S},"
+		done
+
+		INDEX=0
+		for I in "${IP[@]}"
+		do
+			((INDEX+=1))
+			COMMAND+="IP.${INDEX}: ${I},"
+		done
+
+		COMMAND=${COMMAND%?}
+		COMMAND+="\""
+	fi
+
+	execute ${COMMAND}
+}
+
+newCertificateAuthority() {
+	if [[ "${TYPE}" == "ROOTCA" ]]; then
+		KEYBITS=8192
+		EXTENSIONS="CA_root"
+		DAYS=${ROOTCADAYS}
+		SUBTYPE="INTERMEDIATECA"
+	fi
+
+	if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
+		KEYBITS=4096
+		EXTENSIONS="CA_intermediate"
+		DAYS=${CADAYS}
+	fi
+
+	if [[ "${TYPE}" == "VPNCA" ]]; then
+		KEYBITS=4096
+		EXTENSIONS="CA_root"
+		DAYS=${ROOTCADAYS}
+		SUBTYPE="VPN"
+	fi
+
+	if [ -z "${KEYBITS}" ]; then
+		echo "Error: invalid certificate authority type" >&2
+
+		exit -1
+	fi
+
+	if [ ! -f ${CAFOLDER}/serial ]; then
+		mkdir -p ${CAFOLDER}
+		mkdir -p ${CAFOLDER}/certs
+		mkdir -p ${CAFOLDER}/crl
+		mkdir -p ${CAFOLDER}/newcerts
+		mkdir -p ${CAFOLDER}/private
+		touch ${CAFOLDER}/index.txt
+		echo 1000 > ${CAFOLDER}/crl/crlnumber
+		openssl rand -writerand ${CAFOLDER}/private/.rand
+		writeRandomString 128 ${CAFOLDER}/private/${PASSFILE}
+		chmod 000 ${CAFOLDER}/private/${PASSFILE}
+		if [ ! -z "${SUBTYPE}" ]; then
+			echo "${SUBTYPE}" > ${CAFOLDER}/${TYPEFILE}
+		fi
+	fi
+
+	if [ ! -f ${CAFOLDER}/private/${CAKEY} ]; then
+		if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
+			echo "CA certificate filename (or enter to create)"
+			read NAME
+		fi
+
+		if [ "${NAME}" ]; then
+			if [ -f "./${NAME}" ]; then
+				NAME="./${NAME%.*}"
+			else
+				if [ -f "../${NAME}" ]; then
+					NAME="../${NAME%.*}"
+				else
+					if [ -f "./${NAME}.crt" ]; then
+						NAME="./${NAME}"
+					else
+						if [ -f "../${NAME}.crt" ]; then
+							NAME="../${NAME}"
+						else
+							echo "Certificate not found"
+							echo "   ("./${NAME}")"
+							echo "   ("../${NAME}")"
+							echo "   ("./${NAME}.crt")"
+							echo "   ("../${NAME}.crt")"
+							echo ""
+							exit -1
+						fi
+					fi
+				fi
+			fi
+
+			if [ -f "${NAME}.csr" ]; then
+				copyPem "${NAME}.csr" ${CAFOLDER}/${CAREQ} CERTIFICATE
+			else
+				echo "CA Request missing (${NAME}.csr)"
+				exit -1
+			fi
+
+			if [ -f "${NAME}.key" ]; then
+				copyPem "${NAME}.key" ${CAFOLDER}/private/${CAKEY} PRIVATE
+			else
+				echo "CA Private Key missing (${NAME}.key)"
+				exit -1
+			fi
+
+			if [ -f "${NAME}.${PASSEXTENSION}" ]; then
+				cp "${NAME}.${PASSEXTENSION}" ${CAFOLDER}/private/${PASSFILE}
+				chmod 000 ${CAFOLDER}/private/${PASSFILE}
+			else
+				echo "CA Private Key Keyfile missing (${NAME}.${PASSEXTENSION})"
+			fi
+
+			if [ -f "${NAME}.crt" ]; then
+				copyPem "${NAME}.crt" ${CAFOLDER}/${CACERT} CERTIFICATE
+			else
+				echo "CA Certificate missing (${NAME}.crt)"
+				exit -1
+			fi
+
+			if [ -f "${NAME}.pem" ]; then
+				COMMAND="cp \"${NAME}.pem\" ${CAFOLDER}/${CHAINFILE}"
+				execute ${COMMAND}
+			else
+				echo "CA Chain missing (${NAME}.pem)"
+				exit -1
+			fi
+
+			if [ ! -f "${CAFOLDER}/serial" ]; then
+				COMMAND="$X509 -in ${CAFOLDER}/${CACERT} -noout -next_serial -out ${CAFOLDER}/serial"
+				execute ${COMMAND}
+			fi
+		else
+			COMMAND="$REQ -new -newkey rsa:${KEYBITS} -passout file:${CAFOLDER}/private/${PASSFILE} -keyout ${CAFOLDER}/private/${CAKEY} -out ${CAFOLDER}/${CAREQ}"
+
+			if [ ! -z "${CN}" ]; then
+				SUBJECT="/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${E}"
+				COMMAND+=" -subj \"${SUBJECT}\""
+			fi
+
+			execute ${COMMAND}
+
+			COMMAND="$CA -create_serial -out ${CAFOLDER}/${CACERT} ${DAYS} -batch -keyfile ${CAFOLDER}/private/${CAKEY} -passin file:${CAFOLDER}/private/${PASSFILE} -selfsign -name ${EXTENSIONS} -infiles ${CAFOLDER}/${CAREQ}"
+			execute ${COMMAND}
+
+			copyPem ${CAFOLDER}/${CACERT} ${CAFOLDER}/${CACERT}.tmp CERTIFICATE
+
+			COMMAND="mv ${CAFOLDER}/${CACERT}.tmp ${CAFOLDER}/${CACERT}"
+			execute ${COMMAND}
+
+			COMMAND="cp ${CAFOLDER}/${CACERT} ${CAFOLDER}/${CHAINFILE}"
+			execute ${COMMAND}
+		fi
+	fi
+
+	generateCrl
+}
+
+renewCertificate() {
+	revokeCertificate
+	signRequest	
+}
+
+renewCertificateAuthorityCertificate() {
+	# TODO
+
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	echo "Not implemented"
+}
+
+signCertificate() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.csr" ]; then
+		echo "Missing Certificate Request"
+		exit -1
+	fi
+
+	COMMAND="${X509} -x509toreq -signkey \"${FILENAME}.key\" -in \"${FILENAME}.csr\" -out temporary.pem"
+	execute ${COMMAND}
+
+	COMMAND="${CA} -policy policy_anything -passin file:${CAFOLDER}/private/${PASSFILE} ${DAYS} -out \"${FILENAME}.crt\" -infiles temporary.pem"
+	execute ${COMMAND}
+
+	copyPem "${FILENAME}.crt" "${FILENAME}.crt.tmp" CERTIFICATE
+
+	COMMAND="mv \"${FILENAME}.crt.tmp\" \"${FILENAME}.crt\""
+	execute ${COMMAND}
+
+	COMMAND="cat \"${FILENAME}.crt\" ${CAFOLDER}/${CHAINFILE} > \"${FILENAME}.pem\""
+	execute ${COMMAND}
+}
+
+signRequest() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.csr" ]; then
+		echo "Missing Certificate Request"
+		exit -1
+	fi
+
+	if [[ "${TYPE}" == "WEBSERVER" ]]; then
+		EXTENSIONS="server_cert"
+	fi
+
+	if [[ "${TYPE}" == "WEBCLIENT" ]]; then
+		EXTENSIONS="client_cert"
+	fi
+
+	if [[ "${TYPE}" == "APPLICATIONCLIENT" ]]; then
+		EXTENSIONS="application_cert"
+	fi
+
+	if [[ "${TYPE}" == "EMAIL" ]]; then
+		EXTENSIONS="email_cert"
+	fi
+
+	if [[ "${TYPE}" == "VPN" ]]; then
+		EXTENSIONS="vpn_cert"
+	fi
+
+	if [[ "${TYPE}" == "INTERMEDIATECA" ]]; then
+		DAYS=${CADAYS}
+		EXTENSIONS="intermediate_extensions"
+	fi
+
+	COMMAND="${CA} -policy policy_match -passin file:${CAFOLDER}/private/${PASSFILE} -name CA_intermediate -extensions ${EXTENSIONS} ${DAYS} -out \"${FILENAME}.crt\" -infiles \"${FILENAME}.csr\""
+	execute ${COMMAND}
+
+	copyPem "${FILENAME}.crt" "${FILENAME}.crt.tmp" CERTIFICATE
+
+	COMMAND="mv \"${FILENAME}.crt.tmp\" \"${FILENAME}.crt\""
+	execute ${COMMAND}
+
+	COMMAND="cat \"${FILENAME}.crt\" ${CAFOLDER}/${CHAINFILE} > \"${FILENAME}.pem\""
+	execute ${COMMAND}
+}
+
+signCertificateAuthorityCertificate() {
+	# TODO
+
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	# $CA -policy policy_anything -out newcert.pem -extensions v3_ca -infiles newreq.pem
+	# RET=$?
+
+	echo "Not implemented"
+}
+
+signRequestAnything() {
+	# TODO
+
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	# $CA -policy policy_anything -infiles newreq.pem
+	# RET=$?
+
+	echo "Not implemented"
+}
+
+createCertificatePackage() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.crt" ]; then
+		echo "Missing Certificate"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.key" ]; then
+		echo "Missing Private Key"
+		exit -1
+	fi
+
+	CACERTCN=$(${X509} -noout -subject -nameopt multiline -in ${CAFOLDER}/${CACERT} | sed -n 's/ *commonName *= //p')
+
+	COMMAND="${PKCS12} -in \"${FILENAME}.crt\" -inkey \"${FILENAME}.key\" -certfile ${CAFOLDER}/${CHAINFILE} -caname \"${CACERTCN}\" -out \"${FILENAME}.p12\" -export -name \"${FILENAME}\""
+	execute ${COMMAND}
+}
+
+generateCrl() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	COMMAND="${CA} -passin file:${CAFOLDER}/private/${PASSFILE} -gencrl -out ${CAFOLDER}/crl/crl.pem"
+	execute ${COMMAND}
+
+	COMMAND="cat ${CAFOLDER}/${CHAINFILE} ${CAFOLDER}/crl/crl.pem > ${CAFOLDER}/crl/crl_chain.pem"
+	execute ${COMMAND}
+}
+
+revokeCertificate() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.crt" ]; then
+		echo "Missing Certificate"
+		exit -1
+	fi
+
+	COMMAND="${CA} -passin file:${CAFOLDER}/private/${PASSFILE} -revoke \"${FILENAME}.crt\""
+	execute ${COMMAND}
+
+	COMMAND="mv \"${FILENAME}.crt\" \"${FILENAME}.crt.revoked\""
+	execute ${COMMAND}
+
+	generateCrl
+}
+
+verifyCertificate() {
+	if [ ! -d ${CAFOLDER} ]; then
+		echo "Missing CA Folder"
+		exit -1
+	fi
+
+	if [ ! -f "${FILENAME}.crt" ]; then
+		echo "Missing Certificate"
+		exit -1
+	fi
+
+	COMMAND="${VERIFY} -CAfile ${CAFOLDER}/${CHAINFILE} \"${FILENAME}.crt\""
+	execute ${COMMAND}
+
+	COMMAND="${VERIFY} -crl_check -CAfile ${CAFOLDER}/crl/crl_chain.pem \"${FILENAME}.crt\""
+	execute ${COMMAND}
+}
+
+printHelp() {
+	echo "" >&2
+	echo "usage: $0 <OPERATION> -t <TYPE> [--san <SAN>] [--ip <IP>] [COMMON NAME]" >&2
+	echo "" >&2
+	echo "  Certificate Types:" >&2
+	echo "   ROOTCA			" >&2
+	echo "   INTERMEDIATECA		" >&2
+	echo "   VPNCA			" >&2
+	echo "   WEBSERVER		" >&2
+	echo "   WEBCLIENT		" >&2
+	echo "   APPLICATIONCLIENT	" >&2
+	echo "   EMAIL			" >&2
+	echo "   VPN			" >&2
+	echo "" >&2
+	echo "  Operations:" >&2
+	echo "   -c|--newcert		Create a new certificate and private key" >&2
+	echo "   -n|--newreq		Create a new certificate request and private key" >&2
+	echo "   --newca		Create a new certificate authority" >&2
+	echo "   -r|--renewcert		Renew an existing certificate (requires a certificate request)" >&2
+	#echo "   --renewca		Renew the certificate authority certificate" >&2
+	echo "   --signcert		Sign a certificate with the certificate authority" >&2
+	echo "   -s|--signreq		Create and sign a new certificate with the certificate autority" >&2
+	#echo "   --signca		Sign the certificate authority certificate" >&2
+	#echo "   --xsign		Sign the certificate request with the certificate authority using the 'policy_anything' option" >&2
+	echo "   -p|--pkcs12		Create pkcs12 package containing the certificate and its private key" >&2
+	echo "   --revoke		Revoke a certificate" >&2
+	echo "   --crl			Generate CRL file" >&2
+	echo "   -v|--verify		Verify a certificate" >&2
+	echo "   -h|--help		Display this help message" >&2
+	echo "" >&2
+}
+
+#------ Commandline parsing ------
+
+shopt -s nocasematch
+
+EXTRASAN=()
+EXTRAIP=()
+
+POSITIONAL=()
+while [[ $# -gt 0 ]]; do
+	key="$1"
+
+	case $key in
+		-t|--type)
+			validateType ${2}
+
+			shift # past argument
+			shift # past value
+			;;
+		-c|--newcert)
+			OPERATION="newCertificate"
+
+			shift # past argument
+			;;
+		-n|--newreq)
+			OPERATION="newRequest"
+
+			shift # past argument
+			;;
+		--newca)
+			OPERATION="newCertificateAuthority"
+
+			shift # past argument
+			;;
+		-r|--renewcert)
+			OPERATION="renewCertificate"
+
+			shift # past argument
+			;;
+		#--renewca)
+		#	OPERATION="renewCertificateAuthorityCertificate"
+		#
+		#	shift # past argument
+		#	;;
+		--signcert)
+			OPERATION="signCertificate"
+
+			shift # past argument
+			;;
+		-s|--signreq)
+			OPERATION="signRequest"
+
+			shift # past argument
+			;;
+		#--signca)
+		#	OPERATION="signCertificateAuthorityCertificate"
+		#
+		#	shift # past argument
+		#	;;
+		#--xsign)
+		#	OPERATION="signRequestAnything"
+		#
+		#	shift # past argument
+		#	;;
+		-p|--pkcs12)
+			OPERATION="createCertificatePackage"
+
+			shift # past argument
+			;;
+		--revoke)
+			OPERATION="revokeCertificate"
+
+			shift # past argument
+			;;
+		--crl)
+			OPERATION="generateCrl"
+
+			shift # past argument
+			;;
+		-v|--verify)
+			OPERATION="verifyCertificate"
+
+			shift # past argument
+			;;
+		--san)
+			EXTRASAN+=("$2")
+
+			shift # past argument
+			shift # past value
+			;;
+		--ip)
+			EXTRAIP+=("$2")
+
+			shift # past argument
+			shift # past value
+			;;
+		-h|--help)
+			OPERATION="printHelp"
+
+			shift # past argument
+			;;
+
+		*)
+			POSITIONAL+=("$1")
+			shift # past argument
+			;;
+	esac
+done
+
+FILENAME="newCertificate"
+if (( ${#POSITIONAL[@]} )); then
+	CN=${POSITIONAL[0]}
+	FILENAME=${CN}
+fi
+
+if [[ -z "${TYPE}" &&
+      -f "${CAFOLDER}/${TYPEFILE}" ]]; then
+	TYPE=$(<${CAFOLDER}/${TYPEFILE})
+
+	validateType ${TYPE}
+fi
+
+if [[ -z "${TYPE}" &&
+      "${OPERATION}" != "revokeCertificate" &&
+      "${OPERATION}" != "generateCrl" &&
+      "${OPERATION}" != "verifyCertificate" &&
+      "${OPERATION}" != "createCertificatePackage" &&
+      "${OPERATION}" != "printHelp" ]]; then
+	echo "Error: missing certificate type" >&2
+
+	printHelp
+	exit -1
+fi
+
+if [[ ! -z "${TYPE}" &&
+      -z "${VALIDTYPE}" &&
+      "${OPERATION}" != "revokeCertificate" &&
+      "${OPERATION}" != "generateCrl" &&
+      "${OPERATION}" != "verifyCertificate" &&
+      "${OPERATION}" != "createCertificatePackage" &&
+      "${OPERATION}" != "printHelp" ]]; then
+	echo "Error: invalid certificate type" >&2
+
+	printHelp
+	exit -1
+fi
+
+if [ -z "${OPERATION}" ]; then
+	echo "Error: missing operation" >&2
+
+	printHelp
+	exit -1
+fi
+
+TYPE=${VALIDTYPE}
+eval ${OPERATION}
+
+exit 0
+

+ 50 - 0
expiryCheck.sh

@@ -0,0 +1,50 @@
+#!/bin/bash
+
+EXPIRATIONDAYS=90
+
+checkCertificate () {
+	CERTIFICATE=$@
+
+	STARTNOTIFICATIONDATE=$(date +%s)
+	EXPIRYNOTIFICATIONDATE=$(($(date +%s) + (86400*${EXPIRATIONDAYS})))
+
+	SUBJECT=$(openssl x509 -in "${CERTIFICATE}" -noout -text | grep "Subject:" | sed 's/^.*CN[ ]*=[ ]*\(.*\),.*$/\1/')
+
+	STARTDATE=$(openssl x509 -in "${CERTIFICATE}" -noout -text | grep 'Not Before' | awk '{printf "%s %.2d %s %s\n",$3,$4,$6,$5}')
+	STARTDATENUMERIC=$(date -d "${STARTDATE}" '+%s');
+
+	EXPIRATIONDATE=$(openssl x509 -in "${CERTIFICATE}" -noout -text | grep 'Not After' | awk '{printf "%s %.2d %s %s\n",$4,$5,$7,$6}')
+	EXPIRATIONDATENUMERIC=$(date -d "${EXPIRATIONDATE}" '+%s');
+
+	if [ ${STARTNOTIFICATIONDATE} -lt ${STARTDATENUMERIC} ]
+	then
+		echo -e "\tOn ${STARTDATE}, the CERTIFICATE for \"${SUBJECT}\" will become valid"
+	fi
+
+	if [ ${EXPIRYNOTIFICATIONDATE} -gt ${EXPIRATIONDATENUMERIC} ]
+	then
+		echo -e "\tOn ${EXPIRATIONDATE}, the CERTIFICATE for \"${SUBJECT}\" will expire"
+	fi
+}
+
+for DIRECTORY in ./*/
+do
+	DIRECTORY=${DIRECTORY%*/}
+	DIRECTORY=${DIRECTORY:2}
+
+	if [ "${DIRECTORY}" != "openssl" ]; then
+		echo "${DIRECTORY}:"
+		cd "${DIRECTORY}"
+
+		for CERTIFICATE in ./*.crt
+		do
+			if [[ -f "${CERTIFICATE}" ]]
+			then
+				checkCertificate ${CERTIFICATE}
+			fi
+		done
+
+		cd - > /dev/null
+	fi
+done
+

+ 170 - 0
openssl.cnf

@@ -0,0 +1,170 @@
+HOME				= .
+RANDFILE			= $ENV::HOME/.rnd
+oid_section			= new_oids
+
+#[ CA_default ]
+dir				= ./CA
+certs				= $dir/certs
+crl_dir				= $dir/crl
+database			= $dir/index.txt
+unique_subject			= yes
+new_certs_dir			= $dir/newcerts
+certificate			= $dir/cacert.pem
+serial				= $dir/serial
+crlnumber			= $crl_dir/crlnumber
+crl				= $crl_dir/crl.pem
+private_key			= $dir/private/cakey.pem
+RANDFILE			= $dir/private/.rand
+default_days			= 825
+default_crl_days		= 30
+default_md			= sha256
+preserve			= no
+policy				= policy_match
+
+[ ca ]
+default_ca			= CA_default 
+
+[ new_oids ]
+tsa_policy1			= 1.2.3.4.1
+tsa_policy2			= 1.2.3.4.5.6
+tsa_policy3			= 1.2.3.4.5.7
+iKEIntermediate			= 1.3.6.1.5.5.8.2.2
+
+[ policy_match ]
+countryName			= match
+stateOrProvinceName		= match
+organizationName		= match
+organizationalUnitName		= optional
+commonName			= supplied
+emailAddress			= optional
+
+[ policy_anything ]
+countryName			= optional
+stateOrProvinceName		= optional
+localityName			= optional
+organizationName		= optional
+organizationalUnitName		= optional
+commonName			= supplied
+emailAddress			= optional
+
+[ CA_default ]
+certs				= $dir/certs
+crl_dir				= $dir/crl
+database			= $dir/index.txt
+unique_subject			= yes
+new_certs_dir			= $dir/newcerts
+certificate			= $dir/cacert.pem
+serial				= $dir/serial
+crlnumber			= $crl_dir/crlnumber
+crl				= $crl_dir/crl.pem
+private_key			= $dir/private/cakey.pem
+RANDFILE			= $dir/private/.rand
+default_days			= 825
+default_crl_days		= 30
+default_md			= sha256
+preserve			= no
+policy				= policy_match
+
+[ CA_root ]
+x509_extensions			= root_extensions
+
+[ root_extensions ]
+basicConstraints		= critical, CA:TRUE, pathlen:1
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid:always, issuer:always
+keyUsage			= critical, cRLSign, keyCertSign
+
+[ CA_VPN ]
+dir				= ./rootCA
+x509_extensions			= intermediate_extensions
+copy_extensions			= copy
+
+[ CA_intermediate ]
+x509_extensions			= intermediate_extensions
+copy_extensions			= copy
+
+[ intermediate_extensions ]
+basicConstraints		= critical, CA:TRUE, pathlen:0
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid:always, issuer:always
+keyUsage			= critical, cRLSign, keyCertSign
+
+[ req ]
+default_bits			= 4096
+default_keyfile			= privkey.pem
+distinguished_name		= req_distinguished_name
+attributes			= req_attributes
+x509_extensions			= v3_ca
+string_mask			= utf8only
+
+[ req_distinguished_name ]
+countryName			= Country Name (2 letter code)
+countryName_default		= NL
+countryName_min			= 2
+countryName_max			= 2
+stateOrProvinceName		= State or Province Name (full name)
+stateOrProvinceName_default	= Noord-Brabant
+localityName			= Locality Name (eg, city)
+localityName_default		= Veldhoven
+0.organizationName		= Organization Name (eg, company)
+0.organizationName_default	= Dierkse DataManagement
+organizationalUnitName		= Organizational Unit Name (eg, section)
+organizationalUnitName_default	= Secure Digital Certificate Signing
+commonName			= Common Name (e.g. server FQDN or YOUR name)
+commonName_max			= 64
+emailAddress			= Email Address
+emailAddress_default		= certification@dierkse.nl
+emailAddress_max		= 64
+
+[ req_attributes ]
+#challengePassword		= A challenge password
+#challengePassword_min		= 4
+#challengePassword_max		= 20
+#unstructuredName		= An optional company name
+
+[ v3_ca ]
+basicConstraints= CA:TRUE
+subjectKeyIdentifier= hash
+authorityKeyIdentifier= keyid:always,issuer:always
+
+[ server_cert ]
+basicConstraints= CA:FALSE
+subjectKeyIdentifier= hash
+authorityKeyIdentifier= keyid,issuer
+keyUsage= nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage= critical, serverAuth
+
+[ client_cert ]
+basicConstraints		= CA:FALSE
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid,issuer
+keyUsage			= nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage		= critical, clientAuth
+
+[ email_cert ]
+basicConstraints		= CA:FALSE
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid,issuer
+keyUsage			= nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage		= critial, emailProtection
+
+[ application_cert ]
+basicConstraints		= CA:FALSE
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid,issuer
+keyUsage			= nonRepudiation, digitalSignature, keyEncipherment
+
+[ vpn_cert ]
+basicConstraints		= CA:FALSE
+subjectKeyIdentifier		= hash
+authorityKeyIdentifier		= keyid,issuer
+extendedKeyUsage		= critical, iKEIntermediate
+#extendedKeyUsage		= critical, serverAuth, iKEIntermediate
+
+# [ vpn_req_extensions ]
+# subjectAltName		= @vpn_san
+
+# [ vpn_san ]
+# #DNS.1			= vpn.dierkse.nl
+# DNS.1				= iphone6plus
+