selftest: add some helper scripts to mange a CA
authorStefan Metzmacher <metze@samba.org>
Sat, 9 Jan 2016 00:06:05 +0000 (01:06 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 17 Mar 2016 16:17:15 +0000 (17:17 +0100)
This is partly based on the SmartCard HowTo from:
https://wiki.samba.org/index.php/Samba_AD_Smart_Card_Login

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
selftest/manage-ca/manage-ca.sh [new file with mode: 0755]
selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf [new file with mode: 0644]
selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf [new file with mode: 0644]
selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf [new file with mode: 0644]
selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf [new file with mode: 0644]
selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf [new file with mode: 0644]

diff --git a/selftest/manage-ca/manage-ca.sh b/selftest/manage-ca/manage-ca.sh
new file mode 100755 (executable)
index 0000000..ab796b7
--- /dev/null
@@ -0,0 +1,387 @@
+#!/bin/bash
+#
+
+set -e
+set -u
+#set -x
+
+umask 022
+
+function print_usage()
+{
+       echo "Usage:"
+       echo ""
+       echo "${0} <CNF_FILE> <CMD> [<ARG1> [<ARG2>]]"
+       echo ""
+       echo "${0} <CNF_FILE> init_ca"
+       echo "${0} <CNF_FILE> update_crl"
+       echo "${0} <CNF_FILE> publish_crl"
+       echo "${0} <CNF_FILE> create_dc <DC_DNS_NAME> <DC_OBJECTGUID_HEX>"
+       echo "${0} <CNF_FILE> revoke_dc <DC_DNS_NAME> <REVOKE_RESON>"
+       echo "${0} <CNF_FILE> create_user <USER_PRINCIPAL_NAME>"
+       echo "${0} <CNF_FILE> revoke_user <USER_PRINCIPAL_NAME> <REVOKE_RESON>"
+       echo ""
+}
+
+function check_arg()
+{
+       local k="${1}"
+       local v="${2}"
+
+       test -n "${v}" || {
+               print_usage
+               echo "ERROR: CMD[${CMD}] argument <${k}> missing"
+               return 1
+       }
+
+       return 0
+}
+CNF="${1-}"
+test -n "${CNF}" || {
+       print_usage
+       echo "ERROR: speficy <CNF_FILE> see manage-ca.templates.d/manage-CA-example.com.cnf"
+       exit 1
+}
+test -e "${CNF}" || {
+       print_usage
+       echo "ERROR: CNF_FILE[${CNF}] does not exist"
+       exit 1
+}
+CMD="${2-}"
+CMDARG1="${3-}"
+CMDARG2="${4-}"
+
+TEMPLATE_DIR="manage-ca.templates.d"
+DEFAULT_VARS=""
+DEFAULT_VARS="${DEFAULT_VARS} CRL_HTTP_BASE DNS_DOMAIN DEFAULT_BITS"
+DEFAULT_VARS="${DEFAULT_VARS} DEFAULT_BITS DEFAULT_DAYS DEFAULT_CRL_DAYS"
+DEFAULT_VARS="${DEFAULT_VARS} COUNTRY_NAME STATE_NAME LOCALITY_NAME ORGANIZATION_NAME"
+DEFAULT_VARS="${DEFAULT_VARS} ORGANIZATIONAL_UNIT_NAME COMMON_NAME EMAIL_ADDRESS"
+
+source "${CNF}"
+
+DEFAULT_BITS=${DEFAULT_BITS:=8192}
+CA_BITS=${CA_BITS:=${DEFAULT_BITS}}
+DC_BITS=${DC_BITS:=${DEFAULT_BITS}}
+USER_BITS=${USER_BITS:=${DEFAULT_BITS}}
+
+CA_DAYS=${CA_DAYS:=3650}
+CRL_DAYS=${CRL_DAYS:=30}
+DC_DAYS=${DC_DAYS:=730}
+USER_DAYS=${USER_DAYS:=730}
+
+CA_DIR="CA-${DNS_DOMAIN}"
+DEFAULT_VARS="${DEFAULT_VARS} CA_DIR"
+
+CACERT_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.pem"
+CACERT_CER="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.cer"
+CACRL_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.pem"
+CACRL_CRL="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.crl"
+CA_SERIAL="${CA_DIR}/Private/CA-${DNS_DOMAIN}-serial.txt"
+
+function generate_from_template()
+{
+       local base_template="${TEMPLATE_DIR}/$1"
+       local cmd_template="${TEMPLATE_DIR}/$2"
+       local cnf_file="$3"
+       shift 3
+       local vars="$@"
+
+       test -f "${base_template}" || {
+               echo "base_template[${base_template}] does not exists"
+               return 1
+       }
+       test -f "${cmd_template}" || {
+               echo "cmd_template[${cmd_template}] does not exists"
+               return 1
+       }
+       test -e "${cnf_file}" && {
+               echo "cnf_file[${cnf_file}] already exists"
+               return 1
+       }
+
+       local sedargs=""
+       for k in $vars; do
+               v=$(eval echo "\${${k}}")
+               sedargs="${sedargs} -e 's!@@${k}@@!${v}!g'"
+       done
+
+       #echo "sedargs[${sedargs}]"
+       cat "${base_template}" "${cmd_template}" | eval sed ${sedargs} > "${cnf_file}"
+       grep '@@'  "${cnf_file}" | wc -l | grep -q '^0' || {
+               echo "invalid context in cnf_file[${cnf_file}]"
+               grep '@@' "${cnf_file}"
+               return 1
+       }
+
+       return 0
+}
+
+case "${CMD}" in
+init_ca)
+       test -e "${CA_DIR}" && {
+               echo "CA with CA_DIR[${CA_DIR}] already exists"
+               exit 1
+       }
+
+       OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+       CA_INDEX="${CA_DIR}/Private/CA-${DNS_DOMAIN}-index.txt"
+       CA_CRLNUMBER="${CA_DIR}/Private/CA-${DNS_DOMAIN}-crlnumber.txt"
+       PRIVATEKEY="${CA_DIR}/Private/CA-${DNS_DOMAIN}-private-key.pem"
+
+       ORGANIZATIONAL_UNIT_NAME="CA Administration"
+       COMMON_NAME="CA of ${DNS_DOMAIN}"
+       EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
+
+       DEFAULT_BITS="${CA_BITS}"
+       DEFAULT_DAYS="1"
+       DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+       mkdir -p "${CA_DIR}/"{,Public}
+       umask 077
+       mkdir -p "${CA_DIR}/"{,Private,NewCerts,DCs,Users}
+       umask 022
+       touch "${CA_INDEX}"
+       echo "00" > "${CA_SERIAL}"
+       echo "00" > "${CA_CRLNUMBER}"
+
+       generate_from_template \
+               "openssl-BASE-template.cnf" \
+               "openssl-CA-template.cnf" \
+               "${OPENSSLCNF}" \
+               ${DEFAULT_VARS}
+       openssl req -new -x509 -sha256 -extensions v3_ca -days "${CA_DAYS}" -keyout "${PRIVATEKEY}" -out "${CACERT_PEM}" -config "${OPENSSLCNF}"
+       openssl x509 -in "${CACERT_PEM}" -inform PEM -out "${CACERT_CER}" -outform DER
+       echo -n "Generate CRL [ENTER] to continue"
+       read
+       openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+       openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+       ls -la "${CA_DIR}"/Public/CA-*
+       echo "Please run: '${0} ${CNF} publish_crl'"
+       exit 0
+       ;;
+update_crl)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+
+       OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+       openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+       openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+       ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+       echo "Please run: '${0} ${CNF} publish_crl'"
+       exit 0
+       ;;
+publish_crl)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+
+       echo "Upload ${CACRL_CRL} to ${CRL_SSH_BASE}/"
+       rsync -a -P "${CACRL_CRL}" "${CRL_SSH_BASE}/"
+       echo "Check ${CRL_HTTP_BASE}/CA-${DNS_DOMAIN}-crl.crl"
+       exit 0
+       ;;
+create_dc)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+       #
+       #
+       # ldbsearch -H ldap://DC_DNS_NAME '(dnsHostName=DC_DNS_NAME)' distinguishedName --controls=search_options:1:1 --controls=extended_dn:1:0
+       DC_DNS_NAME="${CMDARG1}"
+       check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
+       DC_OBJECTGUID_HEX=$(echo "${CMDARG2}" | tr a-z A-Z)
+       check_arg "DC_OBJECTGUID_HEX" "${DC_OBJECTGUID_HEX}"
+
+       DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
+       test -e "${DC_DIR}" && {
+               echo "DC with DC_DIR[${DC_DIR}] already exists"
+               exit 1
+       }
+
+       NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
+       DCFILE_BASE="DC-${DC_DNS_NAME}-S${NEXT_SERIAL}"
+       OPENSSLCNF="${DC_DIR}/${DCFILE_BASE}-openssl.cnf"
+       DCKEY_PEM="${DC_DIR}/${DCFILE_BASE}-key.pem"
+       DCKEY_PRIVATE_PEM="${DC_DIR}/${DCFILE_BASE}-private-key.pem"
+       DCKEY_PRIVATE_PEM_BASE="${DCFILE_BASE}-private-key.pem"
+       DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
+       DCREQ_PEM="${DC_DIR}/${DCFILE_BASE}-req.pem"
+       DCCERT_PEM="${DC_DIR}/${DCFILE_BASE}-cert.pem"
+       DCCERT_PEM_BASE="${DCFILE_BASE}-cert.pem"
+       DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
+       DCCERT_CER="${DC_DIR}/${DCFILE_BASE}-cert.cer"
+       DCCERT_P12="${DC_DIR}/${DCFILE_BASE}-private.p12"
+
+       ORGANIZATIONAL_UNIT_NAME="Domain Controllers"
+       COMMON_NAME="${DC_DNS_NAME}"
+       EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
+
+       DEFAULT_BITS="${DC_BITS}"
+       DEFAULT_DAYS="${DC_DAYS}"
+       DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+       umask 077
+       mkdir -p "${DC_DIR}/"
+
+       generate_from_template \
+               "openssl-BASE-template.cnf" \
+               "openssl-DC-template.cnf" \
+               "${OPENSSLCNF}" \
+               ${DEFAULT_VARS} DC_DNS_NAME DC_OBJECTGUID_HEX
+
+       openssl req -new -newkey rsa -keyout "${DCKEY_PEM}" -out "${DCREQ_PEM}" -config "${OPENSSLCNF}"
+       openssl rsa -in "${DCKEY_PEM}" -inform PEM -out "${DCKEY_PRIVATE_PEM}" -outform PEM
+       openssl ca -config "${OPENSSLCNF}" -in "${DCREQ_PEM}" -out "${DCCERT_PEM}"
+       ln -s "${DCKEY_PRIVATE_PEM_BASE}" "${DCKEY_PRIVATE_PEM_LINK}"
+       ln -s "${DCCERT_PEM_BASE}" "${DCCERT_PEM_LINK}"
+       openssl x509 -in "${DCCERT_PEM}"  -inform PEM -out "${DCCERT_CER}" -outform DER
+       echo "Generate ${DCCERT_P12}"
+       openssl pkcs12 -in "${DCCERT_PEM}" -inkey "${DCKEY_PRIVATE_PEM}" -export -out "${DCCERT_P12}"
+       ls -la "${DC_DIR}"/*.*
+       exit 0
+       ;;
+revoke_dc)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+       DC_DNS_NAME="${CMDARG1}"
+       check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
+       REVOKE_REASON="${CMDARG2}"
+       check_arg "REVOKE_REASON" "${REVOKE_REASON}"
+
+       DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
+       test -e "${DC_DIR}" || {
+               echo "DC with DC_DIR[${DC_DIR}] does not exists"
+               exit 1
+       }
+
+       OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+       DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
+       DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
+
+       REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
+       REVOKE_DC_DIR="${DC_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
+
+       openssl ca -config "${OPENSSLCNF}" -revoke "${DCCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
+
+       mv "${DCKEY_PRIVATE_PEM_LINK}" "${DCKEY_PRIVATE_PEM_LINK}.revoked"
+       mv "${DCCERT_PEM_LINK}" "${DCCERT_PEM_LINK}.revoked"
+       mv "${DC_DIR}" "${REVOKE_DC_DIR}"
+       echo "${REVOKE_DC_DIR}"
+
+       openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+       openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+       ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+       echo "Please run: '${0} ${CNF} publish_crl'"
+       exit 0
+       ;;
+create_user)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+       USER_PRINCIPAL_NAME="${CMDARG1}"
+       check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
+
+       USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
+       test -e "${USER_DIR}" && {
+               echo "USER with USER_DIR[${USER_DIR}] already exists"
+               exit 1
+       }
+
+       NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
+       USERFILE_BASE="USER-${USER_PRINCIPAL_NAME}-S${NEXT_SERIAL}"
+       OPENSSLCNF="${USER_DIR}/${USERFILE_BASE}-openssl.cnf"
+       USERKEY_PEM="${USER_DIR}/${USERFILE_BASE}-key.pem"
+       USERKEY_PRIVATE_PEM="${USER_DIR}/${USERFILE_BASE}-private-key.pem"
+       USERKEY_PRIVATE_PEM_BASE="${USERFILE_BASE}-private-key.pem"
+       USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
+       USERREQ_PEM="${USER_DIR}/${USERFILE_BASE}-req.pem"
+       USERCERT_PEM="${USER_DIR}/${USERFILE_BASE}-cert.pem"
+       USERCERT_PEM_BASE="${USERFILE_BASE}-cert.pem"
+       USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
+       USERCERT_CER="${USER_DIR}/${USERFILE_BASE}-cert.cer"
+       USERCERT_P12="${USER_DIR}/${USERFILE_BASE}-private.p12"
+
+       ORGANIZATIONAL_UNIT_NAME="Users"
+       COMMON_NAME="${USER_PRINCIPAL_NAME}"
+       EMAIL_ADDRESS="${USER_PRINCIPAL_NAME}"
+
+       DEFAULT_BITS="${USER_BITS}"
+       DEFAULT_DAYS="${USER_DAYS}"
+       DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+       umask 077
+       mkdir -p "${USER_DIR}/"
+
+       generate_from_template \
+               "openssl-BASE-template.cnf" \
+               "openssl-USER-template.cnf" \
+               "${OPENSSLCNF}" \
+               ${DEFAULT_VARS} USER_PRINCIPAL_NAME
+
+       openssl req -new -newkey rsa -keyout "${USERKEY_PEM}" -out "${USERREQ_PEM}" -config "${OPENSSLCNF}"
+       openssl rsa -in "${USERKEY_PEM}" -inform PEM -out "${USERKEY_PRIVATE_PEM}" -outform PEM
+       openssl ca -config "${OPENSSLCNF}" -in "${USERREQ_PEM}" -out "${USERCERT_PEM}"
+       ln -s "${USERKEY_PRIVATE_PEM_BASE}" "${USERKEY_PRIVATE_PEM_LINK}"
+       ln -s "${USERCERT_PEM_BASE}" "${USERCERT_PEM_LINK}"
+       openssl x509 -in "${USERCERT_PEM}"  -inform PEM -out "${USERCERT_CER}" -outform DER
+       echo "Generate ${USERCERT_P12}"
+       openssl pkcs12 -in "${USERCERT_PEM}" -inkey "${USERKEY_PRIVATE_PEM}" -export -out "${USERCERT_P12}"
+       ls -la "${USER_DIR}"/*.*
+       exit 0
+       ;;
+revoke_user)
+       test -e "${CA_DIR}" || {
+               echo "CA with CA_DIR[${CA_DIR}] does not exists"
+               exit 1
+       }
+       USER_PRINCIPAL_NAME="${CMDARG1}"
+       check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
+       REVOKE_REASON="${CMDARG2}"
+       check_arg "REVOKE_REASON" "${REVOKE_REASON}"
+
+       USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
+       test -e "${USER_DIR}" || {
+               echo "USER with USER_DIR[${USER_DIR}] does not exists"
+               exit 1
+       }
+
+       OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+       USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
+       USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
+
+       REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
+       REVOKE_USER_DIR="${USER_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
+
+       openssl ca -config "${OPENSSLCNF}" -revoke "${USERCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
+
+       mv "${USERKEY_PRIVATE_PEM_LINK}" "${USERKEY_PRIVATE_PEM_LINK}.revoked"
+       mv "${USERCERT_PEM_LINK}" "${USERCERT_PEM_LINK}.revoked"
+       mv "${USER_DIR}" "${REVOKE_USER_DIR}.revoked"
+       echo "${REVOKE_USER_DIR}"
+
+       openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+       openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+       ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+       echo "Please run: '${0} ${CNF} publish_crl'"
+       exit 0
+       ;;
+usage)
+       print_usage
+       exit 1
+       ;;
+*)
+       print_usage
+       echo "ERROR: CMD[${CMD}] - unknown"
+       exit 1
+       ;;
+esac
+
+exit 1
diff --git a/selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf b/selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf
new file mode 100644 (file)
index 0000000..1f3d24e
--- /dev/null
@@ -0,0 +1,17 @@
+
+CRL_HTTP_BASE="http://www.example.com/crls"
+CRL_SSH_BASE="www.example.com:/path/to/crls"
+DNS_DOMAIN="example.com"
+
+#CA_BITS="8192"
+#DC_BITS="8192"
+#USER_BITS="8192"
+#CA_DAYS="3650"
+#CRL_DAYS="30"
+#DC_DAYS="730"
+#USER_DAYS="730"
+
+COUNTRY_NAME="US"
+STATE_NAME="ExampleState"
+LOCALITY_NAME="ExampleCity"
+ORGANIZATION_NAME="ExampleOrganization"
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf
new file mode 100644 (file)
index 0000000..ca8415b
--- /dev/null
@@ -0,0 +1,201 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = @@CRL_HTTP_BASE@@/CA-@@DNS_DOMAIN@@-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = @@CA_DIR@@         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-@@DNS_DOMAIN@@-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-@@DNS_DOMAIN@@-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-@@DNS_DOMAIN@@-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-@@DNS_DOMAIN@@-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-@@DNS_DOMAIN@@-crl.pem           # The current CRL
+crl         = $dir/Public/CA-@@DNS_DOMAIN@@-crl.crl           # The current CRL
+private_key = $dir/Private/CA-@@DNS_DOMAIN@@-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-@@DNS_DOMAIN@@.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = @@DEFAULT_DAYS@@           # how long to certify for
+default_crl_days= @@DEFAULT_CRL_DAYS@@            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = @@DEFAULT_BITS@@
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = @@COUNTRY_NAME@@
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = @@STATE_NAME@@
+
+localityName            = Locality Name (eg, city)
+localityName_default    = @@LOCALITY_NAME@@
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = @@ORGANIZATION_NAME@@
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = @@ORGANIZATIONAL_UNIT_NAME@@
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = @@COMMON_NAME@@
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = @@EMAIL_ADDRESS@@
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf
new file mode 100644 (file)
index 0000000..4c6bb4a
--- /dev/null
@@ -0,0 +1,2 @@
+[ template_x509_extensions ]
+
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf
new file mode 100644 (file)
index 0000000..0b0424d
--- /dev/null
@@ -0,0 +1,49 @@
+#[ usr_cert_mskdc ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a domain controller certificate.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+nsCertType          = server
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Domain Controller Certificate @@DC_DNS_NAME@@"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=@dc_subjalt
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for our domain controller certs
+# serverAuth - says cert can be used to identify an ssl/tls server
+# msKDC - says cert can be used to identify a Kerberos Domain Controller.
+extendedKeyUsage = clientAuth,serverAuth,msKDC
+
+[dc_subjalt]
+DNS=@@DC_DNS_NAME@@
+otherName=msADGUID;FORMAT:HEX,OCTETSTRING:@@DC_OBJECTGUID_HEX@@
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf
new file mode 100644 (file)
index 0000000..71674b9
--- /dev/null
@@ -0,0 +1,41 @@
+#[ usr_cert_scarduser ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a certificate that will be used to login from a smart card
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# For normal client use this is typical
+nsCertType = client, email
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Smart Card Login Certificate for @@USER_PRINCIPAL_NAME@@"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=email:copy,otherName:msUPN;UTF8:@@USER_PRINCIPAL_NAME@@
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for client certs
+extendedKeyUsage = clientAuth,scardLogin
+