BadCertAndPinningServer.cpp (6997B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // This is a standalone server that uses various bad certificates. 6 // The client is expected to connect, initiate an SSL handshake (with SNI 7 // to indicate which "server" to connect to), and verify the certificate. 8 // If all is good, the client then sends one encrypted byte and receives that 9 // same byte back. 10 // This server also has the ability to "call back" another process waiting on 11 // it. That is, when the server is all set up and ready to receive connections, 12 // it will connect to a specified port and issue a simple HTTP request. 13 14 #include <stdio.h> 15 16 #include "TLSServer.h" 17 18 using namespace mozilla; 19 using namespace mozilla::test; 20 21 struct BadCertAndPinningHost { 22 const char* mHostName; 23 const char* mCertName; 24 }; 25 26 // Hostname, cert nickname pairs. 27 const BadCertAndPinningHost sBadCertAndPinningHosts[] = { 28 {"expired.example.com", "expired-ee"}, 29 {"notyetvalid.example.com", "notYetValid"}, 30 {"before-epoch.example.com", "beforeEpoch"}, 31 {"before-epoch-self-signed.example.com", "beforeEpochSelfSigned"}, 32 {"selfsigned.example.com", "selfsigned"}, 33 {"unknownissuer.example.com", "unknownissuer"}, 34 {"mismatch.example.com", "mismatch"}, 35 {"mismatch-CN.example.com", "mismatchCN"}, 36 {"mitm.example.com", "mitm"}, 37 {"expiredissuer.example.com", "expiredissuer"}, 38 {"notyetvalidissuer.example.com", "notYetValidIssuer"}, 39 {"before-epoch-issuer.example.com", "beforeEpochIssuer"}, 40 {"md5signature.example.com", "md5signature"}, 41 {"untrusted.example.com", "default-ee"}, 42 {"untrustedissuer.example.com", "untrustedissuer"}, 43 {"mismatch-expired.example.com", "mismatch-expired"}, 44 {"mismatch-notYetValid.example.com", "mismatch-notYetValid"}, 45 {"mismatch-untrusted.example.com", "mismatch-untrusted"}, 46 {"untrusted-expired.example.com", "untrusted-expired"}, 47 {"md5signature-expired.example.com", "md5signature-expired"}, 48 {"mismatch-untrusted-expired.example.com", "mismatch-untrusted-expired"}, 49 {"inadequatekeyusage.example.com", "inadequatekeyusage-ee"}, 50 {"selfsigned-inadequateEKU.example.com", "selfsigned-inadequateEKU"}, 51 {"self-signed-end-entity-with-cA-true.example.com", 52 "self-signed-EE-with-cA-true"}, 53 {"ca-used-as-end-entity.example.com", "ca-used-as-end-entity"}, 54 {"ca-used-as-end-entity-name-mismatch.example.com", 55 "ca-used-as-end-entity"}, 56 // All of include-subdomains.pinning.example.com is pinned to End Entity 57 // Test Cert with nick default-ee. Any other nick will only 58 // pass pinning when security.cert_pinning.enforcement.level != strict and 59 // otherCA is added as a user-specified trust anchor. See StaticHPKPins.h. 60 {"include-subdomains.pinning.example.com", "default-ee"}, 61 {"good.include-subdomains.pinning.example.com", "default-ee"}, 62 {"bad.include-subdomains.pinning.example.com", "other-issuer-ee"}, 63 {"bad.include-subdomains.pinning.example.com.", "other-issuer-ee"}, 64 {"bad.include-subdomains.pinning.example.com..", "other-issuer-ee"}, 65 {"exclude-subdomains.pinning.example.com", "default-ee"}, 66 {"sub.exclude-subdomains.pinning.example.com", "other-issuer-ee"}, 67 {"test-mode.pinning.example.com", "other-issuer-ee"}, 68 {"unknownissuer.include-subdomains.pinning.example.com", "unknownissuer"}, 69 {"unknownissuer.test-mode.pinning.example.com", "unknownissuer"}, 70 {"nsCertTypeNotCritical.example.com", "nsCertTypeNotCritical"}, 71 {"nsCertTypeCriticalWithExtKeyUsage.example.com", 72 "nsCertTypeCriticalWithExtKeyUsage"}, 73 {"nsCertTypeCritical.example.com", "nsCertTypeCritical"}, 74 {"end-entity-issued-by-v1-cert.example.com", "eeIssuedByV1Cert"}, 75 {"end-entity-issued-by-non-CA.example.com", "eeIssuedByNonCA"}, 76 {"inadequate-key-size-ee.example.com", "inadequateKeySizeEE"}, 77 {"badSubjectAltNames.example.com", "badSubjectAltNames"}, 78 {"ipAddressAsDNSNameInSAN.example.com", "ipAddressAsDNSNameInSAN"}, 79 {"noValidNames.example.com", "noValidNames"}, 80 {"bug413909.xn--hxajbheg2az3al.xn--jxalpdlp", "idn-certificate"}, 81 {"emptyissuername.example.com", "emptyIssuerName"}, 82 {"ev-test.example.com", "ev-test"}, 83 {"ee-from-missing-intermediate.example.com", 84 "ee-from-missing-intermediate"}, 85 {"imminently-distrusted.example.com", "ee-imminently-distrusted"}, 86 {"localhost", "unknownissuer"}, 87 {"a.pinning.example.com", "default-ee"}, 88 {"b.pinning.example.com", "default-ee"}, 89 {"not-preloaded.example.com", "default-ee"}, 90 {"ee.example.com", "default-ee"}, 91 {"requireclientauth.example.com", "default-ee"}, 92 {nullptr, nullptr}}; 93 94 int32_t DoSNISocketConfigBySubjectCN(PRFileDesc* aFd, 95 const SECItem* aSrvNameArr, 96 uint32_t aSrvNameArrSize) { 97 for (uint32_t i = 0; i < aSrvNameArrSize; i++) { 98 UniquePORTString name( 99 static_cast<char*>(PORT_ZAlloc(aSrvNameArr[i].len + 1))); 100 if (name) { 101 PORT_Memcpy(name.get(), aSrvNameArr[i].data, aSrvNameArr[i].len); 102 if (ConfigSecureServerWithNamedCert(aFd, name.get(), nullptr, nullptr, 103 nullptr) == SECSuccess) { 104 return 0; 105 } 106 } 107 } 108 109 return SSL_SNI_SEND_ALERT; 110 } 111 112 int32_t DoSNISocketConfig(PRFileDesc* aFd, const SECItem* aSrvNameArr, 113 uint32_t aSrvNameArrSize, void* aArg) { 114 const BadCertAndPinningHost* host = 115 GetHostForSNI(aSrvNameArr, aSrvNameArrSize, sBadCertAndPinningHosts); 116 if (!host) { 117 // No static cert <-> hostname mapping found. This happens when we use a 118 // collection of certificates in a given directory and build a cert DB at 119 // runtime, rather than using an NSS cert DB populated at build time. 120 // (This will be the default in the future.) 121 // For all given server names, check if the runtime-built cert DB contains 122 // a certificate with a matching subject CN. 123 return DoSNISocketConfigBySubjectCN(aFd, aSrvNameArr, aSrvNameArrSize); 124 } 125 126 if (gDebugLevel >= DEBUG_VERBOSE) { 127 fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName); 128 } 129 130 UniqueCERTCertificate cert; 131 SSLKEAType certKEA; 132 if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, host->mCertName, &cert, 133 &certKEA, nullptr)) { 134 return SSL_SNI_SEND_ALERT; 135 } 136 137 const char* kRequireClientAuthHostname = "requireclientauth.example.com"; 138 if (strncmp(host->mHostName, kRequireClientAuthHostname, 139 std::string::traits_type::length(kRequireClientAuthHostname)) == 140 0) { 141 (void)SSL_OptionSet(aFd, SSL_REQUEST_CERTIFICATE, true); 142 (void)SSL_OptionSet(aFd, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_ALWAYS); 143 } 144 145 return 0; 146 } 147 148 int main(int argc, char* argv[]) { 149 return StartServer(argc, argv, DoSNISocketConfig, nullptr); 150 }