From 17ccef2b9f0c71b60d31b84b8824215ff87f03aa Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Thu, 26 Jul 2018 16:15:41 +0000 Subject: SERVER-35418 Allow specifying CAs for incoming and outgoing connections separately --- src/mongo/util/net/ssl_manager_windows.cpp | 69 +++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'src/mongo/util/net/ssl_manager_windows.cpp') diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp index c5dcc4c865e..7ac11406796 100644 --- a/src/mongo/util/net/ssl_manager_windows.cpp +++ b/src/mongo/util/net/ssl_manager_windows.cpp @@ -297,7 +297,15 @@ private: SSLX509Name* subjectName, Date_t* serverCertificateExpirationDate); - Status _initChainEngines(bool hasCAFile); + struct CAEngine { + CERT_CHAIN_ENGINE_CONFIG machineConfig; + UniqueCertChainEngine machine; + CERT_CHAIN_ENGINE_CONFIG userConfig; + UniqueCertChainEngine user; + UniqueCertStore CAstore; + }; + + Status _initChainEngines(CAEngine* engine); private: bool _weakValidation; @@ -314,17 +322,21 @@ private: std::array _clientCertificates; std::array _serverCertificates; - UniqueCertificate _sslCertificate; - UniqueCertificate _sslClusterCertificate; - - UniqueCertStore _certStore; + /* _clientEngine represents the CA to use when acting as a client + * and validating remotes during outbound connections. + * This comes from, in order, --tlsCAFile, or the system CA. + */ + CAEngine _clientEngine; - std::array _additionalCertStores; - CERT_CHAIN_ENGINE_CONFIG _chainEngineConfigMachine; - UniqueCertChainEngine _chainEngineMachine; + /* _serverEngine represents the CA to use when acting as a server + * and validating remotes during inbound connections. + * This comes from --tlsClusterCAFile, if available, + * otherwise it inherits from _clientEngine. + */ + CAEngine _serverEngine; - CERT_CHAIN_ENGINE_CONFIG _chainEngineConfigUser; - UniqueCertChainEngine _chainEngineUser; + UniqueCertificate _sslCertificate; + UniqueCertificate _sslClusterCertificate; }; MONGO_INITIALIZER(SSLManager)(InitializerContext*) { @@ -411,7 +423,8 @@ SSLManagerWindows::SSLManagerWindows(const SSLParams& params, bool isServer) CertificateExpirationMonitor(_sslConfiguration.serverCertificateExpirationDate); } - uassertStatusOK(_initChainEngines(!params.sslCAFile.empty())); + uassertStatusOK(_initChainEngines(&_serverEngine)); + uassertStatusOK(_initChainEngines(&_clientEngine)); } StatusWith initChainEngine(CERT_CHAIN_ENGINE_CONFIG* chainEngineConfig, @@ -439,23 +452,23 @@ StatusWith initChainEngine(CERT_CHAIN_ENGINE_CONFIG* chai return {chainEngine}; } -Status SSLManagerWindows::_initChainEngines(bool hasCAFile) { - auto swMachine = - initChainEngine(&_chainEngineConfigMachine, _certStore, CERT_CHAIN_USE_LOCAL_MACHINE_STORE); +Status SSLManagerWindows::_initChainEngines(CAEngine* engine) { + auto swMachine = initChainEngine( + &engine->machineConfig, engine->CAstore, CERT_CHAIN_USE_LOCAL_MACHINE_STORE); if (!swMachine.isOK()) { return swMachine.getStatus(); } - _chainEngineMachine = std::move(swMachine.getValue()); + engine->machine = std::move(swMachine.getValue()); - auto swUser = initChainEngine(&_chainEngineConfigUser, _certStore, 0); + auto swUser = initChainEngine(&engine->userConfig, engine->CAstore, 0); if (!swUser.isOK()) { return swUser.getStatus(); } - _chainEngineUser = std::move(swUser.getValue()); + engine->user = std::move(swUser.getValue()); return Status::OK(); } @@ -1180,7 +1193,18 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) { return swChain.getStatus(); } - _certStore = std::move(swChain.getValue()); + _clientEngine.CAstore = std::move(swChain.getValue()); + } + + const auto serverCAFile = + params.sslClusterCAFile.empty() ? params.sslCAFile : params.sslClusterCAFile; + if (!serverCAFile.empty()) { + auto swChain = readCertChains(serverCAFile, params.sslCRLFile); + if (!swChain.isOK()) { + return swChain.getStatus(); + } + + _serverEngine.CAstore = std::move(swChain.getValue()); } if (hasCertificateSelector(params.sslCertificateSelector)) { @@ -1228,7 +1252,6 @@ Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred, cred->dwVersion = SCHANNEL_CRED_VERSION; cred->dwFlags = SCH_USE_STRONG_CRYPTO; // Use strong crypto; - cred->hRootStore = _certStore; uint32_t supportedProtocols = 0; @@ -1236,6 +1259,7 @@ Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred, supportedProtocols = SP_PROT_TLS1_SERVER | SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER; + cred->hRootStore = _serverEngine.CAstore; cred->dwFlags = cred->dwFlags // flags | SCH_CRED_REVOCATION_CHECK_CHAIN // Check certificate revocation | SCH_CRED_SNI_CREDENTIAL // Pass along SNI creds @@ -1246,6 +1270,7 @@ Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred, supportedProtocols = SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + cred->hRootStore = _clientEngine.CAstore; cred->dwFlags = cred->dwFlags // Flags | SCH_CRED_REVOCATION_CHECK_CHAIN // Check certificate revocation | SCH_CRED_NO_SERVERNAME_CHECK // Do not validate server name against cert @@ -1702,10 +1727,12 @@ StatusWith> SSLManagerWindows::parseAndValidatePeer UniqueCertificate certHolder(cert); SSLX509Name peerSubjectName; + auto* engine = remoteHost.empty() ? &_serverEngine : &_clientEngine; + // Validate against the local machine store first since it is easier to manage programmatically. Status validateCertMachine = validatePeerCertificate(remoteHost, certHolder.get(), - _chainEngineMachine, + engine->machine, _allowInvalidCertificates, _allowInvalidHostnames, &peerSubjectName); @@ -1714,7 +1741,7 @@ StatusWith> SSLManagerWindows::parseAndValidatePeer // manage. Status validateCertUser = validatePeerCertificate(remoteHost, certHolder.get(), - _chainEngineUser, + engine->user, _allowInvalidCertificates, _allowInvalidHostnames, &peerSubjectName); -- cgit v1.2.1