summaryrefslogtreecommitdiffstats
path: root/security/nss/tests/chains/chains.sh
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/tests/chains/chains.sh')
-rwxr-xr-xsecurity/nss/tests/chains/chains.sh1308
1 files changed, 1308 insertions, 0 deletions
diff --git a/security/nss/tests/chains/chains.sh b/security/nss/tests/chains/chains.sh
new file mode 100755
index 000000000..4c3fa57a0
--- /dev/null
+++ b/security/nss/tests/chains/chains.sh
@@ -0,0 +1,1308 @@
+#!/bin/bash
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+########################################################################
+#
+# mozilla/security/nss/tests/cert/chains.sh
+#
+# Script to test certificate chains validity.
+#
+# needs to work on all Unix and Windows platforms
+#
+# special strings
+# ---------------
+# FIXME ... known problems, search for this string
+# NOTE .... unexpected behavior
+########################################################################
+
+########################### is_httpserv_alive ##########################
+# local shell function to exit with a fatal error if selfserver is not
+# running
+########################################################################
+is_httpserv_alive()
+{
+ if [ ! -f "${HTTPPID}" ]; then
+ echo "$SCRIPTNAME: Error - httpserv PID file ${HTTPPID} doesn't exist"
+ sleep 5
+ if [ ! -f "${HTTPPID}" ]; then
+ Exit 9 "Fatal - httpserv pid file ${HTTPPID} does not exist"
+ fi
+ fi
+
+ if [ "${OS_ARCH}" = "WINNT" ] && \
+ [ "$OS_NAME" = "CYGWIN_NT" -o "$OS_NAME" = "MINGW32_NT" ]; then
+ PID=${SHELL_HTTPPID}
+ else
+ PID=`cat ${HTTPPID}`
+ fi
+
+ echo "kill -0 ${PID} >/dev/null 2>/dev/null"
+ kill -0 ${PID} >/dev/null 2>/dev/null || Exit 10 "Fatal - httpserv process not detectable"
+
+ echo "httpserv with PID ${PID} found at `date`"
+}
+
+########################### wait_for_httpserv ##########################
+# local shell function to wait until httpserver is running and initialized
+########################################################################
+wait_for_httpserv()
+{
+ echo "trying to connect to httpserv at `date`"
+ echo "tstclnt -p ${NSS_AIA_PORT} -h ${HOSTADDR} -q -v"
+ ${BINDIR}/tstclnt -p ${NSS_AIA_PORT} -h ${HOSTADDR} -q -v
+ if [ $? -ne 0 ]; then
+ sleep 5
+ echo "retrying to connect to httpserv at `date`"
+ echo "tstclnt -p ${NSS_AIA_PORT} -h ${HOSTADDR} -q -v"
+ ${BINDIR}/tstclnt -p ${NSS_AIA_PORT} -h ${HOSTADDR} -q -v
+ if [ $? -ne 0 ]; then
+ html_failed "Waiting for Server"
+ fi
+ fi
+ is_httpserv_alive
+}
+
+########################### kill_httpserv ##############################
+# local shell function to kill the httpserver after the tests are done
+########################################################################
+kill_httpserv()
+{
+ if [ "${OS_ARCH}" = "WINNT" ] && \
+ [ "$OS_NAME" = "CYGWIN_NT" -o "$OS_NAME" = "MINGW32_NT" ]; then
+ PID=${SHELL_HTTPPID}
+ else
+ PID=`cat ${HTTPPID}`
+ fi
+
+ echo "trying to kill httpserv with PID ${PID} at `date`"
+
+ if [ "${OS_ARCH}" = "WINNT" -o "${OS_ARCH}" = "WIN95" -o "${OS_ARCH}" = "OS2" ]; then
+ echo "${KILL} ${PID}"
+ ${KILL} ${PID}
+ else
+ echo "${KILL} -USR1 ${PID}"
+ ${KILL} -USR1 ${PID}
+ fi
+ wait ${PID}
+
+ # On Linux httpserv needs up to 30 seconds to fully die and free
+ # the port. Wait until the port is free. (Bug 129701)
+ if [ "${OS_ARCH}" = "Linux" ]; then
+ echo "httpserv -b -p ${NSS_AIA_PORT} 2>/dev/null;"
+ until ${BINDIR}/httpserv -b -p ${NSS_AIA_PORT} 2>/dev/null; do
+ echo "RETRY: httpserv -b -p ${NSS_AIA_PORT} 2>/dev/null;"
+ sleep 1
+ done
+ fi
+
+ echo "httpserv with PID ${PID} killed at `date`"
+
+ rm ${HTTPPID}
+ html_detect_core "kill_httpserv core detection step"
+}
+
+########################### start_httpserv #############################
+# local shell function to start the httpserver with the parameters required
+# for this test and log information (parameters, start time)
+# also: wait until the server is up and running
+########################################################################
+start_httpserv()
+{
+ HTTP_METHOD=$1
+
+ if [ -n "$testname" ] ; then
+ echo "$SCRIPTNAME: $testname ----"
+ fi
+ echo "httpserv starting at `date`"
+ ODDIR="${HOSTDIR}/chains/OCSPD"
+ echo "httpserv -D -p ${NSS_AIA_PORT} ${SERVER_OPTIONS} \\"
+ echo " -A OCSPRoot -C ${ODDIR}/OCSPRoot.crl -A OCSPCA1 -C ${ODDIR}/OCSPCA1.crl \\"
+ echo " -A OCSPCA2 -C ${ODDIR}/OCSPCA2.crl -A OCSPCA3 -C ${ODDIR}/OCSPCA3.crl \\"
+ echo " -O ${HTTP_METHOD} -d ${ODDIR}/ServerDB/ -f ${ODDIR}/ServerDB/dbpasswd \\"
+ echo " -i ${HTTPPID} $verbose &"
+ ${PROFTOOL} ${BINDIR}/httpserv -D -p ${NSS_AIA_PORT} ${SERVER_OPTIONS} \
+ -A OCSPRoot -C ${ODDIR}/OCSPRoot.crl -A OCSPCA1 -C ${ODDIR}/OCSPCA1.crl \
+ -A OCSPCA2 -C ${ODDIR}/OCSPCA2.crl -A OCSPCA3 -C ${ODDIR}/OCSPCA3.crl \
+ -O ${HTTP_METHOD} -d ${ODDIR}/ServerDB/ -f ${ODDIR}/ServerDB/dbpasswd \
+ -i ${HTTPPID} $verbose &
+ RET=$?
+
+ # The PID $! returned by the MKS or Cygwin shell is not the PID of
+ # the real background process, but rather the PID of a helper
+ # process (sh.exe). MKS's kill command has a bug: invoking kill
+ # on the helper process does not terminate the real background
+ # process. Our workaround has been to have httpserv save its PID
+ # in the ${HTTPPID} file and "kill" that PID instead. But this
+ # doesn't work under Cygwin; its kill command doesn't recognize
+ # the PID of the real background process, but it does work on the
+ # PID of the helper process. So we save the value of $! in the
+ # SHELL_HTTPPID variable, and use it instead of the ${HTTPPID}
+ # file under Cygwin. (In fact, this should work in any shell
+ # other than the MKS shell.)
+ SHELL_HTTPPID=$!
+ wait_for_httpserv
+
+ if [ "${OS_ARCH}" = "WINNT" ] && \
+ [ "$OS_NAME" = "CYGWIN_NT" -o "$OS_NAME" = "MINGW32_NT" ]; then
+ PID=${SHELL_HTTPPID}
+ else
+ PID=`cat ${HTTPPID}`
+ fi
+
+ echo "httpserv with PID ${PID} started at `date`"
+}
+
+############################# chains_init ##############################
+# local shell function to initialize this script
+########################################################################
+chains_init()
+{
+ if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for
+ CLEANUP="${SCRIPTNAME}" # cleaning this script will do it
+ fi
+ if [ -z "${INIT_SOURCED}" ] ; then
+ cd ../common
+ . ./init.sh
+ fi
+
+ SCRIPTNAME="chains.sh"
+
+ CHAINS_DIR="${HOSTDIR}/chains"
+ mkdir -p ${CHAINS_DIR}
+ cd ${CHAINS_DIR}
+
+ CHAINS_SCENARIOS="${QADIR}/chains/scenarios/scenarios"
+
+ CERT_SN_CNT=$(date '+%m%d%H%M%S' | sed "s/^0*//")
+ CERT_SN_FIX=$(expr ${CERT_SN_CNT} - 1000)
+
+ PK7_NONCE=${CERT_SN_CNT}
+ SCEN_CNT=${CERT_SN_CNT}
+
+ AIA_FILES="${HOSTDIR}/aiafiles"
+
+ CU_DATA=${HOSTDIR}/cu_data
+ CRL_DATA=${HOSTDIR}/crl_data
+
+ DEFAULT_AIA_BASE_PORT=$(expr ${PORT:-8631} + 10)
+ NSS_AIA_PORT=${NSS_AIA_PORT:-$DEFAULT_AIA_BASE_PORT}
+ DEFAULT_UNUSED_PORT=$(expr ${PORT:-8631} + 11)
+ NSS_UNUSED_PORT=${NSS_UNUSED_PORT:-$DEFAULT_UNUSED_PORT}
+ NSS_AIA_HTTP=${NSS_AIA_HTTP:-"http://${HOSTADDR}:${NSS_AIA_PORT}"}
+ NSS_AIA_PATH=${NSS_AIA_PATH:-$HOSTDIR/aiahttp}
+ NSS_AIA_OCSP=${NSS_AIA_OCSP:-$NSS_AIA_HTTP/ocsp}
+ NSS_OCSP_UNUSED=${NSS_AIA_OCSP_UNUSED:-"http://${HOSTADDR}:${NSS_UNUSED_PORT}"}
+
+ html_head "Certificate Chains Tests"
+}
+
+chains_run_httpserv()
+{
+ HTTP_METHOD=$1
+
+ if [ -n "${NSS_AIA_PATH}" ]; then
+ HTTPPID=${NSS_AIA_PATH}/http_pid.$$
+ mkdir -p "${NSS_AIA_PATH}"
+ SAVEPWD=`pwd`
+ cd "${NSS_AIA_PATH}"
+ # Start_httpserv sets environment variables, which are required for
+ # correct cleanup. (Running it in a subshell doesn't work, the
+ # value of $SHELL_HTTPPID wouldn't arrive in this scope.)
+ start_httpserv ${HTTP_METHOD}
+ cd "${SAVEPWD}"
+ fi
+}
+
+chains_stop_httpserv()
+{
+ if [ -n "${NSS_AIA_PATH}" ]; then
+ kill_httpserv
+ fi
+}
+
+############################ chains_cleanup ############################
+# local shell function to finish this script (no exit since it might be
+# sourced)
+########################################################################
+chains_cleanup()
+{
+ html "</TABLE><BR>"
+ cd ${QADIR}
+ . common/cleanup.sh
+}
+
+############################ print_cu_data #############################
+# local shell function to print certutil input data
+########################################################################
+print_cu_data()
+{
+ echo "=== Certutil input data ==="
+ cat ${CU_DATA}
+ echo "==="
+}
+
+set_cert_sn()
+{
+ if [ -z "${SERIAL}" ]; then
+ CERT_SN_CNT=$(expr ${CERT_SN_CNT} + 1)
+ CERT_SN=${CERT_SN_CNT}
+ else
+ echo ${SERIAL} | cut -b 1 | grep '+' > /dev/null
+ if [ $? -eq 0 ]; then
+ CERT_SN=$(echo ${SERIAL} | cut -b 2-)
+ CERT_SN=$(expr ${CERT_SN_FIX} + ${CERT_SN})
+ else
+ CERT_SN=${SERIAL}
+ fi
+ fi
+}
+
+############################# create_db ################################
+# local shell function to create certificate database
+########################################################################
+create_db()
+{
+ DB=$1
+
+ [ -d "${DB}" ] && rm -rf ${DB}
+ mkdir -p ${DB}
+
+ echo "${DB}passwd" > ${DB}/dbpasswd
+
+ TESTNAME="Creating DB ${DB}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -N -d ${DB} -f ${DB}/dbpasswd"
+ ${BINDIR}/certutil -N -d ${DB} -f ${DB}/dbpasswd
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+########################### create_root_ca #############################
+# local shell function to generate self-signed root certificate
+########################################################################
+create_root_ca()
+{
+ ENTITY=$1
+ ENTITY_DB=${ENTITY}DB
+
+ set_cert_sn
+ date >> ${NOISE_FILE} 2>&1
+
+ CTYPE_OPT=
+ if [ -n "${CTYPE}" ]; then
+ CTYPE_OPT="-k ${CTYPE}"
+ fi
+
+ echo "5
+6
+9
+n
+y
+-1
+n
+5
+6
+7
+9
+n
+" > ${CU_DATA}
+
+ TESTNAME="Creating Root CA ${ENTITY}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -s \"CN=${ENTITY} ROOT CA, O=${ENTITY}, C=US\" -S -n ${ENTITY} ${CTYPE_OPT} -t CTu,CTu,CTu -v 600 -x -d ${ENTITY_DB} -1 -2 -5 -f ${ENTITY_DB}/dbpasswd -z ${NOISE_FILE} -m ${CERT_SN} < ${CU_DATA}"
+ print_cu_data
+ ${BINDIR}/certutil -s "CN=${ENTITY} ROOT CA, O=${ENTITY}, C=US" -S -n ${ENTITY} ${CTYPE_OPT} -t CTu,CTu,CTu -v 600 -x -d ${ENTITY_DB} -1 -2 -5 -f ${ENTITY_DB}/dbpasswd -z ${NOISE_FILE} -m ${CERT_SN} < ${CU_DATA}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+
+ TESTNAME="Exporting Root CA ${ENTITY}.der"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -L -d ${ENTITY_DB} -r -n ${ENTITY} -o ${ENTITY}.der"
+ ${BINDIR}/certutil -L -d ${ENTITY_DB} -r -n ${ENTITY} -o ${ENTITY}.der
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+########################### create_cert_req ############################
+# local shell function to generate certificate sign request
+########################################################################
+create_cert_req()
+{
+ ENTITY=$1
+ TYPE=$2
+
+ ENTITY_DB=${ENTITY}DB
+
+ REQ=${ENTITY}Req.der
+
+ date >> ${NOISE_FILE} 2>&1
+
+ CTYPE_OPT=
+ if [ -n "${CTYPE}" ]; then
+ CTYPE_OPT="-k ${CTYPE}"
+ fi
+
+ CA_FLAG=
+ EXT_DATA=
+ OPTIONS=
+
+ if [ "${TYPE}" != "EE" ]; then
+ CA_FLAG="-2"
+ EXT_DATA="y
+-1
+y
+"
+ fi
+
+ process_crldp
+
+ echo "${EXT_DATA}" > ${CU_DATA}
+
+ TESTNAME="Creating ${TYPE} certifiate request ${REQ}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -s \"CN=${ENTITY} ${TYPE}, O=${ENTITY}, C=US\" ${CTYPE_OPT} -R ${CA_FLAG} -d ${ENTITY_DB} -f ${ENTITY_DB}/dbpasswd -z ${NOISE_FILE} -o ${REQ} ${OPTIONS} < ${CU_DATA}"
+ print_cu_data
+ ${BINDIR}/certutil -s "CN=${ENTITY} ${TYPE}, O=${ENTITY}, C=US" ${CTYPE_OPT} -R ${CA_FLAG} -d ${ENTITY_DB} -f ${ENTITY_DB}/dbpasswd -z ${NOISE_FILE} -o ${REQ} ${OPTIONS} < ${CU_DATA}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+############################ create_entity #############################
+# local shell function to create certificate chain entity
+########################################################################
+create_entity()
+{
+ ENTITY=$1
+ TYPE=$2
+
+ if [ -z "${ENTITY}" ]; then
+ echo "Configuration error: Unnamed entity"
+ exit 1
+ fi
+
+ DB=${ENTITY}DB
+ ENTITY_DB=${ENTITY}DB
+
+ case "${TYPE}" in
+ "Root")
+ create_db "${DB}"
+ create_root_ca "${ENTITY}"
+ ;;
+ "Intermediate" | "Bridge" | "EE")
+ create_db "${DB}"
+ create_cert_req "${ENTITY}" "${TYPE}"
+ ;;
+ "*")
+ echo "Configuration error: Unknown type ${TYPE}"
+ exit 1
+ ;;
+ esac
+}
+
+########################################################################
+# List of global variables related to certificate extensions processing:
+#
+# Generated by process_extensions and functions called from it:
+# OPTIONS - list of command line policy extensions
+# DATA - list of inpud data related to policy extensions
+#
+# Generated by parse_config:
+# POLICY - list of certificate policies
+# MAPPING - list of policy mappings
+# INHIBIT - inhibit flag
+# AIA - AIA list
+########################################################################
+
+############################ process_policy ############################
+# local shell function to process policy extension parameters and
+# generate input for certutil
+########################################################################
+process_policy()
+{
+ if [ -n "${POLICY}" ]; then
+ OPTIONS="${OPTIONS} --extCP"
+
+ NEXT=
+ for ITEM in ${POLICY}; do
+ if [ -n "${NEXT}" ]; then
+ DATA="${DATA}y
+"
+ fi
+
+ NEXT=1
+ DATA="${DATA}${ITEM}
+1
+
+n
+"
+ done
+
+ DATA="${DATA}n
+n
+"
+ fi
+}
+
+########################### process_mapping ############################
+# local shell function to process policy mapping parameters and
+# generate input for certutil
+########################################################################
+process_mapping()
+{
+ if [ -n "${MAPPING}" ]; then
+ OPTIONS="${OPTIONS} --extPM"
+
+ NEXT=
+ for ITEM in ${MAPPING}; do
+ if [ -n "${NEXT}" ]; then
+ DATA="${DATA}y
+"
+ fi
+
+ NEXT=1
+ IDP=`echo ${ITEM} | cut -d: -f1`
+ SDP=`echo ${ITEM} | cut -d: -f2`
+ DATA="${DATA}${IDP}
+${SDP}
+"
+ done
+
+ DATA="${DATA}n
+n
+"
+ fi
+}
+
+########################### process_inhibit#############################
+# local shell function to process inhibit extension and generate input
+# for certutil
+########################################################################
+process_inhibit()
+{
+ if [ -n "${INHIBIT}" ]; then
+ OPTIONS="${OPTIONS} --extIA"
+
+ DATA="${DATA}${INHIBIT}
+n
+"
+ fi
+}
+
+############################# process_aia ##############################
+# local shell function to process AIA extension parameters and
+# generate input for certutil
+########################################################################
+process_aia()
+{
+ if [ -n "${AIA}" ]; then
+ OPTIONS="${OPTIONS} --extAIA"
+
+ DATA="${DATA}1
+"
+
+ for ITEM in ${AIA}; do
+ PK7_NONCE=`expr $PK7_NONCE + 1`
+
+ echo ${ITEM} | grep ":" > /dev/null
+ if [ $? -eq 0 ]; then
+ CERT_NICK=`echo ${ITEM} | cut -d: -f1`
+ CERT_ISSUER=`echo ${ITEM} | cut -d: -f2`
+ CERT_LOCAL="${CERT_NICK}${CERT_ISSUER}.der"
+ CERT_PUBLIC="${HOST}-$$-${CERT_NICK}${CERT_ISSUER}-${PK7_NONCE}.der"
+ else
+ CERT_LOCAL="${ITEM}.p7"
+ CERT_PUBLIC="${HOST}-$$-${ITEM}-${PK7_NONCE}.p7"
+ fi
+
+ DATA="${DATA}7
+${NSS_AIA_HTTP}/${CERT_PUBLIC}
+"
+
+ if [ -n "${NSS_AIA_PATH}" ]; then
+ cp ${CERT_LOCAL} ${NSS_AIA_PATH}/${CERT_PUBLIC} 2> /dev/null
+ chmod a+r ${NSS_AIA_PATH}/${CERT_PUBLIC}
+ echo ${NSS_AIA_PATH}/${CERT_PUBLIC} >> ${AIA_FILES}
+ fi
+ done
+
+ DATA="${DATA}0
+n
+n"
+ fi
+}
+
+process_ocsp()
+{
+ if [ -n "${OCSP}" ]; then
+ OPTIONS="${OPTIONS} --extAIA"
+
+ if [ "${OCSP}" = "offline" ]; then
+ MY_OCSP_URL=${NSS_OCSP_UNUSED}
+ else
+ MY_OCSP_URL=${NSS_AIA_OCSP}
+ fi
+
+ DATA="${DATA}2
+7
+${MY_OCSP_URL}
+0
+n
+n
+"
+ fi
+}
+
+process_crldp()
+{
+ if [ -n "${CRLDP}" ]; then
+ OPTIONS="${OPTIONS} -4"
+
+ EXT_DATA="${EXT_DATA}1
+"
+
+ for ITEM in ${CRLDP}; do
+ CRL_PUBLIC="${HOST}-$$-${ITEM}-${SCEN_CNT}.crl"
+
+ EXT_DATA="${EXT_DATA}7
+${NSS_AIA_HTTP}/${CRL_PUBLIC}
+"
+ done
+
+ EXT_DATA="${EXT_DATA}-1
+-1
+-1
+n
+n
+"
+ fi
+}
+
+process_ku_ns_eku()
+{
+ if [ -n "${EXT_KU}" ]; then
+ OPTIONS="${OPTIONS} --keyUsage ${EXT_KU}"
+ fi
+ if [ -n "${EXT_NS}" ]; then
+ EXT_NS_KEY=$(echo ${EXT_NS} | cut -d: -f1)
+ EXT_NS_CODE=$(echo ${EXT_NS} | cut -d: -f2)
+
+ OPTIONS="${OPTIONS} --nsCertType ${EXT_NS_KEY}"
+ DATA="${DATA}${EXT_NS_CODE}
+-1
+n
+"
+ fi
+ if [ -n "${EXT_EKU}" ]; then
+ OPTIONS="${OPTIONS} --extKeyUsage ${EXT_EKU}"
+ fi
+}
+
+copy_crl()
+
+{
+ if [ -z "${NSS_AIA_PATH}" ]; then
+ return;
+ fi
+
+ CRL_LOCAL="${COPYCRL}.crl"
+ CRL_PUBLIC="${HOST}-$$-${COPYCRL}-${SCEN_CNT}.crl"
+
+ cp ${CRL_LOCAL} ${NSS_AIA_PATH}/${CRL_PUBLIC} 2> /dev/null
+ chmod a+r ${NSS_AIA_PATH}/${CRL_PUBLIC}
+ echo ${NSS_AIA_PATH}/${CRL_PUBLIC} >> ${AIA_FILES}
+}
+
+########################## process_extension ###########################
+# local shell function to process entity extension parameters and
+# generate input for certutil
+########################################################################
+process_extensions()
+{
+ OPTIONS=
+ DATA=
+
+ process_policy
+ process_mapping
+ process_inhibit
+ process_aia
+ process_ocsp
+ process_ku_ns_eku
+}
+
+############################## sign_cert ###############################
+# local shell function to sign certificate sign reuqest
+########################################################################
+sign_cert()
+{
+ ENTITY=$1
+ ISSUER=$2
+ TYPE=$3
+
+ [ -z "${ISSUER}" ] && return
+
+ ENTITY_DB=${ENTITY}DB
+ ISSUER_DB=${ISSUER}DB
+ REQ=${ENTITY}Req.der
+ CERT=${ENTITY}${ISSUER}.der
+
+ set_cert_sn
+
+ EMAIL_OPT=
+ if [ "${TYPE}" = "Bridge" ]; then
+ EMAIL_OPT="-7 ${ENTITY}@${ISSUER}"
+
+ [ -n "${EMAILS}" ] && EMAILS="${EMAILS},"
+ EMAILS="${EMAILS}${ENTITY}@${ISSUER}"
+ fi
+
+ process_extensions
+
+ echo "${DATA}" > ${CU_DATA}
+
+ TESTNAME="Creating certficate ${CERT} signed by ${ISSUER}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -C -c ${ISSUER} -v 60 -d ${ISSUER_DB} -i ${REQ} -o ${CERT} -f ${ISSUER_DB}/dbpasswd -m ${CERT_SN} ${EMAIL_OPT} ${OPTIONS} < ${CU_DATA}"
+ print_cu_data
+ ${BINDIR}/certutil -C -c ${ISSUER} -v 60 -d ${ISSUER_DB} -i ${REQ} -o ${CERT} -f ${ISSUER_DB}/dbpasswd -m ${CERT_SN} ${EMAIL_OPT} ${OPTIONS} < ${CU_DATA}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+
+ TESTNAME="Importing certificate ${CERT} to ${ENTITY_DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -A -n ${ENTITY} -t u,u,u -d ${ENTITY_DB} -f ${ENTITY_DB}/dbpasswd -i ${CERT}"
+ ${BINDIR}/certutil -A -n ${ENTITY} -t u,u,u -d ${ENTITY_DB} -f ${ENTITY_DB}/dbpasswd -i ${CERT}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+############################# create_pkcs7##############################
+# local shell function to package bridge certificates into pkcs7
+# package
+########################################################################
+create_pkcs7()
+{
+ ENTITY=$1
+ ENTITY_DB=${ENTITY}DB
+
+ TESTNAME="Generating PKCS7 package from ${ENTITY_DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "cmsutil -O -r \"${EMAILS}\" -d ${ENTITY_DB} > ${ENTITY}.p7"
+ ${BINDIR}/cmsutil -O -r "${EMAILS}" -d ${ENTITY_DB} > ${ENTITY}.p7
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+############################# import_key ###############################
+# local shell function to import private key + cert into database
+########################################################################
+import_key()
+{
+ KEY_NAME=$1.p12
+ DB=$2
+
+ KEY_FILE=../OCSPD/${KEY_NAME}
+
+ TESTNAME="Importing p12 key ${KEY_NAME} to ${DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "${BINDIR}/pk12util -d ${DB} -i ${KEY_FILE} -k ${DB}/dbpasswd -W nssnss"
+ ${BINDIR}/pk12util -d ${DB} -i ${KEY_FILE} -k ${DB}/dbpasswd -W nssnss
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+export_key()
+{
+ KEY_NAME=$1.p12
+ DB=$2
+
+ TESTNAME="Exporting $1 as ${KEY_NAME} from ${DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "${BINDIR}/pk12util -d ${DB} -o ${KEY_NAME} -n $1 -k ${DB}/dbpasswd -W nssnss"
+ ${BINDIR}/pk12util -d ${DB} -o ${KEY_NAME} -n $1 -k ${DB}/dbpasswd -W nssnss
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+############################# import_cert ##############################
+# local shell function to import certificate into database
+########################################################################
+import_cert()
+{
+ IMPORT=$1
+ DB=$2
+
+ CERT_NICK=`echo ${IMPORT} | cut -d: -f1`
+ CERT_ISSUER=`echo ${IMPORT} | cut -d: -f2`
+ CERT_TRUST=`echo ${IMPORT} | cut -d: -f3`
+
+ if [ "${CERT_ISSUER}" = "x" ]; then
+ CERT_ISSUER=
+ CERT=${CERT_NICK}.cert
+ CERT_FILE="${QADIR}/libpkix/certs/${CERT}"
+ elif [ "${CERT_ISSUER}" = "d" ]; then
+ CERT_ISSUER=
+ CERT=${CERT_NICK}.der
+ CERT_FILE="../OCSPD/${CERT}"
+ else
+ CERT=${CERT_NICK}${CERT_ISSUER}.der
+ CERT_FILE=${CERT}
+ fi
+
+ IS_ASCII=`grep -c -- "-----BEGIN CERTIFICATE-----" ${CERT_FILE}`
+
+ ASCII_OPT=
+ if [ "${IS_ASCII}" -gt 0 ]; then
+ ASCII_OPT="-a"
+ fi
+
+ TESTNAME="Importing certificate ${CERT} to ${DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "certutil -A -n ${CERT_NICK} ${ASCII_OPT} -t \"${CERT_TRUST}\" -d ${DB} -f ${DB}/dbpasswd -i ${CERT_FILE}"
+ ${BINDIR}/certutil -A -n ${CERT_NICK} ${ASCII_OPT} -t "${CERT_TRUST}" -d ${DB} -f ${DB}/dbpasswd -i ${CERT_FILE}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+import_crl()
+{
+ IMPORT=$1
+ DB=$2
+
+ CRL_NICK=`echo ${IMPORT} | cut -d: -f1`
+ CRL_FILE=${CRL_NICK}.crl
+
+ if [ ! -f "${CRL_FILE}" ]; then
+ return
+ fi
+
+ TESTNAME="Importing CRL ${CRL_FILE} to ${DB} database"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "crlutil -I -d ${DB} -f ${DB}/dbpasswd -i ${CRL_FILE}"
+ ${BINDIR}/crlutil -I -d ${DB} -f ${DB}/dbpasswd -i ${CRL_FILE}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+create_crl()
+{
+ ISSUER=$1
+ ISSUER_DB=${ISSUER}DB
+
+ CRL=${ISSUER}.crl
+
+ DATE=$(date -u '+%Y%m%d%H%M%SZ')
+ DATE_LAST="${DATE}"
+
+ UPDATE=$(expr $(date -u '+%Y') + 1)$(date -u '+%m%d%H%M%SZ')
+
+ echo "update=${DATE}" > ${CRL_DATA}
+ echo "nextupdate=${UPDATE}" >> ${CRL_DATA}
+
+ TESTNAME="Create CRL for ${ISSUER_DB}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "crlutil -G -d ${ISSUER_DB} -n ${ISSUER} -f ${ISSUER_DB}/dbpasswd -o ${CRL}"
+ echo "=== Crlutil input data ==="
+ cat ${CRL_DATA}
+ echo "==="
+ ${BINDIR}/crlutil -G -d ${ISSUER_DB} -n ${ISSUER} -f ${ISSUER_DB}/dbpasswd -o ${CRL} < ${CRL_DATA}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+revoke_cert()
+{
+ ISSUER=$1
+ ISSUER_DB=${ISSUER}DB
+
+ CRL=${ISSUER}.crl
+
+ set_cert_sn
+
+ DATE=$(date -u '+%Y%m%d%H%M%SZ')
+ while [ "${DATE}" = "${DATE_LAST}" ]; do
+ sleep 1
+ DATE=$(date -u '+%Y%m%d%H%M%SZ')
+ done
+ DATE_LAST="${DATE}"
+
+ echo "update=${DATE}" > ${CRL_DATA}
+ echo "addcert ${CERT_SN} ${DATE}" >> ${CRL_DATA}
+
+ TESTNAME="Revoking certificate with SN ${CERT_SN} issued by ${ISSUER}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "crlutil -M -d ${ISSUER_DB} -n ${ISSUER} -f ${ISSUER_DB}/dbpasswd -o ${CRL}"
+ echo "=== Crlutil input data ==="
+ cat ${CRL_DATA}
+ echo "==="
+ ${BINDIR}/crlutil -M -d ${ISSUER_DB} -n ${ISSUER} -f ${ISSUER_DB}/dbpasswd -o ${CRL} < ${CRL_DATA}
+ html_msg $? 0 "${SCENARIO}${TESTNAME}"
+}
+
+########################################################################
+# List of global variables related to certificate verification:
+#
+# Generated by parse_config:
+# DB - DB used for testing
+# FETCH - fetch flag (used with AIA extension)
+# POLICY - list of policies
+# TRUST - trust anchor
+# TRUST_AND_DB - Examine both trust anchors and the cert db for trust
+# VERIFY - list of certificates to use as vfychain parameters
+# EXP_RESULT - expected result
+# REV_OPTS - revocation options
+########################################################################
+
+############################# verify_cert ##############################
+# local shell function to verify certificate validity
+########################################################################
+verify_cert()
+{
+ ENGINE=$1
+
+ DB_OPT=
+ FETCH_OPT=
+ POLICY_OPT=
+ TRUST_OPT=
+ VFY_CERTS=
+ VFY_LIST=
+ TRUST_AND_DB_OPT=
+
+ if [ -n "${DB}" ]; then
+ DB_OPT="-d ${DB}"
+ fi
+
+ if [ -n "${FETCH}" ]; then
+ FETCH_OPT="-f"
+ if [ -z "${NSS_AIA_HTTP}" ]; then
+ echo "${SCRIPTNAME} Skipping test using AIA fetching, NSS_AIA_HTTP not defined"
+ return
+ fi
+ fi
+
+ if [ -n "${TRUST_AND_DB}" ]; then
+ TRUST_AND_DB_OPT="-T"
+ fi
+
+ for ITEM in ${POLICY}; do
+ POLICY_OPT="${POLICY_OPT} -o ${ITEM}"
+ done
+
+ for ITEM in ${TRUST}; do
+ echo ${ITEM} | grep ":" > /dev/null
+ if [ $? -eq 0 ]; then
+ CERT_NICK=`echo ${ITEM} | cut -d: -f1`
+ CERT_ISSUER=`echo ${ITEM} | cut -d: -f2`
+ CERT=${CERT_NICK}${CERT_ISSUER}.der
+
+ TRUST_OPT="${TRUST_OPT} -t ${CERT}"
+ else
+ TRUST_OPT="${TRUST_OPT} -t ${ITEM}"
+ fi
+ done
+
+ for ITEM in ${VERIFY}; do
+ CERT_NICK=`echo ${ITEM} | cut -d: -f1`
+ CERT_ISSUER=`echo ${ITEM} | cut -d: -f2`
+
+ if [ "${CERT_ISSUER}" = "x" ]; then
+ CERT="${QADIR}/libpkix/certs/${CERT_NICK}.cert"
+ VFY_CERTS="${VFY_CERTS} ${CERT}"
+ VFY_LIST="${VFY_LIST} ${CERT_NICK}.cert"
+ elif [ "${CERT_ISSUER}" = "d" ]; then
+ CERT="../OCSPD/${CERT_NICK}.der"
+ VFY_CERTS="${VFY_CERTS} ${CERT}"
+ VFY_LIST="${VFY_LIST} ${CERT_NICK}.cert"
+ else
+ CERT=${CERT_NICK}${CERT_ISSUER}.der
+ VFY_CERTS="${VFY_CERTS} ${CERT}"
+ VFY_LIST="${VFY_LIST} ${CERT}"
+ fi
+ done
+
+ VFY_OPTS_TNAME="${DB_OPT} ${ENGINE} ${TRUST_AND_DB_OPT} ${REV_OPTS} ${FETCH_OPT} ${USAGE_OPT} ${POLICY_OPT} ${TRUST_OPT}"
+ VFY_OPTS_ALL="${DB_OPT} ${ENGINE} -vv ${TRUST_AND_DB_OPT} ${REV_OPTS} ${FETCH_OPT} ${USAGE_OPT} ${POLICY_OPT} ${VFY_CERTS} ${TRUST_OPT}"
+
+ TESTNAME="Verifying certificate(s) ${VFY_LIST} with flags ${VFY_OPTS_TNAME}"
+ echo "${SCRIPTNAME}: ${TESTNAME}"
+ echo "vfychain ${VFY_OPTS_ALL}"
+
+ if [ -z "${MEMLEAK_DBG}" ]; then
+ VFY_OUT=$(${BINDIR}/vfychain ${VFY_OPTS_ALL} 2>&1)
+ RESULT=$?
+ echo "${VFY_OUT}"
+ else
+ VFY_OUT=$(${RUN_COMMAND_DBG} ${BINDIR}/vfychain ${VFY_OPTS_ALL} 2>> ${LOGFILE})
+ RESULT=$?
+ echo "${VFY_OUT}"
+ fi
+
+ echo "${VFY_OUT}" | grep "ERROR -5990: I/O operation timed out" > /dev/null
+ E5990=$?
+ echo "${VFY_OUT}" | grep "ERROR -8030: Server returned bad HTTP response" > /dev/null
+ E8030=$?
+
+ if [ $E5990 -eq 0 -o $E8030 -eq 0 ]; then
+ echo "Result of this test is not valid due to network time out."
+ html_unknown "${SCENARIO}${TESTNAME}"
+ return
+ fi
+
+ echo "Returned value is ${RESULT}, expected result is ${EXP_RESULT}"
+
+ if [ "${EXP_RESULT}" = "pass" -a ${RESULT} -eq 0 ]; then
+ html_passed "${SCENARIO}${TESTNAME}"
+ elif [ "${EXP_RESULT}" = "fail" -a ${RESULT} -ne 0 ]; then
+ html_passed "${SCENARIO}${TESTNAME}"
+ else
+ html_failed "${SCENARIO}${TESTNAME}"
+ fi
+}
+
+check_ocsp()
+{
+ OCSP_CERT=$1
+
+ CERT_NICK=`echo ${OCSP_CERT} | cut -d: -f1`
+ CERT_ISSUER=`echo ${OCSP_CERT} | cut -d: -f2`
+
+ if [ "${CERT_ISSUER}" = "x" ]; then
+ CERT_ISSUER=
+ CERT=${CERT_NICK}.cert
+ CERT_FILE="${QADIR}/libpkix/certs/${CERT}"
+ elif [ "${CERT_ISSUER}" = "d" ]; then
+ CERT_ISSUER=
+ CERT=${CERT_NICK}.der
+ CERT_FILE="../OCSPD/${CERT}"
+ else
+ CERT=${CERT_NICK}${CERT_ISSUER}.der
+ CERT_FILE=${CERT}
+ fi
+
+ # sample line:
+ # URI: "http://ocsp.server:2601"
+ OCSP_HOST=$(${BINDIR}/pp -w -t certificate -i ${CERT_FILE} | grep URI | sed "s/.*:\/\///" | sed "s/:.*//")
+ OCSP_PORT=$(${BINDIR}/pp -w -t certificate -i ${CERT_FILE} | grep URI | sed "s/^.*:.*:\/\/.*:\([0-9]*\).*$/\1/")
+
+ echo "tstclnt -h ${OCSP_HOST} -p ${OCSP_PORT} -q -t 20"
+ tstclnt -h ${OCSP_HOST} -p ${OCSP_PORT} -q -t 20
+ return $?
+}
+
+############################ parse_result ##############################
+# local shell function to process expected result value
+# this function was created for case that expected result depends on
+# some conditions - in our case type of cert DB
+#
+# default results are pass and fail
+# this function added parsable values in format:
+# type1:value1 type2:value2 .... typex:valuex
+#
+# allowed types are dbm, sql, all (all means all other cases)
+# allowed values are pass and fail
+#
+# if this format is not used, EXP_RESULT will stay unchanged (this also
+# covers pass and fail states)
+########################################################################
+parse_result()
+{
+ for RES in ${EXP_RESULT}
+ do
+ RESTYPE=$(echo ${RES} | cut -d: -f1)
+ RESSTAT=$(echo ${RES} | cut -d: -f2)
+
+ if [ "${RESTYPE}" = "${NSS_DEFAULT_DB_TYPE}" -o "${RESTYPE}" = "all" ]; then
+ EXP_RESULT=${RESSTAT}
+ break
+ fi
+ done
+}
+
+############################ parse_config ##############################
+# local shell function to parse and process file containing certificate
+# chain configuration and list of tests
+########################################################################
+parse_config()
+{
+ SCENARIO=
+ LOGNAME=
+
+ while read KEY VALUE
+ do
+ case "${KEY}" in
+ "entity")
+ ENTITY="${VALUE}"
+ TYPE=
+ ISSUER=
+ CTYPE=
+ POLICY=
+ MAPPING=
+ INHIBIT=
+ AIA=
+ CRLDP=
+ OCSP=
+ DB=
+ EMAILS=
+ EXT_KU=
+ EXT_NS=
+ EXT_EKU=
+ SERIAL=
+ EXPORT_KEY=
+ ;;
+ "type")
+ TYPE="${VALUE}"
+ ;;
+ "issuer")
+ if [ -n "${ISSUER}" ]; then
+ if [ -z "${DB}" ]; then
+ create_entity "${ENTITY}" "${TYPE}"
+ fi
+ sign_cert "${ENTITY}" "${ISSUER}" "${TYPE}"
+ fi
+
+ ISSUER="${VALUE}"
+ POLICY=
+ MAPPING=
+ INHIBIT=
+ AIA=
+ EXT_KU=
+ EXT_NS=
+ EXT_EKU=
+ ;;
+ "ctype")
+ CTYPE="${VALUE}"
+ ;;
+ "policy")
+ POLICY="${POLICY} ${VALUE}"
+ ;;
+ "mapping")
+ MAPPING="${MAPPING} ${VALUE}"
+ ;;
+ "inhibit")
+ INHIBIT="${VALUE}"
+ ;;
+ "aia")
+ AIA="${AIA} ${VALUE}"
+ ;;
+ "crldp")
+ CRLDP="${CRLDP} ${VALUE}"
+ ;;
+ "ocsp")
+ OCSP="${VALUE}"
+ ;;
+ "db")
+ DB="${VALUE}DB"
+ create_db "${DB}"
+ ;;
+ "import")
+ IMPORT="${VALUE}"
+ import_cert "${IMPORT}" "${DB}"
+ import_crl "${IMPORT}" "${DB}"
+ ;;
+ "import_key")
+ IMPORT="${VALUE}"
+ import_key "${IMPORT}" "${DB}"
+ ;;
+ "crl")
+ ISSUER="${VALUE}"
+ create_crl "${ISSUER}"
+ ;;
+ "revoke")
+ REVOKE="${VALUE}"
+ ;;
+ "serial")
+ SERIAL="${VALUE}"
+ ;;
+ "export_key")
+ EXPORT_KEY=1
+ ;;
+ "copycrl")
+ COPYCRL="${VALUE}"
+ copy_crl "${COPYCRL}"
+ ;;
+ "verify")
+ VERIFY="${VALUE}"
+ TRUST=
+ TRUST_AND_DB=
+ POLICY=
+ FETCH=
+ EXP_RESULT=
+ REV_OPTS=
+ USAGE_OPT=
+ ;;
+ "cert")
+ VERIFY="${VERIFY} ${VALUE}"
+ ;;
+ "testdb")
+ if [ -n "${VALUE}" ]; then
+ DB="${VALUE}DB"
+ else
+ DB=
+ fi
+ ;;
+ "trust")
+ TRUST="${TRUST} ${VALUE}"
+ ;;
+ "trust_and_db")
+ TRUST_AND_DB=1
+ ;;
+ "fetch")
+ FETCH=1
+ ;;
+ "result")
+ EXP_RESULT="${VALUE}"
+ parse_result
+ ;;
+ "rev_type")
+ REV_OPTS="${REV_OPTS} -g ${VALUE}"
+ ;;
+ "rev_flags")
+ REV_OPTS="${REV_OPTS} -h ${VALUE}"
+ ;;
+ "rev_mtype")
+ REV_OPTS="${REV_OPTS} -m ${VALUE}"
+ ;;
+ "rev_mflags")
+ REV_OPTS="${REV_OPTS} -s ${VALUE}"
+ ;;
+ "scenario")
+ SCENARIO="${VALUE}: "
+
+ CHAINS_DIR="${HOSTDIR}/chains/${VALUE}"
+ mkdir -p ${CHAINS_DIR}
+ cd ${CHAINS_DIR}
+
+ if [ -n "${MEMLEAK_DBG}" ]; then
+ LOGNAME="libpkix-${VALUE}"
+ LOGFILE="${LOGDIR}/${LOGNAME}"
+ fi
+
+ SCEN_CNT=$(expr ${SCEN_CNT} + 1)
+ ;;
+ "sleep")
+ sleep ${VALUE}
+ ;;
+ "break")
+ break
+ ;;
+ "check_ocsp")
+ TESTNAME="Test that OCSP server is reachable"
+ check_ocsp ${VALUE}
+ if [ $? -ne 0 ]; then
+ html_failed "$TESTNAME"
+ break;
+ else
+ html_passed "$TESTNAME"
+ fi
+ ;;
+ "ku")
+ EXT_KU="${VALUE}"
+ ;;
+ "ns")
+ EXT_NS="${VALUE}"
+ ;;
+ "eku")
+ EXT_EKU="${VALUE}"
+ ;;
+ "usage")
+ USAGE_OPT="-u ${VALUE}"
+ ;;
+ "")
+ if [ -n "${ENTITY}" ]; then
+ if [ -z "${DB}" ]; then
+ create_entity "${ENTITY}" "${TYPE}"
+ fi
+ sign_cert "${ENTITY}" "${ISSUER}" "${TYPE}"
+ if [ "${TYPE}" = "Bridge" ]; then
+ create_pkcs7 "${ENTITY}"
+ fi
+ if [ -n "${EXPORT_KEY}" ]; then
+ export_key "${ENTITY}" "${DB}"
+ fi
+ ENTITY=
+ fi
+
+ if [ -n "${VERIFY}" ] && \
+ [ -z "$NSS_DISABLE_LIBPKIX" ]; then
+ verify_cert "-pp"
+ if [ -n "${VERIFY_CLASSIC_ENGINE_TOO}" ] && \
+ [ -z "$NSS_DISABLE_LIBPKIX" ]; then
+ verify_cert ""
+ verify_cert "-p"
+ fi
+ VERIFY=
+ fi
+
+ if [ -n "${REVOKE}" ]; then
+ revoke_cert "${REVOKE}" "${DB}"
+ REVOKE=
+ fi
+ ;;
+ *)
+ if [ `echo ${KEY} | cut -b 1` != "#" ]; then
+ echo "Configuration error: Unknown keyword ${KEY}"
+ exit 1
+ fi
+ ;;
+ esac
+ done
+
+ if [ -n "${MEMLEAK_DBG}" ]; then
+ log_parse
+ html_msg $? 0 "${SCENARIO}Memory leak checking"
+ fi
+}
+
+process_scenario()
+{
+ SCENARIO_FILE=$1
+
+ > ${AIA_FILES}
+
+ parse_config < "${QADIR}/chains/scenarios/${SCENARIO_FILE}"
+
+ while read AIA_FILE
+ do
+ rm ${AIA_FILE} 2> /dev/null
+ done < ${AIA_FILES}
+ rm ${AIA_FILES}
+}
+
+# process ocspd.cfg separately
+chains_ocspd()
+{
+ process_scenario "ocspd.cfg"
+}
+
+# process ocsp.cfg separately
+chains_method()
+{
+ process_scenario "method.cfg"
+}
+
+############################# chains_main ##############################
+# local shell function to process all testing scenarios
+########################################################################
+chains_main()
+{
+ while read LINE
+ do
+ [ `echo ${LINE} | cut -b 1` != "#" ] || continue
+
+ [ ${LINE} != 'ocspd.cfg' ] || continue
+ [ ${LINE} != 'method.cfg' ] || continue
+
+ process_scenario ${LINE}
+ done < "${CHAINS_SCENARIOS}"
+}
+
+################################ main ##################################
+
+chains_init
+VERIFY_CLASSIC_ENGINE_TOO=
+chains_ocspd
+VERIFY_CLASSIC_ENGINE_TOO=1
+chains_run_httpserv get
+chains_method
+chains_stop_httpserv
+chains_run_httpserv post
+chains_method
+chains_stop_httpserv
+VERIFY_CLASSIC_ENGINE_TOO=
+chains_run_httpserv random
+chains_main
+chains_stop_httpserv
+chains_run_httpserv get-unknown
+chains_main
+chains_stop_httpserv
+chains_cleanup