#! /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/ssl/ssl.sh
#
# Script to test NSS SSL
#
# Needs to work on all Unix and Windows platforms
#
# Testing schema:
# ---------------
# all.sh ~ (main)
# | |
# +------------+------------+-----------+ ~ run_cycles
# | | | | |
# standard pkix upgradedb sharedb ~ run_cycle_*
# ... | ... ... |
# +------+------+-----> ~ run_tests
# | | | |
# ... ssl ... ~ ssl.sh
# | |
# +-------+-------+-----------------+ ~ ssl_run_tests
# | | | | |
# crl iopr policy permute(normal,fips) ~ ssl_run_test_*
# | | | | |
# +------+------+------+------+---+-+-+-+----> ~ ssl_run
# | | | | | | |
# stapling cov auth stress dtls ... ~ ssl_run_*
#
# special strings
# ---------------
# FIXME ... known problems, search for this string
# NOTE .... unexpected behavior
#
########################################################################
############################## ssl_init ################################
# local shell function to initialize this script
########################################################################
ssl_init()
{
SCRIPTNAME=ssl.sh
# sourced - $0 would point to all.sh
if [ -z
"${CLEANUP}" ] ;
then # if nobody else is responsible for
CLEANUP=
"${SCRIPTNAME}" # cleaning this script will do it
fi
if [ -z
"${INIT_SOURCED}" -o
"${INIT_SOURCED}" !=
"TRUE" ];
then
cd ../common
. ./init.sh
fi
if [ -z
"${IOPR_SSL_SOURCED}" ];
then
. ../iopr/ssl_iopr.sh
fi
if [ ! -r $CERT_LOG_FILE ];
then # we need certificates here
cd ../cert
. ./cert.sh
fi
SCRIPTNAME=ssl.sh
echo "$SCRIPTNAME: SSL tests ==============================="
grep
"SUCCESS: SSL passed" $CERT_LOG_FILE >/dev/null || {
html_head
"SSL Test failure"
Exit 8
"Fatal - cert.sh needs to pass first"
}
if [ -z
"$NSS_TEST_DISABLE_CRL" ] ;
then
grep
"SUCCESS: SSL CRL prep passed" $CERT_LOG_FILE >/dev/null || {
html_head
"SSL Test failure"
Exit 8
"Fatal - SSL of cert.sh needs to pass first"
}
fi
PORT=${PORT-8443}
# Avoid port conflicts when multiple tests are running on the same machine.
if [ -n
"$NSS_TASKCLUSTER_MAC" ];
then
cwd=$(cd $(dirname $0); pwd -P)
padd=$(
echo $cwd | cut -d
"/" -f4 | sed
's/[^0-9]//g')
PORT=$(($PORT + $padd))
fi
NSS_SSL_TESTS=${NSS_SSL_TESTS:-normal_normal}
nss_ssl_run=
"stapling signed_cert_timestamps cov auth dtls scheme exporter"
NSS_SSL_RUN=${NSS_SSL_RUN:-$nss_ssl_run}
# Test case files
SSLCOV=${QADIR}/ssl/sslcov.txt
SSLAUTH=${QADIR}/ssl/sslauth.txt
SSLSTRESS=${QADIR}/ssl/sslstress.txt
SSLPOLICY=${QADIR}/ssl/sslpolicy.txt
REQUEST_FILE=${QADIR}/ssl/sslreq.dat
#temparary files
SERVEROUTFILE=${TMP}/tests_server.$$
SERVERPID=${TMP}/tests_pid.$$
R_SERVERPID=../tests_pid.$$
TEMPFILES=
"$TMPFILES ${SERVEROUTFILE} ${SERVERPID}"
fileout=0
#FIXME, looks like all.sh tried to turn this on but actually didn't
#fileout=1
#verbose="-v" #FIXME - see where this is usefull
USER_NICKNAME=TestUser
NORM_EXT=
""
EC_SUITES=
":C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D"
EC_SUITES=
"${EC_SUITES}:C00E:C00F:C010:C011:C012:C013:C014:C023:C024:C027"
EC_SUITES=
"${EC_SUITES}:C028:C02B:C02C:C02F:C030:CCA8:CCA9:CCAA"
NON_EC_SUITES=
":0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B"
NON_EC_SUITES=
"${NON_EC_SUITES}:0084:009C:009D:009E:009F:00A2:00A3:CCAAcdeinvyz"
TLS13_SUITES=
":1301:1302:1303"
# List of cipher suites to test, including ECC cipher suites.
CIPHER_SUITES=
"-c ${EC_SUITES}${NON_EC_SUITES}"
TLS13_CIPHER_SUITES=
"-c ${TLS13_SUITES}${EC_SUITES}${NON_EC_SUITES}"
# in fips mode, turn off curve25519 until it's NIST approved
FIPS_OPTIONS=
"-I P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192"
# in non-fips mode, tstclnt may run without the db password in some
# cases, but in fips mode it's always needed
CLIENT_PW=
""
CLIENT_PW_FIPS=
"-w nss"
CLIENT_PW_NORMAL=
""
if [
"${OS_ARCH}" !=
"WINNT" ];
then
ulimit -n 1000
# make sure we have enough file descriptors
fi
cd ${CLIENTDIR}
}
########################### is_selfserv_alive ##########################
# local shell function to exit with a fatal error if selfserver is not
# running
########################################################################
is_selfserv_alive()
{
if [ ! -f
"${SERVERPID}" ];
then
echo "$SCRIPTNAME: Error - selfserv PID file ${SERVERPID} doesn't exist"
sleep 5
if [ ! -f
"${SERVERPID}" ];
then
Exit 9
"Fatal - selfserv pid file ${SERVERPID} does not exist"
fi
fi
if [
"${OS_ARCH}" =
"WINNT" ] && \
[
"$OS_NAME" =
"CYGWIN_NT" -o
"$OS_NAME" =
"MINGW32_NT" ];
then
PID=${SHELL_SERVERPID}
else
PID=`
cat ${SERVERPID}`
fi
echo "kill -0 ${PID} >/dev/null 2>/dev/null"
kill -0 ${PID} >/dev/null 2>/dev/null || Exit 10
"Fatal - selfserv process not detectable"
echo "selfserv with PID ${PID} found at `date`"
}
########################### wait_for_selfserv ##########################
# local shell function to wait until selfserver is running and initialized
########################################################################
wait_for_selfserv()
{
#verbose="-v"
echo "trying to connect to selfserv at `date`"
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} ${CLIENT_OPTIONS} -q \\"
echo " -d ${P_R_CLIENTDIR} $verbose < ${REQUEST_FILE}"
${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} ${CLIENT_OPTIONS} -q \
-d ${P_R_CLIENTDIR} $verbose < ${REQUEST_FILE}
if [ $? -ne 0 ];
then
sleep 5
echo "retrying to connect to selfserv at `date`"
echo "tstclnt -p ${PORT} -h ${HOSTADDR} ${CLIENT_OPTIONS} -q \\"
echo " -d ${P_R_CLIENTDIR} $verbose < ${REQUEST_FILE}"
${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} ${CLIENT_OPTIONS} -q \
-d ${P_R_CLIENTDIR} $verbose < ${REQUEST_FILE}
if [ $? -ne 0 ];
then
html_failed
"Waiting for Server"
fi
fi
is_selfserv_alive
}
########################### kill_selfserv ##############################
# local shell function to kill the selfserver after the tests are done
########################################################################
kill_selfserv()
{
if [
"${OS_ARCH}" =
"WINNT" ] && \
[
"$OS_NAME" =
"CYGWIN_NT" -o
"$OS_NAME" =
"MINGW32_NT" ];
then
PID=${SHELL_SERVERPID}
else
PID=`
cat ${SERVERPID}`
fi
echo "trying to kill selfserv with PID ${PID} at `date`"
if [
"${OS_ARCH}" =
"WINNT" ];
then
echo "${KILL} ${PID}"
${KILL} ${PID}
else
echo "${KILL} -USR1 ${PID}"
${KILL} -USR1 ${PID}
fi
wait ${PID}
if [ ${fileout} -eq 1 ];
then
cat ${SERVEROUTFILE}
fi
# On Linux selfserv 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 "selfserv -b -p ${PORT} 2>/dev/null;"
until ${BINDIR}/selfserv -b -p ${PORT} 2>/dev/null;
do
echo "RETRY: selfserv -b -p ${PORT} 2>/dev/null;"
sleep 1
done
fi
echo "selfserv with PID ${PID} killed at `date`"
rm ${SERVERPID}
html_detect_core
"kill_selfserv core detection step"
}
########################### start_selfserv #############################
# local shell function to start the selfserver with the parameters required
# for this test and log information (parameters, start time)
# also: wait until the server is up and running
########################################################################
start_selfserv()
{
if [ -n
"$testname" ] ;
then
echo "$SCRIPTNAME: $testname ----"
fi
if [ -z
"$NO_ECC_CERTS" -o
"$NO_ECC_CERTS" !=
"1" ] ;
then
ECC_OPTIONS=
"-e ${HOSTADDR}-ecmixed -e ${HOSTADDR}-ec"
else
ECC_OPTIONS=
""
fi
if [ -z
"$RSA_PSS_CERT" -o
"$RSA_PSS_CERT" !=
"1" ] ;
then
RSA_OPTIONS=
"-n ${HOSTADDR}"
else
RSA_OPTIONS=
"-n ${HOSTADDR}-rsa-pss"
fi
SERVER_VMIN=${SERVER_VMIN-ssl3}
SERVER_VMAX=${SERVER_VMAX-tls1.2}
echo "selfserv starting at `date`"
echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \\"
echo " ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@
" -i ${R_SERVERPID}\\"
echo " -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 &"
if [ ${fileout} -eq 1 ];
then
${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER
_OPTIONS} \
${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 \
> ${SERVEROUTFILE} 2>&1 &
RET=$?
else
${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \
${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 &
RET=$?
fi
# 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 selfserv save its PID
# in the ${SERVERPID} 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_SERVERPID variable, and use it instead of the ${SERVERPID}
# file under Cygwin. (In fact, this should work in any shell
# other than the MKS shell.)
SHELL_SERVERPID=$!
wait_for_selfserv
if [ "${OS_ARCH}" = "WINNT" ] && \
[ "$OS_NAME" = "CYGWIN_NT" -o "$OS_NAME" = "MINGW32_NT" ]; then
PID=${SHELL_SERVERPID}
else
PID=`cat ${SERVERPID}`
fi
echo "selfserv with PID ${PID} started at `date`"
}
############################## ssl_cov #################################
# local shell function to perform SSL Cipher Coverage tests
########################################################################
ssl_cov()
{
verbose_save=${verbose}
verbose="-v"
html_head "SSL Cipher Coverage $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE"
testname=""
SAVE_SERVER_OPTIONS=${SERVER_OPTIONS}
if [ "${SERVER_MODE}" = "fips" ] ; then
SERVER_OPTIONS="${SERVER_OPTIONS} ${FIPS_OPTIONS}"
fi
SAVE_CLIENT_OPTIONS=${CLIENT_OPTIONS}
if [ "${CLIENT_MODE}" = "fips" ] ; then
CLIENT_OPTIONS="${CLIENT_OPTIONS} ${FIPS_OPTIONS}"
fi
start_selfserv $CIPHER_SUITES # Launch the server
VMIN="ssl3"
VMAX="tls1.1"
# can't use a pipe here, because we may have to restart selfserv, and
# doing so hides the server pid environment variable in the subshell in
# cygwin, which means we can't kill selfserv at the end here.
SSL_COV_TMP=$(mktemp /tmp/ssl_cov.XXXXXX)
ignore_blank_lines ${SSLCOV} > ${SSL_COV_TMP}
while read ectype testmax param testname
do
echo "${testname}" | grep "EXPORT" > /dev/null
EXP=$?
# RSA-PSS tests are handled in a separate function
case $testname in
*RSA-PSS)
continue
;;
esac
echo "$SCRIPTNAME: running $testname ----------------------------"
VMAX="ssl3"
if [ "$testmax" = "TLS10" ]; then
VMAX="tls1.0"
fi
if [ "$testmax" = "TLS11" ]; then
VMAX="tls1.1"
fi
if [ "$testmax" = "TLS12" ]; then
VMAX="tls1.2"
fi
if [ "$testmax" = "TLS13" ]; then
# if our selfserv can only do up to tls1.2
# restart it so it can do tls1.3, This requires
# moving VMIN up to tls1.0 because you can't enable SSL3 and
# TLS 1.3.
if [ "$VMIN" = "ssl3" ]; then
SERVER_VMIN="tls1.0"
SERVER_VMAX="tls1.3"
kill_selfserv
start_selfserv ${TLS13_CIPHER_SUITES}
unset SERVER_VMIN
unset SERVER_VMAX
VMIN="tls1.0"
fi
VMAX="tls1.3"
fi
# if we are testing ssl3 and our server can only do down to tls1.1,
# restart it to enable ssl3
if [ "$VMAX" = "ssl3" -a "$VMIN" = "tls1.1" ]; then
kill_selfserv
start_selfserv $CIPHER_SUITES
VMIN="ssl3"
fi
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\"
echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}"
rm ${TMP}/$HOST.tmp.$$ 2>/dev/null
${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \
-d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE} \
>${TMP}/$HOST.tmp.$$ 2>&1
ret=$?
cat ${TMP}/$HOST.tmp.$$
rm ${TMP}/$HOST.tmp.$$ 2>/dev/null
html_msg $ret 0 "${testname}" \
"produced a returncode of $ret, expected is 0"
done < ${SSL_COV_TMP}
rm -f ${SSL_COV_TMP}
SERVER_OPTIONS=${SAVE_SERVER_OPTIONS}
CLIENT_OPTIONS=${SAVE_CLIENT_OPTIONS}
verbose=${verbose_save}
kill_selfserv
html "