DelegatedCredentialsServer.cpp (4998B)
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 used to test Delegated Credentials 6 // (see: https://tools.ietf.org/html/draft-ietf-tls-subcerts-03). 7 // 8 // The client is expected to connect, initiate an SSL handshake (with SNI 9 // to indicate which "server" to connect to), and verify the certificate. 10 // If all is good, the client then sends one encrypted byte and receives that 11 // same byte back. 12 // This server also has the ability to "call back" another process waiting on 13 // it. That is, when the server is all set up and ready to receive connections, 14 // it will connect to a specified port and issue a simple HTTP request. 15 16 #include <iostream> 17 18 #include "TLSServer.h" 19 20 #include "sslexp.h" 21 22 using namespace mozilla; 23 using namespace mozilla::test; 24 25 struct DelegatedCertHost { 26 const char* mHostName; 27 const char* mCertName; 28 const char* mDCKeyNick; 29 bool mEnableDelegatedCredentials; 30 }; 31 32 const PRUint32 kDCValidFor = 60 * 60 * 24 * 7 /* 1 week (seconds) */; 33 34 // {host, eeCert, dcCert, enableDC} 35 const DelegatedCertHost sDelegatedCertHosts[] = { 36 {"delegated-enabled.example.com", "delegated-ee", "delegated.key", true}, 37 {"standard-enabled.example.com", "default-ee", "delegated.key", true}, 38 {"delegated-disabled.example.com", "delegated-ee", 39 /* anything non-null */ "delegated.key", false}, 40 {nullptr, nullptr, nullptr, false}}; 41 42 int32_t DoSNISocketConfig(PRFileDesc* aFd, const SECItem* aSrvNameArr, 43 uint32_t aSrvNameArrSize, void* aArg) { 44 const DelegatedCertHost* host = 45 GetHostForSNI(aSrvNameArr, aSrvNameArrSize, sDelegatedCertHosts); 46 if (!host) { 47 return SSL_SNI_SEND_ALERT; 48 } 49 50 if (gDebugLevel >= DEBUG_VERBOSE) { 51 std::cerr << "Identified host " << host->mHostName << '\n'; 52 } 53 54 UniqueCERTCertificate delegatorCert( 55 PK11_FindCertFromNickname(host->mCertName, nullptr)); 56 if (!delegatorCert) { 57 PrintPRError("PK11_FindCertFromNickname failed"); 58 return SSL_SNI_SEND_ALERT; 59 } 60 61 UniquePK11SlotInfo slot(PK11_GetInternalKeySlot()); 62 if (!slot) { 63 PrintPRError("PK11_GetInternalKeySlot failed"); 64 return SSL_SNI_SEND_ALERT; 65 } 66 67 SSLExtraServerCertData extra_data = {ssl_auth_null, 68 /* Filled in by callee */ nullptr, 69 nullptr, 70 nullptr, 71 /* DC */ nullptr, 72 /* DC PrivKey */ nullptr}; 73 74 UniqueSECKEYPrivateKey delegatorPriv( 75 PK11_FindKeyByDERCert(slot.get(), delegatorCert.get(), nullptr)); 76 if (!delegatorPriv) { 77 PrintPRError("PK11_FindKeyByDERCert failed"); 78 return SSL_SNI_SEND_ALERT; 79 } 80 81 // Find the DC keypair by the file (nick) name. 82 ScopedAutoSECItem dc; 83 UniqueSECKEYPrivateKey dcPriv; 84 if (host->mEnableDelegatedCredentials) { 85 if (gDebugLevel >= DEBUG_VERBOSE) { 86 std::cerr << "Enabling a delegated credential for host " 87 << host->mHostName << '\n'; 88 } 89 90 if (PK11_NeedLogin(slot.get())) { 91 SECStatus rv = PK11_Authenticate(slot.get(), PR_TRUE, nullptr); 92 if (rv != SECSuccess) { 93 PrintPRError("PK11_Authenticate failed"); 94 return SSL_SNI_SEND_ALERT; 95 } 96 } 97 UniqueSECKEYPrivateKeyList list(PK11_ListPrivKeysInSlot( 98 slot.get(), const_cast<char*>(host->mDCKeyNick), nullptr)); 99 if (!list) { 100 PrintPRError("PK11_ListPrivKeysInSlot failed"); 101 return SSL_SNI_SEND_ALERT; 102 } 103 SECKEYPrivateKeyListNode* node = PRIVKEY_LIST_HEAD(list); 104 105 dcPriv.reset(SECKEY_CopyPrivateKey(node->key)); 106 if (!dcPriv) { 107 PrintPRError("PK11_ListPrivKeysInSlot could not find dcPriv"); 108 return SSL_SNI_SEND_ALERT; 109 } 110 111 UniqueSECKEYPublicKey dcPub(SECKEY_ConvertToPublicKey(dcPriv.get())); 112 if (!dcPub) { 113 PrintPRError("SECKEY_ConvertToPublicKey failed"); 114 return SSL_SNI_SEND_ALERT; 115 } 116 117 // Create and set the DC. 118 if (SSL_DelegateCredential(delegatorCert.get(), delegatorPriv.get(), 119 dcPub.get(), ssl_sig_ecdsa_secp384r1_sha384, 120 kDCValidFor, PR_Now(), &dc) != SECSuccess) { 121 PrintPRError("SSL_DelegateCredential failed"); 122 return SSL_SNI_SEND_ALERT; 123 } 124 extra_data.delegCred = &dc; 125 extra_data.delegCredPrivKey = dcPriv.get(); 126 127 // The list should only have a single key. 128 PORT_Assert(PRIVKEY_LIST_END(PRIVKEY_LIST_NEXT(node), list)); 129 } 130 131 if (ConfigSecureServerWithNamedCert(aFd, host->mCertName, nullptr, nullptr, 132 &extra_data) != SECSuccess) { 133 PrintPRError("ConfigSecureServerWithNamedCert failed"); 134 return SSL_SNI_SEND_ALERT; 135 } 136 137 return 0; 138 } 139 140 int main(int argc, char* argv[]) { 141 return StartServer(argc, argv, DoSNISocketConfig, nullptr); 142 }