From fd3579fa78cc3500e97e77a8fece6b7bf3dc8226 Mon Sep 17 00:00:00 2001 From: "kaie%kuix.de" Date: Fri, 15 Feb 2013 17:57:01 +0000 Subject: [PATCH] Bug 811331 / Bug 360420, add selfsigned OCSP stapling to selfserv, stapling support for strsclnt, run self-contained stapling tests, r=rrelyea git-svn-id: svn://10.0.0.236/trunk@264737 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/security/nss/cmd/selfserv/selfserv.c | 275 +++++++++++++++++- mozilla/security/nss/cmd/strsclnt/strsclnt.c | 20 +- mozilla/security/nss/cmd/tstclnt/tstclnt.c | 2 + mozilla/security/nss/tests/all.sh | 4 +- mozilla/security/nss/tests/cert/cert.sh | 23 ++ mozilla/security/nss/tests/common/init.sh | 2 + .../security/nss/tests/dbupgrade/dbupgrade.sh | 2 +- mozilla/security/nss/tests/ocsp/ocsp.sh | 4 +- mozilla/security/nss/tests/ssl/ssl.sh | 130 ++++++++- 9 files changed, 453 insertions(+), 9 deletions(-) diff --git a/mozilla/security/nss/cmd/selfserv/selfserv.c b/mozilla/security/nss/cmd/selfserv/selfserv.c index 501215bfca7..e9d5dc3e237 100644 --- a/mozilla/security/nss/cmd/selfserv/selfserv.c +++ b/mozilla/security/nss/cmd/selfserv/selfserv.c @@ -40,6 +40,7 @@ #include "sslproto.h" #include "cert.h" #include "certt.h" +#include "ocsp.h" #ifndef PORT_Sprintf #define PORT_Sprintf sprintf @@ -77,6 +78,21 @@ static PRUint32 loggerOps; static PRUint32 loggerBytes; static PRUint32 loggerBytesTCP; static PRUint32 bulkSentChunks; +static enum ocspStaplingModeEnum { + osm_disabled, /* server doesn't support stapling */ + osm_good, /* supply a signed good status */ + osm_revoked, /* supply a signed revoked status */ + osm_unknown, /* supply a signed unknown status */ + osm_failure, /* supply a unsigned failure status, "try later" */ + osm_badsig, /* supply a good status response with a bad signature */ + osm_corrupted, /* supply a corrupted data block as the status */ + osm_random, /* use a random response for each connection */ + osm_ocsp /* retrieve ocsp status from external ocsp server, + use empty status if server is unavailable */ +} ocspStaplingMode = osm_disabled; +typedef enum ocspStaplingModeEnum ocspStaplingModeType; +static char *ocspStaplingCA = NULL; +CERTCertificate * certForStatusWeakReference = NULL; const int ssl2CipherSuites[] = { SSL_EN_RC4_128_WITH_MD5, /* A */ @@ -143,6 +159,7 @@ PrintUsageHeader(const char *progName) " [-t threads] [-i pid_file] [-c ciphers] [-Y] [-d dbdir] [-g numblocks]\n" " [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n" " [-V [min-version]:[max-version]] [-a sni_name]\n" +" [ T ] [-A ca]\n" #ifdef NSS_ENABLE_ECC " [-C SSLCacheEntries] [-e ec_nickname]\n" #else @@ -189,6 +206,16 @@ PrintParameterUsage() "-j means measure TCP throughput (for use with -g option)\n" "-C SSLCacheEntries sets the maximum number of entries in the SSL\n" " session cache\n" +"-T enable OCSP stapling. Possible modes:\n" +" none: don't send cert status (default)\n" +" good, revoked, unknown: Include locally signed response. Requires: -A\n" +" failure: return a failure response (try later, unsigned)\n" +" badsig: use a good status but with an invalid signature\n" +" corrupted: stapled cert status is an invalid block of data\n" +" random: each connection uses a random status from this list:\n" +" good, revoked, unknown, failure, badsig, corrupted\n" +" ocsp: fetch from external OCSP server using AIA, or none\n" +"-A Nickname of a CA used to sign a stapled cert status\n" "-c Restrict ciphers\n" "-Y prints cipher values allowed for parameter -c and exits\n" , stderr); @@ -1038,6 +1065,130 @@ void stop_server() PZ_TraceFlush(); } +SECItemArray * +makeTryLaterOCSPResponse(PRArenaPool *arena) +{ + SECItemArray *result = NULL; + SECItem *ocspResponse = NULL; + + ocspResponse = CERT_CreateEncodedOCSPErrorResponse(arena, + SEC_ERROR_OCSP_TRY_SERVER_LATER); + if (!ocspResponse) + errExit("cannot created ocspResponse"); + + result = SECITEM_AllocArray(arena, NULL, 1); + if (!result) + errExit("cannot allocate multiOcspResponses"); + + result->items[0].data = ocspResponse->data; + result->items[0].len = ocspResponse->len; + + return result; +} + +SECItemArray * +makeCorruptedOCSPResponse(PRArenaPool *arena) +{ + SECItemArray *result = NULL; + SECItem *ocspResponse = NULL; + + ocspResponse = SECITEM_AllocItem(arena, NULL, 1); + if (!ocspResponse) + errExit("cannot created ocspResponse"); + + result = SECITEM_AllocArray(arena, NULL, 1); + if (!result) + errExit("cannot allocate multiOcspResponses"); + + result->items[0].data = ocspResponse->data; + result->items[0].len = ocspResponse->len; + + return result; +} + +SECItemArray * +makeSignedOCSPResponse(PRArenaPool *arena, ocspStaplingModeType osm, + PRFileDesc *model_sock, CERTCertificate *cert) +{ + SECItemArray *result = NULL; + SECItem *ocspResponse = NULL; + CERTOCSPSingleResponse **singleResponses; + CERTOCSPSingleResponse *sr; + CERTOCSPCertID *cid = NULL; + CERTCertificate *ca; + PRTime now = PR_Now(); + PRTime nextUpdate; + const secuPWData *pwdata; + + PORT_Assert(model_sock != NULL && cert != NULL); + + ca = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), ocspStaplingCA); + if (!ca) + errExit("cannot find CA"); + + cid = CERT_CreateOCSPCertID(cert, now); + if (!cid) + errExit("cannot created cid"); + + nextUpdate = now + 60*60*24 * PR_USEC_PER_SEC; /* plus 1 day */ + + switch (osm) { + case osm_good: + case osm_badsig: + sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, + &nextUpdate); + break; + case osm_unknown: + sr = CERT_CreateOCSPSingleResponseUnknown(arena, cid, now, + &nextUpdate); + break; + case osm_revoked: + sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, + &nextUpdate, + now - 60*60*24 * PR_USEC_PER_SEC, /* minus 1 day */ + NULL); + break; + default: + PORT_Assert(0); + break; + } + + if (!sr) + errExit("cannot create sr"); + + /* meaning of value 2: one entry + one end marker */ + singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse*, 2); + if (singleResponses == NULL) + errExit("cannot allocate singleResponses"); + + singleResponses[0] = sr; + singleResponses[1] = NULL; + + pwdata = SSL_RevealPinArg(model_sock); + + ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena, + (osm == osm_badsig) ? NULL : ca, + ocspResponderID_byName, now, singleResponses, + &pwdata); + if (!ocspResponse) + errExit("cannot created ocspResponse"); + + CERT_DestroyCertificate(ca); + ca = NULL; + + result = SECITEM_AllocArray(arena, NULL, 1); + if (!result) + errExit("cannot allocate multiOcspResponses"); + + result->items[0].data = ocspResponse->data; + result->items[0].len = ocspResponse->len; + + CERT_DestroyOCSPCertID(cid); + cid = NULL; + + return result; +} + int handle_connection( PRFileDesc *tcp_sock, @@ -1065,6 +1216,8 @@ handle_connection( char fileName[513]; char proto[128]; PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER; + PRArenaPool *arena = NULL; + ocspStaplingModeType osm; pBuf = buf; bufRem = sizeof buf; @@ -1091,6 +1244,58 @@ handle_connection( ssl_sock = tcp_sock; } + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) + errExit("cannot allocate arena"); + + osm = ocspStaplingMode; + if (osm == osm_random) { + /* 6 different responses */ + int r = rand() % 6; + switch (r) { + case 0: osm = osm_good; break; + case 1: osm = osm_revoked; break; + case 2: osm = osm_unknown; break; + case 3: osm = osm_badsig; break; + case 4: osm = osm_corrupted; break; + case 5: osm = osm_failure; break; + default: PORT_Assert(0); break; + } + } + if (osm != osm_disabled) { + SECItemArray *multiOcspResponses = NULL; + switch (osm) { + case osm_good: + case osm_revoked: + case osm_unknown: + case osm_badsig: + multiOcspResponses = + makeSignedOCSPResponse(arena, osm, ssl_sock, + certForStatusWeakReference); + break; + case osm_corrupted: + multiOcspResponses = makeCorruptedOCSPResponse(arena); + break; + case osm_failure: + multiOcspResponses = makeTryLaterOCSPResponse(arena); + break; + case osm_ocsp: + errExit("stapling mode \"ocsp\" not implemented"); + break; + break; + default: + break; + } + + if (multiOcspResponses) { + SSL_SetStapledOCSPResponses(ssl_sock, multiOcspResponses, + PR_FALSE /* no ownership transfer */); + } + } + + PORT_FreeArena(arena, PR_FALSE); + arena = NULL; + if (loggingLayer) { /* find the layer where our new layer is to be pushed */ aboveLayer = PR_GetLayersIdentity(ssl_sock->lower); @@ -1705,6 +1910,9 @@ server_main( for (kea = kt_rsa; kea < kt_kea_size; kea++) { if (cert[kea] != NULL) { + if (!certForStatusWeakReference) + certForStatusWeakReference = cert[kea]; + secStatus = SSL_ConfigSecureServer(model_sock, cert[kea], privKey[kea], kea); if (secStatus != SECSuccess) @@ -1889,6 +2097,43 @@ beAGoodParent(int argc, char **argv, int maxProcs, PRFileDesc * listen_sock) exit(9); \ } +SECStatus enableOCSPStapling(const char* mode) +{ + if (!strcmp(mode, "good")) { + ocspStaplingMode = osm_good; + return SECSuccess; + } + if (!strcmp(mode, "unknown")) { + ocspStaplingMode = osm_unknown; + return SECSuccess; + } + if (!strcmp(mode, "revoked")) { + ocspStaplingMode = osm_revoked; + return SECSuccess; + } + if (!strcmp(mode, "badsig")) { + ocspStaplingMode = osm_badsig; + return SECSuccess; + } + if (!strcmp(mode, "corrupted")) { + ocspStaplingMode = osm_corrupted; + return SECSuccess; + } + if (!strcmp(mode, "failure")) { + ocspStaplingMode = osm_failure; + return SECSuccess; + } + if (!strcmp(mode, "random")) { + ocspStaplingMode = osm_random; + return SECSuccess; + } + if (!strcmp(mode, "ocsp")) { + ocspStaplingMode = osm_ocsp; + return SECSuccess; + } + return SECFailure; +} + int main(int argc, char **argv) { @@ -1940,12 +2185,14 @@ main(int argc, char **argv) ** numbers, then capital letters, then lower case, alphabetical. */ optstate = PL_CreateOptState(argc, argv, - "2:BC:DEL:M:NP:RV:Ya:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz"); + "2:A:BC:DEL:M:NP:RT:V:Ya:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch(optstate->option) { case '2': fileName = optstate->value; break; + case 'A': ocspStaplingCA = PORT_Strdup(optstate->value); break; + case 'B': bypassPKCS11 = PR_TRUE; break; case 'C': if (optstate->value) NumSidCacheEntries = PORT_Atoi(optstate->value); break; @@ -1953,6 +2200,8 @@ main(int argc, char **argv) case 'D': noDelay = PR_TRUE; break; case 'E': disableStepDown = PR_TRUE; break; + case 'I': /* reserved for OCSP multi-stapling */ break; + case 'L': logStats = PR_TRUE; if (optstate->value == NULL) { @@ -1973,6 +2222,14 @@ main(int argc, char **argv) case 'R': disableRollBack = PR_TRUE; break; + case 'T': + if (enableOCSPStapling(optstate->value) != SECSuccess) { + fprintf(stderr, "Invalid OCSP stapling mode.\n"); + fprintf(stderr, "Run '%s -h' for usage information.\n", progName); + exit(53); + } + break; + case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value, enabledVersions, enableSSL2, &enabledVersions, &enableSSL2) != SECSuccess) { @@ -2078,7 +2335,21 @@ main(int argc, char **argv) if (!optionsFound) { Usage(progName); exit(51); - } + } + switch (ocspStaplingMode) { + case osm_good: + case osm_revoked: + case osm_unknown: + case osm_random: + if (!ocspStaplingCA) { + fprintf(stderr, "Selected stapling response requires the -A parameter.\n"); + fprintf(stderr, "Run '%s -h' for usage information.\n", progName); + exit(52); + } + break; + default: + break; + } /* The -b (bindOnly) option is only used by the ssl.sh test * script on Linux to determine whether a previous selfserv diff --git a/mozilla/security/nss/cmd/strsclnt/strsclnt.c b/mozilla/security/nss/cmd/strsclnt/strsclnt.c index f66e108fcde..8801dbfad26 100644 --- a/mozilla/security/nss/cmd/strsclnt/strsclnt.c +++ b/mozilla/security/nss/cmd/strsclnt/strsclnt.c @@ -129,6 +129,7 @@ static PRBool ignoreErrors = PR_FALSE; static PRBool enableSessionTickets = PR_FALSE; static PRBool enableCompression = PR_FALSE; static PRBool enableFalseStart = PR_FALSE; +static PRBool enableCertStatus = PR_FALSE; PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT; @@ -166,6 +167,7 @@ Usage(const char *progName) " Example: \"-V ssl3:\" enables SSL 3 and newer.\n" " -U means enable throttling up threads\n" " -B bypasses the PKCS11 layer for SSL encryption and MACing\n" + " -T enable the cert_status extension (OCSP stapling)\n" " -u enable TLS Session Ticket extension\n" " -z enable compression\n" " -g enable false start\n", @@ -226,6 +228,7 @@ mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, { SECStatus rv; CERTCertificate * peerCert; + const SECItemArray *csa; if (MakeCertOK>=2) { return SECSuccess; @@ -234,6 +237,11 @@ mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n", peerCert->subjectName, peerCert->issuerName); + csa = SSL_PeerStapledOCSPResponses(fd); + if (csa) { + PRINTF("Received %d Cert Status items (OCSP stapled data)\n", + csa->len); + } /* invoke the "default" AuthCert handler. */ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer); @@ -1220,6 +1228,12 @@ client_main( errExit("SSL_OptionSet SSL_ENABLE_FALSE_START"); } + if (enableCertStatus) { + rv = SSL_OptionSet(model_sock, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); + if (rv != SECSuccess) + errExit("SSL_OptionSet SSL_ENABLE_OCSP_STAPLING"); + } + SSL_SetPKCS11PinArg(model_sock, &pwdata); SSL_SetURL(model_sock, hostName); @@ -1332,7 +1346,7 @@ main(int argc, char **argv) optstate = PL_CreateOptState(argc, argv, - "BC:DNP:UV:W:a:c:d:f:gin:op:qst:uvw:z"); + "BC:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch(optstate->option) { case 'B': bypassPKCS11 = PR_TRUE; break; @@ -1341,10 +1355,14 @@ main(int argc, char **argv) case 'D': NoDelay = PR_TRUE; break; + case 'I': /* reserved for OCSP multi-stapling */ break; + case 'N': NoReuse = 1; break; case 'P': fullhs = PORT_Atoi(optstate->value); break; + case 'T': enableCertStatus = PR_TRUE; break; + case 'U': ThrottleUp = PR_TRUE; break; case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value, diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c index 48e36504550..80c221fdc04 100644 --- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c +++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c @@ -861,6 +861,8 @@ int main(int argc, char **argv) serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE; break; + case 'I': /* reserved for OCSP multi-stapling */ break; + case 'O': serverCertAuth.shouldPause = PR_FALSE; break; case 'M': switch (atoi(optstate->value)) { diff --git a/mozilla/security/nss/tests/all.sh b/mozilla/security/nss/tests/all.sh index eb8b537a9a7..ee108523993 100755 --- a/mozilla/security/nss/tests/all.sh +++ b/mozilla/security/nss/tests/all.sh @@ -183,7 +183,7 @@ run_cycle_upgrade_db() init_directories if [ -r "${OLDHOSTDIR}/cert.log" ]; then - DIRS="alicedir bobdir CA cert_extensions client clientCA dave eccurves eve ext_client ext_server fips SDR server serverCA tools/copydir cert.log cert.done tests.*" + DIRS="alicedir bobdir CA cert_extensions client clientCA dave eccurves eve ext_client ext_server fips SDR server serverCA stapling tools/copydir cert.log cert.done tests.*" for i in $DIRS do cp -r ${OLDHOSTDIR}/${i} ${HOSTDIR} #2> /dev/null @@ -281,7 +281,7 @@ ALL_TESTS=${TESTS} nss_ssl_tests="crl bypass_normal normal_bypass fips_normal normal_fips iopr" NSS_SSL_TESTS="${NSS_SSL_TESTS:-$nss_ssl_tests}" -nss_ssl_run="cov auth stress" +nss_ssl_run="cov auth stapling stress" NSS_SSL_RUN="${NSS_SSL_RUN:-$nss_ssl_run}" SCRIPTNAME=all.sh diff --git a/mozilla/security/nss/tests/cert/cert.sh b/mozilla/security/nss/tests/cert/cert.sh index dc3700eee02..b710b689fb1 100755 --- a/mozilla/security/nss/tests/cert/cert.sh +++ b/mozilla/security/nss/tests/cert/cert.sh @@ -74,6 +74,23 @@ cert_log() ###################### write the cert_status file echo $* >>${CERT_LOG_FILE} } +######################################################################## +# function wraps calls to pk12util, also: writes action and options +# to stdout. +# Params are the same as to pk12util. +# Returns pk12util status +# +pk12u() +{ + echo "${CU_ACTION} --------------------------" + + echo "pk12util $@" + ${BINDIR}/pk12util $@ + RET=$? + + return $RET +} + ################################ certu ################################# # local shell function to call certutil, also: writes action and options to # stdout, sets variable RET and writes results to the html file results @@ -921,6 +938,12 @@ cert_ssl() else cert_log "SUCCESS: SSL passed" fi + + echo "$SCRIPTNAME: Creating database for OCSP stapling tests ===============" + echo "cp -rv ${SERVERDIR} ${STAPLINGDIR}" + cp -rv ${R_SERVERDIR} ${R_STAPLINGDIR} + pk12u -o ${R_STAPLINGDIR}/ca.p12 -n TestCA -k ${R_PWFILE} -w ${R_PWFILE} -d ${R_CADIR} + pk12u -i ${R_STAPLINGDIR}/ca.p12 -k ${R_PWFILE} -w ${R_PWFILE} -d ${R_STAPLINGDIR} } ############################## cert_stresscerts ################################ # local shell function to create client certs for SSL stresstest diff --git a/mozilla/security/nss/tests/common/init.sh b/mozilla/security/nss/tests/common/init.sh index d9ee5890521..07a7e7c14a2 100644 --- a/mozilla/security/nss/tests/common/init.sh +++ b/mozilla/security/nss/tests/common/init.sh @@ -75,6 +75,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then IOPR_OCSP_CLIENTDIR=${HOSTDIR}/client_ocsp_iopr CERT_EXTENSIONS_DIR=${HOSTDIR}/cert_extensions + STAPLINGDIR=${HOSTDIR}/stapling PWFILE=${HOSTDIR}/tests.pw NOISE_FILE=${HOSTDIR}/tests_noise @@ -537,6 +538,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then R_EXT_SERVERDIR=../ext_server R_EXT_CLIENTDIR=../ext_client R_CERT_EXT=../cert_extensions + R_STAPLINGDIR=../stapling # # profiles are either paths or domains depending on the setting of diff --git a/mozilla/security/nss/tests/dbupgrade/dbupgrade.sh b/mozilla/security/nss/tests/dbupgrade/dbupgrade.sh index 8d7f77f966b..b43ac14fc51 100755 --- a/mozilla/security/nss/tests/dbupgrade/dbupgrade.sh +++ b/mozilla/security/nss/tests/dbupgrade/dbupgrade.sh @@ -63,7 +63,7 @@ dbupgrade_main() # test upgrade to the new database echo "nss" > ${PWFILE} html_head "Legacy to shared Library update" - dirs="alicedir bobdir CA cert_extensions client clientCA dave eccurves eve ext_client ext_server SDR server serverCA tools/copydir" + dirs="alicedir bobdir CA cert_extensions client clientCA dave eccurves eve ext_client ext_server SDR server serverCA stapling tools/copydir" for i in $dirs do echo $i diff --git a/mozilla/security/nss/tests/ocsp/ocsp.sh b/mozilla/security/nss/tests/ocsp/ocsp.sh index 7fedfafccbb..f3040313747 100644 --- a/mozilla/security/nss/tests/ocsp/ocsp.sh +++ b/mozilla/security/nss/tests/ocsp/ocsp.sh @@ -97,13 +97,13 @@ ocsp_stapling() ${BINDIR}/tstclnt -V tls1.0: -T -v -F -M 1 -O -h login.live.com -p 443 -d . html_msg $? 0 "$TESTNAME" - TESTNAME="startssl valid, don't support OCSP stapling" + TESTNAME="startssl valid, doesn't support OCSP stapling" echo "$SCRIPTNAME: $TESTNAME" echo "tstclnt -V tls1.0: -T -v -F -M 1 -O -h kuix.de -p 443 -d ." ${BINDIR}/tstclnt -V tls1.0: -T -v -F -M 1 -O -h kuix.de -p 443 -d . html_msg $? 2 "$TESTNAME" - TESTNAME="cacert untrusted, don't support OCSP stapling" + TESTNAME="cacert untrusted, doesn't support OCSP stapling" echo "$SCRIPTNAME: $TESTNAME" echo "tstclnt -V tls1.0: -T -v -F -M 1 -O -h www.cacert.org -p 443 -d ." ${BINDIR}/tstclnt -V tls1.0: -T -v -F -M 1 -O -h www.cacert.org -p 443 -d . diff --git a/mozilla/security/nss/tests/ssl/ssl.sh b/mozilla/security/nss/tests/ssl/ssl.sh index 4fe39e522df..48ca1ca9e7c 100755 --- a/mozilla/security/nss/tests/ssl/ssl.sh +++ b/mozilla/security/nss/tests/ssl/ssl.sh @@ -58,7 +58,7 @@ ssl_init() PORT=${PORT-8443} NSS_SSL_TESTS=${NSS_SSL_TESTS:-normal_normal} - nss_ssl_run="cov auth stress" + nss_ssl_run="stapling cov auth stress" NSS_SSL_RUN=${NSS_SSL_RUN:-$nss_ssl_run} # Test case files @@ -404,6 +404,131 @@ ssl_auth() html "
" } +ssl_stapling_sub() +{ + testname=$1 + SO=$2 + value=$3 + + if [ "$NORM_EXT" = "Extended Test" ] ; then + # these tests use the ext_client directory for tstclnt, + # which doesn't contain the required "TestCA" for server cert + # verification, I don't know if it would be OK to add it... + echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" + return 0 + fi + if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then + echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" + return 0 + fi + + SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} + SERVER_OPTIONS="${SERVER_OPTIONS} ${SO}" + + SAVE_P_R_SERVERDIR=${P_R_SERVERDIR} + P_R_SERVERDIR=${P_R_SERVERDIR}/../stapling/ + + echo "${testname}" + + start_selfserv + + echo "tstclnt -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} -v ${CLIENT_OPTIONS} \\" + echo " -T -O -F -M 1 -V ssl3: < ${REQUEST_FILE}" + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + ${PROFTOOL} ${BINDIR}/tstclnt -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \ + -d ${P_R_CLIENTDIR} -v -T -O -F -M 1 -V ssl3: < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? + cat ${TMP}/$HOST.tmp.$$ + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + + # hopefully no workaround for bug #402058 needed here? + # (see commands in ssl_auth + + html_msg $ret $value "${testname}" \ + "produced a returncode of $ret, expected is $value" + kill_selfserv + + SERVER_OPTIONS=${SAVE_SERVER_OPTIONS} + P_R_SERVERDIR=${SAVE_P_R_SERVERDIR} +} + +ssl_stapling_stress() +{ + testname="Stress OCSP stapling, server uses random status" + SO="-A TestCA -T random" + value=0 + + if [ "$NORM_EXT" = "Extended Test" ] ; then + # these tests use the ext_client directory for tstclnt, + # which doesn't contain the required "TestCA" for server cert + # verification, I don't know if it would be OK to add it... + echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" + return 0 + fi + if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then + echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" + return 0 + fi + + SAVE_SERVER_OPTIONS=${SERVER_OPTIONS} + SERVER_OPTIONS="${SERVER_OPTIONS} ${SO}" + + SAVE_P_R_SERVERDIR=${P_R_SERVERDIR} + P_R_SERVERDIR=${P_R_SERVERDIR}/../stapling/ + + echo "${testname}" + start_selfserv + + echo "strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} ${CLIENT_OPTIONS} -w nss \\" + echo " -c 1000 -V ssl3: -N -T $verbose ${HOSTADDR}" + echo "strsclnt started at `date`" + ${PROFTOOL} ${BINDIR}/strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} ${CLIENT_OPTIONS} -w nss \ + -c 1000 -V ssl3: -N -T $verbose ${HOSTADDR} + ret=$? + + echo "strsclnt completed at `date`" + html_msg $ret $value \ + "${testname}" \ + "produced a returncode of $ret, expected is $value." + kill_selfserv + + SERVER_OPTIONS=${SAVE_SERVER_OPTIONS} + P_R_SERVERDIR=${SAVE_P_R_SERVERDIR} +} + +############################ ssl_stapling ############################## +# local shell function to perform SSL Cert Status (OCSP Stapling) tests +######################################################################## +ssl_stapling() +{ + html_head "SSL Cert Status (OCSP Stapling) $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE $ECC_STRING" + + # tstclnt Exit code: + # 0: have fresh and valid revocation data, status good + # 1: cert failed to verify, prior to revocation checking + # 2: missing, old or invalid revocation data + # 3: have fresh and valid revocation data, status revoked + + # selfserv modes + # good, revoked, unkown: Include locally signed response. Requires: -A + # failure: Include OCSP failure status, such as "try later" (unsigned) + # badsig: use a good status but with an invalid signature + # corrupted: stapled cert status is an invalid block of data + + ssl_stapling_sub "OCSP stapling, signed response, good status" "-A TestCA -T good" 0 + ssl_stapling_sub "OCSP stapling, signed response, revoked status" "-A TestCA -T revoked" 3 + ssl_stapling_sub "OCSP stapling, signed response, unknown status" "-A TestCA -T unknown" 2 + ssl_stapling_sub "OCSP stapling, unsigned failure response" "-A TestCA -T failure" 2 + ssl_stapling_sub "OCSP stapling, good status, bad signature" "-A TestCA -T badsig" 2 + ssl_stapling_sub "OCSP stapling, invalid cert status data" "-A TestCA -T corrupted" 2 + ssl_stapling_sub "Valid cert, Server doesn't staple" "" 2 + + ssl_stapling_stress + + html "
" +} + ############################## ssl_stress ############################## # local shell function to perform SSL stress test @@ -801,6 +926,9 @@ ssl_run() for SSL_RUN in ${NSS_SSL_RUN} do case "${SSL_RUN}" in + "stapling") + ssl_stapling + ;; "cov") ssl_cov ;;