1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,126 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +// This is a standalone server that delivers various stapled OCSP responses. 1.9 +// The client is expected to connect, initiate an SSL handshake (with SNI 1.10 +// to indicate which "server" to connect to), and verify the OCSP response. 1.11 +// If all is good, the client then sends one encrypted byte and receives that 1.12 +// same byte back. 1.13 +// This server also has the ability to "call back" another process waiting on 1.14 +// it. That is, when the server is all set up and ready to receive connections, 1.15 +// it will connect to a specified port and issue a simple HTTP request. 1.16 + 1.17 +#include <stdio.h> 1.18 + 1.19 +#include "OCSPCommon.h" 1.20 +#include "TLSServer.h" 1.21 + 1.22 +using namespace mozilla; 1.23 +using namespace mozilla::test; 1.24 + 1.25 +const OCSPHost sOCSPHosts[] = 1.26 +{ 1.27 + { "ocsp-stapling-good.example.com", ORTGood, nullptr }, 1.28 + { "ocsp-stapling-revoked.example.com", ORTRevoked, nullptr }, 1.29 + { "ocsp-stapling-revoked-old.example.com", ORTRevokedOld, nullptr }, 1.30 + { "ocsp-stapling-unknown.example.com", ORTUnknown, nullptr }, 1.31 + { "ocsp-stapling-unknown-old.example.com", ORTUnknownOld, nullptr }, 1.32 + { "ocsp-stapling-good-other.example.com", ORTGoodOtherCert, "ocspOtherEndEntity" }, 1.33 + { "ocsp-stapling-good-other-ca.example.com", ORTGoodOtherCA, "otherCA" }, 1.34 + { "ocsp-stapling-expired.example.com", ORTExpired, nullptr }, 1.35 + { "ocsp-stapling-expired-fresh-ca.example.com", ORTExpiredFreshCA, nullptr }, 1.36 + { "ocsp-stapling-none.example.com", ORTNone, nullptr }, 1.37 + { "ocsp-stapling-empty.example.com", ORTEmpty, nullptr }, 1.38 + { "ocsp-stapling-malformed.example.com", ORTMalformed, nullptr }, 1.39 + { "ocsp-stapling-srverr.example.com", ORTSrverr, nullptr }, 1.40 + { "ocsp-stapling-trylater.example.com", ORTTryLater, nullptr }, 1.41 + { "ocsp-stapling-needssig.example.com", ORTNeedsSig, nullptr }, 1.42 + { "ocsp-stapling-unauthorized.example.com", ORTUnauthorized, nullptr }, 1.43 + { "ocsp-stapling-with-intermediate.example.com", ORTGood, "ocspEEWithIntermediate" }, 1.44 + { "ocsp-stapling-bad-signature.example.com", ORTBadSignature, nullptr }, 1.45 + { "ocsp-stapling-skip-responseBytes.example.com", ORTSkipResponseBytes, nullptr }, 1.46 + { "ocsp-stapling-critical-extension.example.com", ORTCriticalExtension, nullptr }, 1.47 + { "ocsp-stapling-noncritical-extension.example.com", ORTNoncriticalExtension, nullptr }, 1.48 + { "ocsp-stapling-empty-extensions.example.com", ORTEmptyExtensions, nullptr }, 1.49 + { "ocsp-stapling-delegated-included.example.com", ORTDelegatedIncluded, "delegatedSigner" }, 1.50 + { "ocsp-stapling-delegated-included-last.example.com", ORTDelegatedIncludedLast, "delegatedSigner" }, 1.51 + { "ocsp-stapling-delegated-missing.example.com", ORTDelegatedMissing, "delegatedSigner" }, 1.52 + { "ocsp-stapling-delegated-missing-multiple.example.com", ORTDelegatedMissingMultiple, "delegatedSigner" }, 1.53 + { "ocsp-stapling-delegated-no-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerNoExtKeyUsage" }, 1.54 + { "ocsp-stapling-delegated-from-intermediate.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerFromIntermediate" }, 1.55 + { "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerKeyUsageCrlSigning" }, 1.56 + { "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerWrongExtKeyUsage" }, 1.57 + { "ocsp-stapling-ancient-valid.example.com", ORTAncientAlmostExpired, nullptr}, 1.58 + { nullptr, ORTNull, nullptr } 1.59 +}; 1.60 + 1.61 +int32_t 1.62 +DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr, 1.63 + uint32_t aSrvNameArrSize, void *aArg) 1.64 +{ 1.65 + const OCSPHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize, 1.66 + sOCSPHosts); 1.67 + if (!host) { 1.68 + return SSL_SNI_SEND_ALERT; 1.69 + } 1.70 + 1.71 + if (gDebugLevel >= DEBUG_VERBOSE) { 1.72 + fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName); 1.73 + } 1.74 + 1.75 + const char *certNickname; 1.76 + if (strcmp(host->mHostName, 1.77 + "ocsp-stapling-with-intermediate.example.com") == 0) { 1.78 + certNickname = host->mAdditionalCertName; 1.79 + } else { 1.80 + certNickname = DEFAULT_CERT_NICKNAME; 1.81 + } 1.82 + 1.83 + ScopedCERTCertificate cert; 1.84 + SSLKEAType certKEA; 1.85 + if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, certNickname, 1.86 + &cert, &certKEA)) { 1.87 + return SSL_SNI_SEND_ALERT; 1.88 + } 1.89 + 1.90 + // If the OCSP response type is "none", don't staple a response. 1.91 + if (host->mORT == ORTNone) { 1.92 + return 0; 1.93 + } 1.94 + 1.95 + PLArenaPool *arena = PORT_NewArena(1024); 1.96 + if (!arena) { 1.97 + PrintPRError("PORT_NewArena failed"); 1.98 + return SSL_SNI_SEND_ALERT; 1.99 + } 1.100 + 1.101 + // response is contained by the arena - freeing the arena will free it 1.102 + SECItemArray *response = GetOCSPResponseForType(host->mORT, cert, arena, 1.103 + host->mAdditionalCertName); 1.104 + if (!response) { 1.105 + PORT_FreeArena(arena, PR_FALSE); 1.106 + return SSL_SNI_SEND_ALERT; 1.107 + } 1.108 + 1.109 + // SSL_SetStapledOCSPResponses makes a deep copy of response 1.110 + SECStatus st = SSL_SetStapledOCSPResponses(aFd, response, certKEA); 1.111 + PORT_FreeArena(arena, PR_FALSE); 1.112 + if (st != SECSuccess) { 1.113 + PrintPRError("SSL_SetStapledOCSPResponses failed"); 1.114 + return SSL_SNI_SEND_ALERT; 1.115 + } 1.116 + 1.117 + return 0; 1.118 +} 1.119 + 1.120 +int 1.121 +main(int argc, char *argv[]) 1.122 +{ 1.123 + if (argc != 2) { 1.124 + fprintf(stderr, "usage: %s <NSS DB directory>\n", argv[0]); 1.125 + return 1; 1.126 + } 1.127 + 1.128 + return StartServer(argv[1], DoSNISocketConfig, nullptr); 1.129 +}