1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kNetwork
32 
33 #include "mongo/platform/basic.h"
34 
35 #include "mongo/util/net/ssl_manager.h"
36 
37 #include <boost/algorithm/string.hpp>
38 #include <boost/date_time/posix_time/posix_time.hpp>
39 #include <fstream>
40 #include <iostream>
41 #include <sstream>
42 #include <stack>
43 #include <string>
44 #include <vector>
45 
46 #include "mongo/base/init.h"
47 #include "mongo/bson/bsonobjbuilder.h"
48 #include "mongo/config.h"
49 #include "mongo/db/server_parameters.h"
50 #include "mongo/platform/atomic_word.h"
51 #include "mongo/stdx/memory.h"
52 #include "mongo/transport/session.h"
53 #include "mongo/util/concurrency/mutex.h"
54 #include "mongo/util/debug_util.h"
55 #include "mongo/util/exit.h"
56 #include "mongo/util/hex.h"
57 #include "mongo/util/log.h"
58 #include "mongo/util/mongoutils/str.h"
59 #include "mongo/util/net/private/ssl_expiration.h"
60 #include "mongo/util/net/sock.h"
61 #include "mongo/util/net/socket_exception.h"
62 #include "mongo/util/net/ssl_options.h"
63 #include "mongo/util/net/ssl_types.h"
64 #include "mongo/util/scopeguard.h"
65 #include "mongo/util/text.h"
66 
67 #ifdef MONGO_CONFIG_SSL
68 #include <openssl/asn1.h>
69 #include <openssl/asn1t.h>
70 #include <openssl/evp.h>
71 #include <openssl/x509_vfy.h>
72 #include <openssl/x509v3.h>
73 #if defined(_WIN32)
74 #include <wincrypt.h>
75 #elif defined(__APPLE__)
76 #include <Security/Security.h>
77 #endif
78 #endif
79 
80 namespace mongo {
81 
82 namespace {
83 
removeFQDNRoot(std::string name)84 std::string removeFQDNRoot(std::string name) {
85     if (name.back() == '.') {
86         name.pop_back();
87     }
88     return name;
89 };
90 
91 #ifdef MONGO_CONFIG_SSL
92 struct UniqueX509StoreCtxDeleter {
operator ()mongo::__anon25b3b6780111::UniqueX509StoreCtxDeleter93     void operator()(X509_STORE_CTX* ctx) {
94         if (ctx) {
95             ::X509_STORE_CTX_free(ctx);
96         }
97     }
98 };
99 using UniqueX509StoreCtx = std::unique_ptr<X509_STORE_CTX, UniqueX509StoreCtxDeleter>;
100 #endif
101 
102 // Because the hostname having a slash is used by `mongo::SockAddr` to determine if a hostname is a
103 // Unix Domain Socket endpoint, this function uses the same logic.  (See
104 // `mongo::SockAddr::Sockaddr(StringData, int, sa_family_t)`).  A user explicitly specifying a Unix
105 // Domain Socket in the present working directory, through a code path which supplies `sa_family_t`
106 // as `AF_UNIX` will cause this code to lie.  This will, in turn, cause the
107 // `SSLManager::parseAndValidatePeerCertificate` code to believe a socket is a host, which will then
108 // cause a connection failure if and only if that domain socket also has a certificate for SSL and
109 // the connection is an SSL connection.
isUnixDomainSocket(const std::string & hostname)110 bool isUnixDomainSocket(const std::string& hostname) {
111     return end(hostname) != std::find(begin(hostname), end(hostname), '/');
112 }
113 
114 const transport::Session::Decoration<SSLPeerInfo> peerInfoForSession =
115     transport::Session::declareDecoration<SSLPeerInfo>();
116 
117 /**
118  * Configurable via --setParameter disableNonSSLConnectionLogging=true. If false (default)
119  * if the sslMode is set to preferSSL, we will log connections that are not using SSL.
120  * If true, such log messages will be suppressed.
121  */
122 ExportedServerParameter<bool, ServerParameterType::kStartupOnly>
123     disableNonSSLConnectionLoggingParameter(ServerParameterSet::getGlobal(),
124                                             "disableNonSSLConnectionLogging",
125                                             &sslGlobalParams.disableNonSSLConnectionLogging);
126 
127 ExportedServerParameter<std::string, ServerParameterType::kStartupOnly>
128     setDiffieHellmanParameterPEMFile(ServerParameterSet::getGlobal(),
129                                      "opensslDiffieHellmanParameters",
130                                      &sslGlobalParams.sslPEMTempDHParam);
131 
132 ExportedServerParameter<bool, ServerParameterType::kStartupOnly>
133     suppressNoTLSPeerCertificateWarning(ServerParameterSet::getGlobal(),
134                                         "suppressNoTLSPeerCertificateWarning",
135                                         &sslGlobalParams.suppressNoTLSPeerCertificateWarning);
136 
137 ExportedServerParameter<bool, ServerParameterType::kStartupOnly> sslWithholdClientCertificate(
138     ServerParameterSet::getGlobal(),
139     "sslWithholdClientCertificate",
140     &sslGlobalParams.tlsWithholdClientCertificate);
141 
142 }  // namespace
143 
forSession(const transport::SessionHandle & session)144 SSLPeerInfo& SSLPeerInfo::forSession(const transport::SessionHandle& session) {
145     return peerInfoForSession(session.get());
146 }
147 
forSession(const transport::ConstSessionHandle & session)148 const SSLPeerInfo& SSLPeerInfo::forSession(const transport::ConstSessionHandle& session) {
149     return peerInfoForSession(session.get());
150 }
151 
152 SSLParams sslGlobalParams;
153 
getSSLGlobalParams()154 const SSLParams& getSSLGlobalParams() {
155     return sslGlobalParams;
156 }
157 
158 class OpenSSLCipherConfigParameter
159     : public ExportedServerParameter<std::string, ServerParameterType::kStartupOnly> {
160 public:
OpenSSLCipherConfigParameter()161     OpenSSLCipherConfigParameter()
162         : ExportedServerParameter<std::string, ServerParameterType::kStartupOnly>(
163               ServerParameterSet::getGlobal(),
164               "opensslCipherConfig",
165               &sslGlobalParams.sslCipherConfig) {}
validate(const std::string & potentialNewValue)166     Status validate(const std::string& potentialNewValue) final {
167         if (!sslGlobalParams.sslCipherConfig.empty()) {
168             return Status(
169                 ErrorCodes::BadValue,
170                 "opensslCipherConfig setParameter is incompatible with net.ssl.sslCipherConfig");
171         }
172         // Note that there is very little validation that we can do here.
173         // OpenSSL exposes no API to validate a cipher config string. The only way to figure out
174         // what a string maps to is to make an SSL_CTX object, set the string on it, then parse the
175         // resulting STACK_OF object. If provided an invalid entry in the string, it will silently
176         // ignore it. Because an entry in the string may map to multiple ciphers, or remove ciphers
177         // from the final set produced by the full string, we can't tell if any entry failed
178         // to parse.
179         return Status::OK();
180     }
181 } openSSLCipherConfig;
182 }  // namespace mongo
183 
184 #ifdef MONGO_CONFIG_SSL
185 namespace mongo {
186 namespace {
187 
188 // If the underlying SSL supports auto-configuration of ECDH parameters, this function will select
189 // it, otherwise this function will do nothing.
setECDHModeAuto(SSL_CTX * const ctx)190 void setECDHModeAuto(SSL_CTX* const ctx) {
191 #ifdef MONGO_CONFIG_HAVE_SSL_SET_ECDH_AUTO
192     SSL_CTX_set_ecdh_auto(ctx, true);
193 #endif
194     std::ignore = ctx;
195 }
196 
197 struct DHFreer {
operator ()mongo::__anon25b3b6780211::DHFreer198     void operator()(DH* const dh) noexcept {
199         if (dh) {
200             ::DH_free(dh);
201         }
202     }
203 };
204 using UniqueDHParams = std::unique_ptr<DH, DHFreer>;
205 
206 struct BIOFree {
operator ()mongo::__anon25b3b6780211::BIOFree207     void operator()(BIO* const p) noexcept {
208         // Assumes that BIO_free succeeds.
209         if (p) {
210             ::BIO_free(p);
211         }
212     }
213 };
214 using UniqueBIO = std::unique_ptr<BIO, BIOFree>;
215 
makeUniqueMemBio(std::vector<std::uint8_t> & v)216 UniqueBIO makeUniqueMemBio(std::vector<std::uint8_t>& v) {
217     UniqueBIO rv(::BIO_new_mem_buf(v.data(), v.size()));
218     if (!rv) {
219         class ssl_bad_alloc : public std::bad_alloc {
220         private:
221             std::string message;
222 
223         public:
224             explicit ssl_bad_alloc(std::string m) : message(std::move(m)) {}
225 
226             const char* what() const noexcept override {
227                 return message.c_str();
228             }
229         };
230         throw ssl_bad_alloc(str::stream()
231                             << "Error allocating SSL BIO: "
232                             << SSLManagerInterface::getSSLErrorMessage(ERR_get_error()));
233     }
234     return rv;
235 }
236 
237 // Old copies of OpenSSL will not have constants to disable protocols they don't support.
238 // Define them to values we can OR together safely to generically disable these protocols across
239 // all versions of OpenSSL.
240 #ifndef SSL_OP_NO_TLSv1_1
241 #define SSL_OP_NO_TLSv1_1 0
242 #endif
243 #ifndef SSL_OP_NO_TLSv1_2
244 #define SSL_OP_NO_TLSv1_2 0
245 #endif
246 #ifndef SSL_OP_NO_TLSv1_3
247 #define SSL_OP_NO_TLSv1_3 0
248 #endif
249 
250 // clang-format off
251 #ifndef MONGO_CONFIG_HAVE_ASN1_ANY_DEFINITIONS
252 // Copies of OpenSSL before 1.0.0 do not have ASN1_SEQUENCE_ANY, ASN1_SET_ANY, or the helper
253 // functions which let us deserialize these objects. We must polyfill the definitions to interact
254 // with ASN1 objects so stored.
255 typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
256 
257 ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
258     ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
259 ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
260 
261 ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
262     ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
263 ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
264 
265 IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY,
266                                             ASN1_SEQUENCE_ANY)
267 IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
268 ; // clang format needs to see a semicolon or it will start formatting unrelated code
269 #endif // MONGO_CONFIG_NEEDS_ASN1_ANY_DEFINITIONS
270 // clang-format on
271 
272 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
273     defined(LIBRESSL_VERSION_NUMBER)
274 // Copies of OpenSSL after 1.1.0 define new functions for interaction with
275 // X509 structure. We must polyfill used definitions to interact with older
276 // OpenSSL versions.
277 #ifndef LIBRESSL_VERSION_NUMBER
STACK_OF(X509_EXTENSION)278 const STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509* peerCert) {
279     return peerCert->cert_info->extensions;
280 }
X509_NAME_ENTRY_set(const X509_NAME_ENTRY * ne)281 inline int X509_NAME_ENTRY_set(const X509_NAME_ENTRY* ne) {
282     return ne->set;
283 }
284 #endif
285 
286 // On OpenSSL < 1.1.0, this chain isn't attached to
287 // the SSL session, so we need it to dispose of itself.
288 struct VerifiedChainDeleter {
operator ()mongo::__anon25b3b6780211::VerifiedChainDeleter289     void operator()(STACK_OF(X509) * chain) {
290         if (chain) {
291             sk_X509_pop_free(chain, X509_free);
292         }
293     }
294 };
295 
296 struct UniqueX509Deleter {
operator ()mongo::__anon25b3b6780211::UniqueX509Deleter297     void operator()(X509* cert) {
298         if (cert) {
299             X509_free(cert);
300         }
301     }
302 };
303 using UniqueX509 = std::unique_ptr<X509, UniqueX509Deleter>;
304 
STACK_OF(X509)305 STACK_OF(X509) * SSL_get0_verified_chain(SSL* s) {
306     auto* store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s));
307     UniqueX509 peer(SSL_get_peer_certificate(s));
308     auto* peerChain = SSL_get_peer_cert_chain(s);
309 
310     UniqueX509StoreCtx ctx(X509_STORE_CTX_new());
311     if (!X509_STORE_CTX_init(ctx.get(), store, peer.get(), peerChain)) {
312         return nullptr;
313     }
314 
315     if (X509_verify_cert(ctx.get()) <= 0) {
316         return nullptr;
317     }
318 
319     return X509_STORE_CTX_get1_chain(ctx.get());
320 }
321 
322 #else
323 // No-op deleter for OpenSSL >= 1.1.0
324 struct VerifiedChainDeleter {
operator ()mongo::__anon25b3b6780211::VerifiedChainDeleter325     void operator()(STACK_OF(X509) * chain) {}
326 };
327 #endif
328 
329 using UniqueVerifiedChainPolyfill = std::unique_ptr<STACK_OF(X509), VerifiedChainDeleter>;
SSLgetVerifiedChain(SSL * s)330 UniqueVerifiedChainPolyfill SSLgetVerifiedChain(SSL* s) {
331     return UniqueVerifiedChainPolyfill(SSL_get0_verified_chain(s));
332 }
333 
334 /**
335  * Multithreaded Support for SSL.
336  *
337  * In order to allow OpenSSL to work in a multithreaded environment, you
338  * may need to provide some callbacks for it to use for locking. The following code
339  * sets up a vector of mutexes and provides a thread unique ID number.
340  * The so-called SSLThreadInfo class encapsulates most of the logic required for
341  * OpenSSL multithreaded support.
342  *
343  * OpenSSL before version 1.1.0 requires applications provide a callback which emits a thread
344  * identifier. This ID is used to store thread specific ERR information. When a thread is
345  * terminated, it must call ERR_remove_state or ERR_remove_thread_state. These functions may
346  * themselves invoke the application provided callback. These IDs are stored in a hashtable with
347  * a questionable hash function. They must be uniformly distributed to prevent collisions.
348  */
349 class SSLThreadInfo {
350 public:
getID()351     static unsigned long getID() {
352         struct CallErrRemoveState {
353             explicit CallErrRemoveState(ThreadIDManager& manager, unsigned long id)
354                 : _manager(manager), id(id) {}
355 
356             ~CallErrRemoveState() {
357                 ERR_remove_state(0);
358                 _manager.releaseID(id);
359             };
360 
361             ThreadIDManager& _manager;
362             unsigned long id;
363         };
364 
365         // NOTE: This logic is fully intentional. Because ERR_remove_state (called within
366         // the destructor of the kRemoveStateFromThread object) re-enters this function,
367         // we must have a two phase protection, otherwise we would access a thread local
368         // during its destruction.
369         static thread_local boost::optional<CallErrRemoveState> threadLocalState;
370         if (!threadLocalState) {
371             threadLocalState.emplace(_idManager, _idManager.reserveID());
372         }
373 
374         return threadLocalState->id;
375     }
376 
lockingCallback(int mode,int type,const char * file,int line)377     static void lockingCallback(int mode, int type, const char* file, int line) {
378         if (mode & CRYPTO_LOCK) {
379             _mutex[type]->lock();
380         } else {
381             _mutex[type]->unlock();
382         }
383     }
384 
init()385     static void init() {
386         CRYPTO_set_id_callback(&SSLThreadInfo::getID);
387         CRYPTO_set_locking_callback(&SSLThreadInfo::lockingCallback);
388 
389         while ((int)_mutex.size() < CRYPTO_num_locks()) {
390             _mutex.emplace_back(stdx::make_unique<stdx::recursive_mutex>());
391         }
392     }
393 
394 private:
395     SSLThreadInfo() = delete;
396 
397     // Note: see SERVER-8734 for why we are using a recursive mutex here.
398     // Once the deadlock fix in OpenSSL is incorporated into most distros of
399     // Linux, this can be changed back to a nonrecursive mutex.
400     static std::vector<std::unique_ptr<stdx::recursive_mutex>> _mutex;
401 
402     class ThreadIDManager {
403     public:
reserveID()404         unsigned long reserveID() {
405             stdx::unique_lock<stdx::mutex> lock(_idMutex);
406             if (!_idLast.empty()) {
407                 unsigned long ret = _idLast.top();
408                 _idLast.pop();
409                 return ret;
410             }
411             return ++_idNext;
412         }
413 
releaseID(unsigned long id)414         void releaseID(unsigned long id) {
415             stdx::unique_lock<stdx::mutex> lock(_idMutex);
416             _idLast.push(id);
417         }
418 
419     private:
420         // Machinery for producing IDs that are unique for the life of a thread.
421         stdx::mutex _idMutex;       // Protects _idNext and _idLast.
422         unsigned long _idNext = 0;  // Stores the next thread ID to use, if none already allocated.
423         std::stack<unsigned long, std::vector<unsigned long>>
424             _idLast;  // Stores old thread IDs, for reuse.
425     };
426     static ThreadIDManager _idManager;
427 };
428 std::vector<std::unique_ptr<stdx::recursive_mutex>> SSLThreadInfo::_mutex;
429 SSLThreadInfo::ThreadIDManager SSLThreadInfo::_idManager;
430 
431 namespace {
432 // We only want to free SSL_CTX objects if they have been populated. OpenSSL seems to perform this
433 // check before freeing them, but because it does not document this, we should protect ourselves.
free_ssl_context(SSL_CTX * ctx)434 void free_ssl_context(SSL_CTX* ctx) {
435     if (ctx != nullptr) {
436         SSL_CTX_free(ctx);
437     }
438 }
439 
getRawSNIServerName(const SSL * const ssl)440 boost::optional<std::string> getRawSNIServerName(const SSL* const ssl) {
441     const char* const name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
442     if (!name) {
443         return boost::none;
444     }
445     return std::string(name);
446 }
447 }  // namespace
448 
449 ////////////////////////////////////////////////////////////////
450 
451 SimpleMutex sslManagerMtx;
452 SSLManagerInterface* theSSLManager = NULL;
453 using UniqueSSLContext = std::unique_ptr<SSL_CTX, decltype(&free_ssl_context)>;
454 static const int BUFFER_SIZE = 8 * 1024;
455 static const int DATE_LEN = 128;
456 
457 class SSLManager : public SSLManagerInterface {
458 public:
459     explicit SSLManager(const SSLParams& params, bool isServer);
460 
461     /**
462      * Initializes an OpenSSL context according to the provided settings. Only settings which are
463      * acceptable on non-blocking connections are set.
464      */
465     Status initSSLContext(SSL_CTX* context,
466                           const SSLParams& params,
467                           ConnectionDirection direction) final;
468 
469     virtual SSLConnection* connect(Socket* socket);
470 
471     virtual SSLConnection* accept(Socket* socket, const char* initialBytes, int len);
472 
473     SSLPeerInfo parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn,
474                                                           const std::string& remoteHost,
475                                                           const HostAndPort& hostForLogging) final;
476 
477     StatusWith<SSLPeerInfo> parseAndValidatePeerCertificate(
478         SSL* conn, const std::string& remoteHost, const HostAndPort& hostForLogging) final;
479 
getSSLConfiguration() const480     virtual const SSLConfiguration& getSSLConfiguration() const {
481         return _sslConfiguration;
482     }
483 
484     virtual int SSL_read(SSLConnection* conn, void* buf, int num);
485 
486     virtual int SSL_write(SSLConnection* conn, const void* buf, int num);
487 
488     virtual unsigned long ERR_get_error();
489 
490     virtual char* ERR_error_string(unsigned long e, char* buf);
491 
492     virtual int SSL_get_error(const SSLConnection* conn, int ret);
493 
494     virtual int SSL_shutdown(SSLConnection* conn);
495 
496     virtual void SSL_free(SSLConnection* conn);
497 
498 private:
499     const int _rolesNid = OBJ_create(mongodbRolesOID.identifier.c_str(),
500                                      mongodbRolesOID.shortDescription.c_str(),
501                                      mongodbRolesOID.longDescription.c_str());
502     UniqueSSLContext _serverContext;  // SSL context for incoming connections
503     UniqueSSLContext _clientContext;  // SSL context for outgoing connections
504     bool _weakValidation;
505     bool _allowInvalidCertificates;
506     bool _allowInvalidHostnames;
507     bool _suppressNoCertificateWarning;
508     SSLConfiguration _sslConfiguration;
509 
510     /**
511      * creates an SSL object to be used for this file descriptor.
512      * caller must SSL_free it.
513      */
514     SSL* _secure(SSL_CTX* context, int fd);
515 
516     /**
517      * Given an error code from an SSL-type IO function, logs an
518      * appropriate message and throws a SocketException.
519      */
520     MONGO_COMPILER_NORETURN void _handleSSLError(SSLConnection* conn, int ret);
521 
522     /*
523      * Init the SSL context using parameters provided in params. This SSL context will
524      * be configured for blocking send/receive.
525      */
526     bool _initSynchronousSSLContext(UniqueSSLContext* context,
527                                     const SSLParams& params,
528                                     ConnectionDirection direction);
529 
530     /*
531      * Converts time from OpenSSL return value to unsigned long long
532      * representing the milliseconds since the epoch.
533      */
534     unsigned long long _convertASN1ToMillis(ASN1_TIME* t);
535 
536     /*
537      * Parse and store x509 subject name from the PEM keyfile.
538      * For server instances check that PEM certificate is not expired
539      * and extract server certificate notAfter date.
540      * @param keyFile referencing the PEM file to be read.
541      * @param subjectName as a pointer to the subject name variable being set.
542      * @param serverNotAfter a Date_t object pointer that is valued if the
543      * date is to be checked (as for a server certificate) and null otherwise.
544      * @return bool showing if the function was successful.
545      */
546     bool _parseAndValidateCertificate(const std::string& keyFile,
547                                       const std::string& keyPassword,
548                                       SSLX509Name* subjectName,
549                                       Date_t* serverNotAfter);
550 
551 
552     StatusWith<stdx::unordered_set<RoleName>> _parsePeerRoles(X509* peerCert) const;
553 
554     /** @return true if was successful, otherwise false */
555     bool _setupPEM(SSL_CTX* context, const std::string& keyFile, const std::string& password);
556 
557     /*
558      * Set up an SSL context for certificate validation by loading a CA
559      */
560     Status _setupCA(SSL_CTX* context, const std::string& caFile);
561 
562     /*
563      * Set up an SSL context for certificate validation by loading the system's CA store
564      */
565     Status _setupSystemCA(SSL_CTX* context);
566 
567     /*
568      * Import a certificate revocation list into an SSL context
569      * for use with validating certificates
570      */
571     bool _setupCRL(SSL_CTX* context, const std::string& crlFile);
572 
573     /*
574      * sub function for checking the result of an SSL operation
575      */
576     bool _doneWithSSLOp(SSLConnection* conn, int status);
577 
578     /*
579      * Send and receive network data
580      */
581     void _flushNetworkBIO(SSLConnection* conn);
582 
583     /**
584      * Callbacks for SSL functions.
585      */
586     static int password_cb(char* buf, int num, int rwflag, void* userdata);
587     static int servername_cb(SSL* s, int* al, void* arg);
588     static int verify_cb(int ok, X509_STORE_CTX* ctx);
589 };
590 
setupFIPS()591 void setupFIPS() {
592 // Turn on FIPS mode if requested, OPENSSL_FIPS must be defined by the OpenSSL headers
593 #if defined(MONGO_CONFIG_HAVE_FIPS_MODE_SET)
594     int status = FIPS_mode_set(1);
595     if (!status) {
596         severe() << "can't activate FIPS mode: "
597                  << SSLManagerInterface::getSSLErrorMessage(ERR_get_error());
598         fassertFailedNoTrace(16703);
599     }
600     log() << "FIPS 140-2 mode activated";
601 #else
602     severe() << "this version of mongodb was not compiled with FIPS support";
603     fassertFailedNoTrace(17089);
604 #endif
605 }
606 
607 }  // namespace
608 
609 // Global variable indicating if this is a server or a client instance
610 bool isSSLServer = false;
611 
612 
MONGO_INITIALIZER(SetupOpenSSL)613 MONGO_INITIALIZER(SetupOpenSSL)(InitializerContext*) {
614     SSL_library_init();
615     SSL_load_error_strings();
616     ERR_load_crypto_strings();
617 
618     if (sslGlobalParams.sslFIPSMode) {
619         setupFIPS();
620     }
621 
622     // Add all digests and ciphers to OpenSSL's internal table
623     // so that encryption/decryption is backwards compatible
624     OpenSSL_add_all_algorithms();
625 
626     // Setup OpenSSL multithreading callbacks and mutexes
627     SSLThreadInfo::init();
628 
629     return Status::OK();
630 }
631 
632 MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("SetupOpenSSL"))(InitializerContext*) {
633     stdx::lock_guard<SimpleMutex> lck(sslManagerMtx);
634     if (!isSSLServer || (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled)) {
635         theSSLManager = new SSLManager(sslGlobalParams, isSSLServer);
636     }
637     return Status::OK();
638 }
639 
create(const SSLParams & params,bool isServer)640 std::unique_ptr<SSLManagerInterface> SSLManagerInterface::create(const SSLParams& params,
641                                                                  bool isServer) {
642     return stdx::make_unique<SSLManager>(params, isServer);
643 }
644 
getSSLManager()645 SSLManagerInterface* getSSLManager() {
646     stdx::lock_guard<SimpleMutex> lck(sslManagerMtx);
647     if (theSSLManager)
648         return theSSLManager;
649     return NULL;
650 }
651 
getCertificateSubjectX509Name(X509 * cert)652 SSLX509Name getCertificateSubjectX509Name(X509* cert) {
653     std::vector<std::vector<SSLX509Name::Entry>> entries;
654 
655     auto name = X509_get_subject_name(cert);
656     int count = X509_NAME_entry_count(name);
657     int prevSet = -1;
658     std::vector<SSLX509Name::Entry> rdn;
659     for (int i = count - 1; i >= 0; --i) {
660         auto* entry = X509_NAME_get_entry(name, i);
661 
662         const auto currentSet = X509_NAME_ENTRY_set(entry);
663         if (currentSet != prevSet) {
664             if (!rdn.empty()) {
665                 entries.push_back(std::move(rdn));
666                 rdn = std::vector<SSLX509Name::Entry>();
667             }
668             prevSet = currentSet;
669         }
670 
671         char buffer[128];
672         // OBJ_obj2txt can only fail if we pass a nullptr from get_object,
673         // or if OpenSSL's BN library falls over.
674         // In either case, just panic.
675         uassert(ErrorCodes::InvalidSSLConfiguration,
676                 "Unable to parse certiciate subject name",
677                 OBJ_obj2txt(buffer, sizeof(buffer), X509_NAME_ENTRY_get_object(entry), 1) > 0);
678 
679         const auto* str = X509_NAME_ENTRY_get_data(entry);
680         rdn.emplace_back(
681             buffer, str->type, std::string(reinterpret_cast<const char*>(str->data), str->length));
682     }
683     if (!rdn.empty()) {
684         entries.push_back(std::move(rdn));
685     }
686 
687     return SSLX509Name(std::move(entries));
688 }
689 
SSLConnection(SSL_CTX * context,Socket * sock,const char * initialBytes,int len)690 SSLConnection::SSLConnection(SSL_CTX* context, Socket* sock, const char* initialBytes, int len)
691     : socket(sock) {
692     ssl = SSL_new(context);
693 
694     std::string sslErr =
695         NULL != getSSLManager() ? getSSLManager()->getSSLErrorMessage(ERR_get_error()) : "";
696     massert(15861, "Error creating new SSL object " + sslErr, ssl);
697 
698     BIO_new_bio_pair(&internalBIO, BUFFER_SIZE, &networkBIO, BUFFER_SIZE);
699     SSL_set_bio(ssl, internalBIO, internalBIO);
700 
701     if (len > 0) {
702         int toBIO = BIO_write(networkBIO, initialBytes, len);
703         if (toBIO != len) {
704             LOG(3) << "Failed to write initial network data to the SSL BIO layer";
705             throw SocketException(SocketException::RECV_ERROR, socket->remoteString());
706         }
707     }
708 }
709 
~SSLConnection()710 SSLConnection::~SSLConnection() {
711     if (ssl) {  // The internalBIO is automatically freed as part of SSL_free
712         SSL_free(ssl);
713     }
714     if (networkBIO) {
715         BIO_free(networkBIO);
716     }
717 }
718 
719 namespace {
x509OidToShortName(const std::string & name)720 std::string x509OidToShortName(const std::string& name) {
721     const auto nid = OBJ_txt2nid(name.c_str());
722     if (nid == 0) {
723         return name;
724     }
725     const auto* sn = OBJ_nid2sn(nid);
726     if (!sn) {
727         return name;
728     }
729     return sn;
730 }
731 
732 // Characters that need to be escaped in RFC 2253
733 const std::array<char, 7> rfc2253EscapeChars = {',', '+', '"', '\\', '<', '>', ';'};
734 
735 // See section "2.4 Converting an AttributeValue from ASN.1 to a String" in RFC 2243
escapeRfc2253(StringData str)736 std::string escapeRfc2253(StringData str) {
737     std::string ret;
738 
739     if (str.size() > 0) {
740         size_t pos = 0;
741 
742         // a space or "#" character occurring at the beginning of the string
743         if (str[0] == ' ') {
744             ret = "\\ ";
745             pos = 1;
746         } else if (str[0] == '#') {
747             ret = "\\#";
748             pos = 1;
749         }
750 
751         while (pos < str.size()) {
752             if (static_cast<signed char>(str[pos]) < 0) {
753                 ret += '\\';
754                 ret += integerToHex(str[pos]);
755             } else {
756                 if (std::find(rfc2253EscapeChars.cbegin(), rfc2253EscapeChars.cend(), str[pos]) !=
757                     rfc2253EscapeChars.cend()) {
758                     ret += '\\';
759                 }
760 
761                 ret += str[pos];
762             }
763             ++pos;
764         }
765 
766         // a space character occurring at the end of the string
767         if (ret.size() > 2 && ret[ret.size() - 1] == ' ') {
768             ret[ret.size() - 1] = '\\';
769             ret += ' ';
770         }
771     }
772 
773     return ret;
774 }
775 
776 TLSVersionCounts tlsVersionCounts;
777 
778 }  // namespace
779 
get()780 TLSVersionCounts& TLSVersionCounts::get() {
781     return tlsVersionCounts;
782 }
783 
getOID(StringData oid) const784 StatusWith<std::string> SSLX509Name::getOID(StringData oid) const {
785     for (const auto& rdn : _entries) {
786         for (const auto& entry : rdn) {
787             if (entry.oid == oid) {
788                 return entry.value;
789             }
790         }
791     }
792     return {ErrorCodes::KeyNotFound, "OID does not exist"};
793 }
794 
operator <<(StringBuilder & os,const SSLX509Name & name)795 StringBuilder& operator<<(StringBuilder& os, const SSLX509Name& name) {
796     std::string comma;
797     for (const auto& rdn : name._entries) {
798         std::string plus;
799         os << comma;
800         for (const auto& entry : rdn) {
801             os << plus << x509OidToShortName(entry.oid) << "=" << escapeRfc2253(entry.value);
802             plus = "+";
803         }
804         comma = ",";
805     }
806     return os;
807 }
808 
toString() const809 std::string SSLX509Name::toString() const {
810     StringBuilder os;
811     os << *this;
812     return os.str();
813 }
814 
815 namespace {
canonicalizeClusterDN(std::vector<std::string> * dn)816 void canonicalizeClusterDN(std::vector<std::string>* dn) {
817     // remove all RDNs we don't care about
818     for (size_t i = 0; i < dn->size(); i++) {
819         std::string& comp = dn->at(i);
820         boost::algorithm::trim(comp);
821         if (!mongoutils::str::startsWith(comp.c_str(), "DC=") &&
822             !mongoutils::str::startsWith(comp.c_str(), "O=") &&
823             !mongoutils::str::startsWith(comp.c_str(), "OU=")) {
824             dn->erase(dn->begin() + i);
825             i--;
826         }
827     }
828     std::stable_sort(dn->begin(), dn->end());
829 }
830 
831 constexpr StringData kOID_DC = "0.9.2342.19200300.100.1.25"_sd;
832 constexpr StringData kOID_O = "2.5.4.10"_sd;
833 constexpr StringData kOID_OU = "2.5.4.11"_sd;
834 
canonicalizeClusterDN(const std::vector<std::vector<SSLX509Name::Entry>> & entries)835 std::vector<SSLX509Name::Entry> canonicalizeClusterDN(
836     const std::vector<std::vector<SSLX509Name::Entry>>& entries) {
837     std::vector<SSLX509Name::Entry> ret;
838 
839     for (const auto& rdn : entries) {
840         for (const auto& entry : rdn) {
841             if ((entry.oid != kOID_DC) && (entry.oid != kOID_O) && (entry.oid != kOID_OU)) {
842                 continue;
843             }
844             ret.push_back(entry);
845         }
846     }
847     std::stable_sort(ret.begin(), ret.end());
848     return ret;
849 }
850 }  // namespace
851 
852 /**
853  * The behavior of isClusterMember() is subtly different when passed
854  * an SSLX509Name versus a StringData.
855  *
856  * The SSLX509Name version (immediately below) compares distinguished
857  * names in their raw, unescaped forms and provides a more reliable match.
858  *
859  * The StringData version attempts to do a simplified string compare
860  * with the serialized version of the server subject name.
861  *
862  * Because escaping is not checked in the StringData version,
863  * some not-strictly matching RDNs will appear to share O/OU/DC with the
864  * server subject name.  Therefore, that variant should be called with care.
865  */
isClusterMember(const SSLX509Name & subject) const866 bool SSLConfiguration::isClusterMember(const SSLX509Name& subject) const {
867     auto client = canonicalizeClusterDN(subject._entries);
868     auto server = canonicalizeClusterDN(serverSubjectName._entries);
869 
870     return !client.empty() && (client == server);
871 }
872 
isClusterMember(StringData subjectName) const873 bool SSLConfiguration::isClusterMember(StringData subjectName) const {
874     std::vector<std::string> clientRDN = StringSplitter::split(subjectName.toString(), ",");
875     std::vector<std::string> serverRDN = StringSplitter::split(serverSubjectName.toString(), ",");
876 
877     canonicalizeClusterDN(&clientRDN);
878     canonicalizeClusterDN(&serverRDN);
879 
880     return !clientRDN.empty() && (clientRDN == serverRDN);
881 }
882 
getServerStatusBSON() const883 BSONObj SSLConfiguration::getServerStatusBSON() const {
884     BSONObjBuilder security;
885     security.append("SSLServerSubjectName", serverSubjectName.toString());
886     security.appendBool("SSLServerHasCertificateAuthority", hasCA);
887     security.appendDate("SSLServerCertificateExpirationDate", serverCertificateExpirationDate);
888     return security.obj();
889 }
890 
~SSLManagerInterface()891 SSLManagerInterface::~SSLManagerInterface() {}
892 
SSLManager(const SSLParams & params,bool isServer)893 SSLManager::SSLManager(const SSLParams& params, bool isServer)
894     : _serverContext(nullptr, free_ssl_context),
895       _clientContext(nullptr, free_ssl_context),
896       _weakValidation(params.sslWeakCertificateValidation),
897       _allowInvalidCertificates(params.sslAllowInvalidCertificates),
898       _allowInvalidHostnames(params.sslAllowInvalidHostnames),
899       _suppressNoCertificateWarning(params.suppressNoTLSPeerCertificateWarning) {
900     if (!_initSynchronousSSLContext(&_clientContext, params, ConnectionDirection::kOutgoing)) {
901         uasserted(16768, "ssl initialization problem");
902     }
903 
904     // pick the certificate for use in outgoing connections,
905     std::string clientPEM, clientPassword;
906     if (!isServer || params.sslClusterFile.empty()) {
907         // We are either a client, or a server without a cluster key,
908         // so use the PEM key file, if specified
909         clientPEM = params.sslPEMKeyFile;
910         clientPassword = params.sslPEMKeyPassword;
911     } else {
912         // We are a server with a cluster key, so use the cluster key file
913         clientPEM = params.sslClusterFile;
914         clientPassword = params.sslClusterPassword;
915     }
916 
917     if (!clientPEM.empty()) {
918         if (!_parseAndValidateCertificate(
919                 clientPEM, clientPassword, &_sslConfiguration.clientSubjectName, NULL)) {
920             uasserted(16941, "ssl initialization problem");
921         }
922     }
923     // SSL server specific initialization
924     if (isServer) {
925         if (!_initSynchronousSSLContext(&_serverContext, params, ConnectionDirection::kIncoming)) {
926             uasserted(16562, "ssl initialization problem");
927         }
928 
929         if (!_parseAndValidateCertificate(params.sslPEMKeyFile,
930                                           params.sslPEMKeyPassword,
931                                           &_sslConfiguration.serverSubjectName,
932                                           &_sslConfiguration.serverCertificateExpirationDate)) {
933             uasserted(16942, "ssl initialization problem");
934         }
935 
936         static CertificateExpirationMonitor task =
937             CertificateExpirationMonitor(_sslConfiguration.serverCertificateExpirationDate);
938     }
939 }
940 
password_cb(char * buf,int num,int rwflag,void * userdata)941 int SSLManager::password_cb(char* buf, int num, int rwflag, void* userdata) {
942     // Unless OpenSSL misbehaves, num should always be positive
943     fassert(17314, num > 0);
944     invariant(userdata);
945     auto pw = static_cast<const std::string*>(userdata);
946 
947     const size_t copied = pw->copy(buf, num - 1);
948     buf[copied] = '\0';
949     return copied;
950 }
951 
servername_cb(SSL * s,int * al,void * arg)952 int SSLManager::servername_cb(SSL* s, int* al, void* arg) {
953     // Unconditionally accept the SNI presented by the client. This will ensure that if the client
954     // later performs session resumption, subsequent connections will still have access to the SNI.
955     return SSL_TLSEXT_ERR_OK;
956 }
957 
verify_cb(int ok,X509_STORE_CTX * ctx)958 int SSLManager::verify_cb(int ok, X509_STORE_CTX* ctx) {
959     return 1;  // always succeed; we will catch the error in our get_verify_result() call
960 }
961 
SSL_read(SSLConnection * conn,void * buf,int num)962 int SSLManager::SSL_read(SSLConnection* conn, void* buf, int num) {
963     int status;
964     do {
965         status = ::SSL_read(conn->ssl, buf, num);
966     } while (!_doneWithSSLOp(conn, status));
967 
968     if (status <= 0)
969         _handleSSLError(conn, status);
970     return status;
971 }
972 
SSL_write(SSLConnection * conn,const void * buf,int num)973 int SSLManager::SSL_write(SSLConnection* conn, const void* buf, int num) {
974     int status;
975     do {
976         status = ::SSL_write(conn->ssl, buf, num);
977     } while (!_doneWithSSLOp(conn, status));
978 
979     if (status <= 0)
980         _handleSSLError(conn, status);
981     return status;
982 }
983 
ERR_get_error()984 unsigned long SSLManager::ERR_get_error() {
985     return ::ERR_get_error();
986 }
987 
ERR_error_string(unsigned long e,char * buf)988 char* SSLManager::ERR_error_string(unsigned long e, char* buf) {
989     return ::ERR_error_string(e, buf);
990 }
991 
SSL_get_error(const SSLConnection * conn,int ret)992 int SSLManager::SSL_get_error(const SSLConnection* conn, int ret) {
993     return ::SSL_get_error(conn->ssl, ret);
994 }
995 
SSL_shutdown(SSLConnection * conn)996 int SSLManager::SSL_shutdown(SSLConnection* conn) {
997     int status;
998     do {
999         status = ::SSL_shutdown(conn->ssl);
1000     } while (!_doneWithSSLOp(conn, status));
1001 
1002     if (status < 0)
1003         _handleSSLError(conn, status);
1004     return status;
1005 }
1006 
SSL_free(SSLConnection * conn)1007 void SSLManager::SSL_free(SSLConnection* conn) {
1008     return ::SSL_free(conn->ssl);
1009 }
1010 
initSSLContext(SSL_CTX * context,const SSLParams & params,ConnectionDirection direction)1011 Status SSLManager::initSSLContext(SSL_CTX* context,
1012                                   const SSLParams& params,
1013                                   ConnectionDirection direction) {
1014     // SSL_OP_ALL - Activate all bug workaround options, to support buggy client SSL's.
1015     // SSL_OP_NO_SSLv2 - Disable SSL v2 support
1016     // SSL_OP_NO_SSLv3 - Disable SSL v3 support
1017     long supportedProtocols = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
1018 
1019     // Set the supported TLS protocols. Allow --sslDisabledProtocols to disable selected
1020     // ciphers.
1021     for (const SSLParams::Protocols& protocol : params.sslDisabledProtocols) {
1022         if (protocol == SSLParams::Protocols::TLS1_0) {
1023             supportedProtocols |= SSL_OP_NO_TLSv1;
1024         } else if (protocol == SSLParams::Protocols::TLS1_1) {
1025             supportedProtocols |= SSL_OP_NO_TLSv1_1;
1026         } else if (protocol == SSLParams::Protocols::TLS1_2) {
1027             supportedProtocols |= SSL_OP_NO_TLSv1_2;
1028         } else if (protocol == SSLParams::Protocols::TLS1_3) {
1029             supportedProtocols |= SSL_OP_NO_TLSv1_3;
1030         }
1031     }
1032     ::SSL_CTX_set_options(context, supportedProtocols);
1033 
1034     // HIGH - Enable strong ciphers
1035     // !EXPORT - Disable export ciphers (40/56 bit)
1036     // !aNULL - Disable anonymous auth ciphers
1037     // @STRENGTH - Sort ciphers based on strength
1038     std::string cipherConfig = "HIGH:!EXPORT:!aNULL@STRENGTH";
1039 
1040     // Allow the cipher configuration string to be overriden by --sslCipherConfig
1041     if (!params.sslCipherConfig.empty()) {
1042         cipherConfig = params.sslCipherConfig;
1043     }
1044 
1045     if (0 == ::SSL_CTX_set_cipher_list(context, cipherConfig.c_str())) {
1046         return Status(ErrorCodes::InvalidSSLConfiguration,
1047                       str::stream() << "Can not set supported cipher suites: "
1048                                     << getSSLErrorMessage(ERR_get_error()));
1049     }
1050 
1051     // We use the address of the context as the session id context.
1052     if (0 == ::SSL_CTX_set_session_id_context(
1053                  context, reinterpret_cast<unsigned char*>(&context), sizeof(context))) {
1054         return Status(ErrorCodes::InvalidSSLConfiguration,
1055                       str::stream() << "Can not store ssl session id context: "
1056                                     << getSSLErrorMessage(ERR_get_error()));
1057     }
1058 
1059     // We should accept all SNI extensions advertised by clients
1060     if (1 != SSL_CTX_set_tlsext_servername_callback(context, &SSLManager::servername_cb)) {
1061         return Status(ErrorCodes::InvalidSSLConfiguration,
1062                       str::stream() << "Can not set servername callback: "
1063                                     << getSSLErrorMessage(ERR_get_error()));
1064     }
1065 
1066     if (direction == ConnectionDirection::kOutgoing && params.tlsWithholdClientCertificate) {
1067         // Do not send a client certificate if they have been suppressed.
1068 
1069     } else if (direction == ConnectionDirection::kOutgoing && !params.sslClusterFile.empty()) {
1070         // Use the configured clusterFile as our client certificate.
1071         ::EVP_set_pw_prompt("Enter cluster certificate passphrase");
1072         if (!_setupPEM(context, params.sslClusterFile, params.sslClusterPassword)) {
1073             return Status(ErrorCodes::InvalidSSLConfiguration, "Can not set up ssl clusterFile.");
1074         }
1075 
1076     } else if (!params.sslPEMKeyFile.empty()) {
1077         // Use the base pemKeyFile for any other outgoing connections,
1078         // as well as all incoming connections.
1079         ::EVP_set_pw_prompt("Enter PEM passphrase");
1080         if (!_setupPEM(context, params.sslPEMKeyFile, params.sslPEMKeyPassword)) {
1081             return Status(ErrorCodes::InvalidSSLConfiguration, "Can not set up PEM key file.");
1082         }
1083     }
1084 
1085     std::string cafile = params.sslCAFile;
1086     if (direction == ConnectionDirection::kIncoming && !params.sslClusterCAFile.empty()) {
1087         cafile = params.sslClusterCAFile;
1088     }
1089     const auto status = cafile.empty() ? _setupSystemCA(context) : _setupCA(context, cafile);
1090     if (!status.isOK()) {
1091         return status;
1092     }
1093 
1094     if (!params.sslCRLFile.empty()) {
1095         if (!_setupCRL(context, params.sslCRLFile)) {
1096             return Status(ErrorCodes::InvalidSSLConfiguration, "Can not set up CRL file.");
1097         }
1098     }
1099 
1100     if (!params.sslPEMTempDHParam.empty()) {
1101         try {
1102             std::ifstream dhparamPemFile(params.sslPEMTempDHParam, std::ios_base::binary);
1103             if (dhparamPemFile.fail() || dhparamPemFile.bad()) {
1104                 return Status(ErrorCodes::InvalidSSLConfiguration,
1105                               str::stream() << "Cannot open PEM DHParams file.");
1106             }
1107 
1108             std::vector<std::uint8_t> paramData{std::istreambuf_iterator<char>(dhparamPemFile),
1109                                                 std::istreambuf_iterator<char>()};
1110             auto bio = makeUniqueMemBio(paramData);
1111 
1112             UniqueDHParams dhparams(::PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr));
1113             if (!dhparams) {
1114                 return Status(ErrorCodes::InvalidSSLConfiguration,
1115                               str::stream() << "Error reading DHParams file."
1116                                             << getSSLErrorMessage(ERR_get_error()));
1117             }
1118 
1119             if (::SSL_CTX_set_tmp_dh(context, dhparams.get()) != 1) {
1120                 return Status(ErrorCodes::InvalidSSLConfiguration,
1121                               str::stream() << "Failure to set PFS DH parameters: "
1122                                             << getSSLErrorMessage(ERR_get_error()));
1123             }
1124         } catch (const std::exception& ex) {
1125             return Status(ErrorCodes::InvalidSSLConfiguration, ex.what());
1126         }
1127     }
1128 
1129     // We always set ECDH mode anyhow, if available.
1130     setECDHModeAuto(context);
1131 
1132     return Status::OK();
1133 }
1134 
_initSynchronousSSLContext(UniqueSSLContext * contextPtr,const SSLParams & params,ConnectionDirection direction)1135 bool SSLManager::_initSynchronousSSLContext(UniqueSSLContext* contextPtr,
1136                                             const SSLParams& params,
1137                                             ConnectionDirection direction) {
1138     *contextPtr = UniqueSSLContext(SSL_CTX_new(SSLv23_method()), free_ssl_context);
1139 
1140     uassertStatusOK(initSSLContext(contextPtr->get(), params, direction));
1141 
1142     // If renegotiation is needed, don't return from recv() or send() until it's successful.
1143     // Note: this is for blocking sockets only.
1144     SSL_CTX_set_mode(contextPtr->get(), SSL_MODE_AUTO_RETRY);
1145 
1146     return true;
1147 }
1148 
_convertASN1ToMillis(ASN1_TIME * asn1time)1149 unsigned long long SSLManager::_convertASN1ToMillis(ASN1_TIME* asn1time) {
1150     BIO* outBIO = BIO_new(BIO_s_mem());
1151     int timeError = ASN1_TIME_print(outBIO, asn1time);
1152     ON_BLOCK_EXIT(BIO_free, outBIO);
1153 
1154     if (timeError <= 0) {
1155         error() << "ASN1_TIME_print failed or wrote no data.";
1156         return 0;
1157     }
1158 
1159     char dateChar[DATE_LEN];
1160     timeError = BIO_gets(outBIO, dateChar, DATE_LEN);
1161     if (timeError <= 0) {
1162         error() << "BIO_gets call failed to transfer contents to buf";
1163         return 0;
1164     }
1165 
1166     // Ensure that day format is two digits for parsing.
1167     // Jun  8 17:00:03 2014 becomes Jun 08 17:00:03 2014.
1168     if (dateChar[4] == ' ') {
1169         dateChar[4] = '0';
1170     }
1171 
1172     std::istringstream inStringStream((std::string(dateChar, 20)));
1173     boost::posix_time::time_input_facet* inputFacet =
1174         new boost::posix_time::time_input_facet("%b %d %H:%M:%S %Y");
1175 
1176     inStringStream.imbue(std::locale(std::cout.getloc(), inputFacet));
1177     boost::posix_time::ptime posixTime;
1178     inStringStream >> posixTime;
1179 
1180     const boost::gregorian::date epoch = boost::gregorian::date(1970, boost::gregorian::Jan, 1);
1181 
1182     return (posixTime - boost::posix_time::ptime(epoch)).total_milliseconds();
1183 }
1184 
_parseAndValidateCertificate(const std::string & keyFile,const std::string & keyPassword,SSLX509Name * subjectName,Date_t * serverCertificateExpirationDate)1185 bool SSLManager::_parseAndValidateCertificate(const std::string& keyFile,
1186                                               const std::string& keyPassword,
1187                                               SSLX509Name* subjectName,
1188                                               Date_t* serverCertificateExpirationDate) {
1189     BIO* inBIO = BIO_new(BIO_s_file());
1190     if (inBIO == NULL) {
1191         error() << "failed to allocate BIO object: " << getSSLErrorMessage(ERR_get_error());
1192         return false;
1193     }
1194 
1195     ON_BLOCK_EXIT(BIO_free, inBIO);
1196     if (BIO_read_filename(inBIO, keyFile.c_str()) <= 0) {
1197         error() << "cannot read key file when setting subject name: " << keyFile << ' '
1198                 << getSSLErrorMessage(ERR_get_error());
1199         return false;
1200     }
1201 
1202     // Callback will not manipulate the password, so const_cast is safe.
1203     X509* x509 = PEM_read_bio_X509(inBIO,
1204                                    NULL,
1205                                    &SSLManager::password_cb,
1206                                    const_cast<void*>(static_cast<const void*>(&keyPassword)));
1207     if (x509 == NULL) {
1208         error() << "cannot retrieve certificate from keyfile: " << keyFile << ' '
1209                 << getSSLErrorMessage(ERR_get_error());
1210         return false;
1211     }
1212     ON_BLOCK_EXIT(X509_free, x509);
1213 
1214     *subjectName = getCertificateSubjectX509Name(x509);
1215     if (serverCertificateExpirationDate != NULL) {
1216         unsigned long long notBeforeMillis = _convertASN1ToMillis(X509_get_notBefore(x509));
1217         if (notBeforeMillis == 0) {
1218             error() << "date conversion failed";
1219             return false;
1220         }
1221 
1222         unsigned long long notAfterMillis = _convertASN1ToMillis(X509_get_notAfter(x509));
1223         if (notAfterMillis == 0) {
1224             error() << "date conversion failed";
1225             return false;
1226         }
1227 
1228         if ((notBeforeMillis > curTimeMillis64()) || (curTimeMillis64() > notAfterMillis)) {
1229             severe() << "The provided SSL certificate is expired or not yet valid.";
1230             fassertFailedNoTrace(28652);
1231         }
1232 
1233         *serverCertificateExpirationDate = Date_t::fromMillisSinceEpoch(notAfterMillis);
1234     }
1235 
1236     return true;
1237 }
1238 
_setupPEM(SSL_CTX * context,const std::string & keyFile,const std::string & password)1239 bool SSLManager::_setupPEM(SSL_CTX* context,
1240                            const std::string& keyFile,
1241                            const std::string& password) {
1242     if (SSL_CTX_use_certificate_chain_file(context, keyFile.c_str()) != 1) {
1243         error() << "cannot read certificate file: " << keyFile << ' '
1244                 << getSSLErrorMessage(ERR_get_error());
1245         return false;
1246     }
1247 
1248     BIO* inBio = BIO_new(BIO_s_file());
1249     if (!inBio) {
1250         error() << "failed to allocate BIO object: " << getSSLErrorMessage(ERR_get_error());
1251         return false;
1252     }
1253     const auto bioGuard = MakeGuard([&inBio]() { BIO_free(inBio); });
1254 
1255     if (BIO_read_filename(inBio, keyFile.c_str()) <= 0) {
1256         error() << "cannot read PEM key file: " << keyFile << ' '
1257                 << getSSLErrorMessage(ERR_get_error());
1258         return false;
1259     }
1260 
1261     // If password is empty, use default OpenSSL callback, which uses the terminal
1262     // to securely request the password interactively from the user.
1263     decltype(&SSLManager::password_cb) password_cb = nullptr;
1264     void* userdata = nullptr;
1265     if (!password.empty()) {
1266         password_cb = &SSLManager::password_cb;
1267         // SSLManager::password_cb will not manipulate the password, so const_cast is safe.
1268         userdata = const_cast<void*>(static_cast<const void*>(&password));
1269     }
1270     EVP_PKEY* privateKey = PEM_read_bio_PrivateKey(inBio, nullptr, password_cb, userdata);
1271     if (!privateKey) {
1272         error() << "cannot read PEM key file: " << keyFile << ' '
1273                 << getSSLErrorMessage(ERR_get_error());
1274         return false;
1275     }
1276     const auto privateKeyGuard = MakeGuard([&privateKey]() { EVP_PKEY_free(privateKey); });
1277 
1278     if (SSL_CTX_use_PrivateKey(context, privateKey) != 1) {
1279         error() << "cannot use PEM key file: " << keyFile << ' '
1280                 << getSSLErrorMessage(ERR_get_error());
1281         return false;
1282     }
1283 
1284     // Verify that the certificate and the key go together.
1285     if (SSL_CTX_check_private_key(context) != 1) {
1286         error() << "SSL certificate validation: " << getSSLErrorMessage(ERR_get_error());
1287         return false;
1288     }
1289 
1290     return true;
1291 }
1292 
_setupCA(SSL_CTX * context,const std::string & caFile)1293 Status SSLManager::_setupCA(SSL_CTX* context, const std::string& caFile) {
1294     // Set the list of CAs sent to clients
1295     STACK_OF(X509_NAME)* certNames = SSL_load_client_CA_file(caFile.c_str());
1296     if (certNames == NULL) {
1297         return Status(ErrorCodes::InvalidSSLConfiguration,
1298                       str::stream() << "cannot read certificate authority file: " << caFile << " "
1299                                     << getSSLErrorMessage(ERR_get_error()));
1300     }
1301     SSL_CTX_set_client_CA_list(context, certNames);
1302 
1303     // Load trusted CA
1304     if (SSL_CTX_load_verify_locations(context, caFile.c_str(), NULL) != 1) {
1305         return Status(ErrorCodes::InvalidSSLConfiguration,
1306                       str::stream() << "cannot read certificate authority file: " << caFile << " "
1307                                     << getSSLErrorMessage(ERR_get_error()));
1308     }
1309 
1310     // Set SSL to require peer (client) certificate verification
1311     // if a certificate is presented
1312     SSL_CTX_set_verify(context, SSL_VERIFY_PEER, &SSLManager::verify_cb);
1313     _sslConfiguration.hasCA = true;
1314     return Status::OK();
1315 }
1316 
checkX509_STORE_error()1317 inline Status checkX509_STORE_error() {
1318     const auto errCode = ERR_peek_last_error();
1319     if (ERR_GET_LIB(errCode) != ERR_LIB_X509 ||
1320         ERR_GET_REASON(errCode) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1321         return {ErrorCodes::InvalidSSLConfiguration,
1322                 str::stream() << "Error adding certificate to X509 store: "
1323                               << ERR_reason_error_string(errCode)};
1324     }
1325     return Status::OK();
1326 }
1327 
1328 #if defined(_WIN32)
1329 // This imports the certificates in a given Windows certificate store into an X509_STORE for
1330 // openssl to use during certificate validation.
importCertStoreToX509_STORE(const wchar_t * storeName,DWORD storeLocation,X509_STORE * verifyStore)1331 Status importCertStoreToX509_STORE(const wchar_t* storeName,
1332                                    DWORD storeLocation,
1333                                    X509_STORE* verifyStore) {
1334     HCERTSTORE systemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
1335                                            0,
1336                                            NULL,
1337                                            storeLocation | CERT_STORE_READONLY_FLAG,
1338                                            const_cast<LPWSTR>(storeName));
1339     if (systemStore == NULL) {
1340         return {ErrorCodes::InvalidSSLConfiguration,
1341                 str::stream() << "error opening system CA store: " << errnoWithDescription()};
1342     }
1343     auto systemStoreGuard = MakeGuard([systemStore]() { CertCloseStore(systemStore, 0); });
1344 
1345     PCCERT_CONTEXT certCtx = NULL;
1346     while ((certCtx = CertEnumCertificatesInStore(systemStore, certCtx)) != NULL) {
1347         auto certBytes = static_cast<const unsigned char*>(certCtx->pbCertEncoded);
1348         X509* x509Obj = d2i_X509(NULL, &certBytes, certCtx->cbCertEncoded);
1349         if (x509Obj == NULL) {
1350             return {ErrorCodes::InvalidSSLConfiguration,
1351                     str::stream() << "Error parsing X509 object from Windows certificate store"
1352                                   << SSLManagerInterface::getSSLErrorMessage(ERR_get_error())};
1353         }
1354         const auto x509ObjGuard = MakeGuard([&x509Obj]() { X509_free(x509Obj); });
1355 
1356         if (X509_STORE_add_cert(verifyStore, x509Obj) != 1) {
1357             auto status = checkX509_STORE_error();
1358             if (!status.isOK())
1359                 return status;
1360         }
1361     }
1362     int lastError = GetLastError();
1363     if (lastError != CRYPT_E_NOT_FOUND) {
1364         return {ErrorCodes::InvalidSSLConfiguration,
1365                 str::stream() << "Error enumerating certificates: "
1366                               << errnoWithDescription(lastError)};
1367     }
1368 
1369     return Status::OK();
1370 }
1371 #elif defined(__APPLE__)
1372 
1373 template <typename T>
1374 class CFTypeRefHolder {
1375 public:
CFTypeRefHolder(T ptr)1376     explicit CFTypeRefHolder(T ptr) : ref(static_cast<CFTypeRef>(ptr)) {}
~CFTypeRefHolder()1377     ~CFTypeRefHolder() {
1378         CFRelease(ref);
1379     }
operator T()1380     operator T() {
1381         return static_cast<T>(ref);
1382     }
1383 
1384 private:
1385     CFTypeRef ref = nullptr;
1386 };
1387 template <typename T>
makeCFTypeRefHolder(T ptr)1388 CFTypeRefHolder<T> makeCFTypeRefHolder(T ptr) {
1389     return CFTypeRefHolder<T>(ptr);
1390 }
1391 
OSStatusToString(OSStatus status)1392 std::string OSStatusToString(OSStatus status) {
1393     auto errMsg = makeCFTypeRefHolder(SecCopyErrorMessageString(status, NULL));
1394     return std::string{CFStringGetCStringPtr(errMsg, kCFStringEncodingUTF8)};
1395 }
1396 
importKeychainToX509_STORE(X509_STORE * verifyStore)1397 Status importKeychainToX509_STORE(X509_STORE* verifyStore) {
1398     CFArrayRef result;
1399     OSStatus status;
1400 
1401     // This copies all the certificates trusted by the system (regardless of what keychain they're
1402     // attached to) into a CFArray.
1403     if ((status = SecTrustCopyAnchorCertificates(&result)) != 0) {
1404         return {ErrorCodes::InvalidSSLConfiguration,
1405                 str::stream() << "Error enumerating certificates: " << OSStatusToString(status)};
1406     }
1407     const auto resultGuard = makeCFTypeRefHolder(result);
1408 
1409     for (CFIndex i = 0; i < CFArrayGetCount(result); i++) {
1410         SecCertificateRef cert =
1411             static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(result, i)));
1412 
1413         auto rawData = makeCFTypeRefHolder(SecCertificateCopyData(cert));
1414         if (!rawData) {
1415             return {ErrorCodes::InvalidSSLConfiguration,
1416                     str::stream() << "Error enumerating certificates: "
1417                                   << OSStatusToString(status)};
1418         }
1419         const uint8_t* rawDataPtr = CFDataGetBytePtr(rawData);
1420 
1421         // Parse an openssl X509 object from each returned certificate
1422         X509* x509Cert = d2i_X509(nullptr, &rawDataPtr, CFDataGetLength(rawData));
1423         if (!x509Cert) {
1424             return {ErrorCodes::InvalidSSLConfiguration,
1425                     str::stream() << "Error parsing X509 certificate from system keychain: "
1426                                   << ERR_reason_error_string(ERR_peek_last_error())};
1427         }
1428         const auto x509CertGuard = MakeGuard([&x509Cert]() { X509_free(x509Cert); });
1429 
1430         // Add the parsed X509 object to the X509_STORE verification store
1431         if (X509_STORE_add_cert(verifyStore, x509Cert) != 1) {
1432             auto status = checkX509_STORE_error();
1433             if (!status.isOK())
1434                 return status;
1435         }
1436     }
1437 
1438     return Status::OK();
1439 }
1440 #endif
1441 
_setupSystemCA(SSL_CTX * context)1442 Status SSLManager::_setupSystemCA(SSL_CTX* context) {
1443 #if !defined(_WIN32) && !defined(__APPLE__)
1444     // On non-Windows/non-Apple platforms, the OpenSSL libraries should have been configured
1445     // with default locations for CA certificates.
1446     if (SSL_CTX_set_default_verify_paths(context) != 1) {
1447         return {ErrorCodes::InvalidSSLConfiguration,
1448                 str::stream() << "error loading system CA certificates "
1449                               << "(default certificate file: "
1450                               << X509_get_default_cert_file()
1451                               << ", "
1452                               << "default certificate path: "
1453                               << X509_get_default_cert_dir()
1454                               << ")"};
1455     }
1456     return Status::OK();
1457 #else
1458 
1459     X509_STORE* verifyStore = SSL_CTX_get_cert_store(context);
1460     if (!verifyStore) {
1461         return {ErrorCodes::InvalidSSLConfiguration,
1462                 "no X509 store found for SSL context while loading system certificates"};
1463     }
1464 #if defined(_WIN32)
1465     auto status = importCertStoreToX509_STORE(L"root", CERT_SYSTEM_STORE_CURRENT_USER, verifyStore);
1466     if (!status.isOK())
1467         return status;
1468     return importCertStoreToX509_STORE(L"CA", CERT_SYSTEM_STORE_CURRENT_USER, verifyStore);
1469 #elif defined(__APPLE__)
1470     return importKeychainToX509_STORE(verifyStore);
1471 #endif
1472 #endif
1473 }
1474 
_setupCRL(SSL_CTX * context,const std::string & crlFile)1475 bool SSLManager::_setupCRL(SSL_CTX* context, const std::string& crlFile) {
1476     X509_STORE* store = SSL_CTX_get_cert_store(context);
1477     fassert(16583, store);
1478 
1479     X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
1480     X509_LOOKUP* lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
1481     fassert(16584, lookup);
1482 
1483     int status = X509_load_crl_file(lookup, crlFile.c_str(), X509_FILETYPE_PEM);
1484     if (status == 0) {
1485         error() << "cannot read CRL file: " << crlFile << ' '
1486                 << getSSLErrorMessage(ERR_get_error());
1487         return false;
1488     }
1489     log() << "ssl imported " << status << " revoked certificate" << ((status == 1) ? "" : "s")
1490           << " from the revocation list.";
1491     return true;
1492 }
1493 
1494 /*
1495 * The interface layer between network and BIO-pair. The BIO-pair buffers
1496 * the data to/from the TLS layer.
1497 */
_flushNetworkBIO(SSLConnection * conn)1498 void SSLManager::_flushNetworkBIO(SSLConnection* conn) {
1499     char buffer[BUFFER_SIZE];
1500     int wantWrite;
1501 
1502     /*
1503     * Write the complete contents of the buffer. Leaving the buffer
1504     * unflushed could cause a deadlock.
1505     */
1506     while ((wantWrite = BIO_ctrl_pending(conn->networkBIO)) > 0) {
1507         if (wantWrite > BUFFER_SIZE) {
1508             wantWrite = BUFFER_SIZE;
1509         }
1510         int fromBIO = BIO_read(conn->networkBIO, buffer, wantWrite);
1511 
1512         int writePos = 0;
1513         do {
1514             int numWrite = fromBIO - writePos;
1515             numWrite = send(conn->socket->rawFD(), buffer + writePos, numWrite, portSendFlags);
1516             if (numWrite < 0) {
1517                 conn->socket->handleSendError(numWrite, "");
1518             }
1519             writePos += numWrite;
1520         } while (writePos < fromBIO);
1521     }
1522 
1523     int wantRead;
1524     while ((wantRead = BIO_ctrl_get_read_request(conn->networkBIO)) > 0) {
1525         if (wantRead > BUFFER_SIZE) {
1526             wantRead = BUFFER_SIZE;
1527         }
1528 
1529         int numRead = recv(conn->socket->rawFD(), buffer, wantRead, portRecvFlags);
1530         if (numRead <= 0) {
1531             conn->socket->handleRecvError(numRead, wantRead);
1532             continue;
1533         }
1534 
1535         int toBIO = BIO_write(conn->networkBIO, buffer, numRead);
1536         if (toBIO != numRead) {
1537             LOG(3) << "Failed to write network data to the SSL BIO layer";
1538             throw SocketException(SocketException::RECV_ERROR, conn->socket->remoteString());
1539         }
1540     }
1541 }
1542 
_doneWithSSLOp(SSLConnection * conn,int status)1543 bool SSLManager::_doneWithSSLOp(SSLConnection* conn, int status) {
1544     int sslErr = SSL_get_error(conn, status);
1545     switch (sslErr) {
1546         case SSL_ERROR_NONE:
1547             _flushNetworkBIO(conn);  // success, flush network BIO before leaving
1548             return true;
1549         case SSL_ERROR_WANT_WRITE:
1550         case SSL_ERROR_WANT_READ:
1551             _flushNetworkBIO(conn);  // not ready, flush network BIO and try again
1552             return false;
1553         default:
1554             return true;
1555     }
1556 }
1557 
connect(Socket * socket)1558 SSLConnection* SSLManager::connect(Socket* socket) {
1559     std::unique_ptr<SSLConnection> sslConn =
1560         stdx::make_unique<SSLConnection>(_clientContext.get(), socket, (const char*)NULL, 0);
1561 
1562     const auto undotted = removeFQDNRoot(socket->remoteAddr().hostOrIp());
1563     int ret = ::SSL_set_tlsext_host_name(sslConn->ssl, undotted.c_str());
1564     if (ret != 1)
1565         _handleSSLError(sslConn.get(), ret);
1566 
1567     do {
1568         ret = ::SSL_connect(sslConn->ssl);
1569     } while (!_doneWithSSLOp(sslConn.get(), ret));
1570 
1571     if (ret != 1)
1572         _handleSSLError(sslConn.get(), ret);
1573 
1574     return sslConn.release();
1575 }
1576 
accept(Socket * socket,const char * initialBytes,int len)1577 SSLConnection* SSLManager::accept(Socket* socket, const char* initialBytes, int len) {
1578     std::unique_ptr<SSLConnection> sslConn =
1579         stdx::make_unique<SSLConnection>(_serverContext.get(), socket, initialBytes, len);
1580 
1581     int ret;
1582     do {
1583         ret = ::SSL_accept(sslConn->ssl);
1584     } while (!_doneWithSSLOp(sslConn.get(), ret));
1585 
1586     if (ret != 1)
1587         _handleSSLError(sslConn.get(), ret);
1588 
1589     return sslConn.release();
1590 }
1591 
1592 
mapTLSVersion(const SSL * conn)1593 StatusWith<TLSVersion> mapTLSVersion(const SSL* conn) {
1594     int protocol = SSL_version(conn);
1595 
1596     switch (protocol) {
1597         case TLS1_VERSION:
1598             return TLSVersion::kTLS10;
1599         case TLS1_1_VERSION:
1600             return TLSVersion::kTLS11;
1601         case TLS1_2_VERSION:
1602             return TLSVersion::kTLS12;
1603 #ifdef TLS1_3_VERSION
1604         case TLS1_3_VERSION:
1605             return TLSVersion::kTLS13;
1606 #endif
1607         default:
1608             return TLSVersion::kUnknown;
1609     }
1610 }
1611 
1612 namespace {
_validatePeerRoles(const stdx::unordered_set<RoleName> & embeddedRoles,SSL * conn)1613 Status _validatePeerRoles(const stdx::unordered_set<RoleName>& embeddedRoles, SSL* conn) {
1614     if (embeddedRoles.empty()) {
1615         // Nothing offered, nothing to restrict.
1616         return Status::OK();
1617     }
1618 
1619     if (!sslGlobalParams.tlsCATrusts) {
1620         // Nothing restricted.
1621         return Status::OK();
1622     }
1623 
1624     const auto& tlsCATrusts = sslGlobalParams.tlsCATrusts.get();
1625     if (tlsCATrusts.empty()) {
1626         // Nothing permitted.
1627         return {ErrorCodes::BadValue,
1628                 "tlsCATrusts parameter prohibits role based authorization via X509 certificates"};
1629     }
1630 
1631     auto stack = SSLgetVerifiedChain(conn);
1632     if (!stack || !sk_X509_num(stack.get())) {
1633         return {ErrorCodes::BadValue, "Unable to obtain certificate chain"};
1634     }
1635 
1636     auto root = sk_X509_value(stack.get(), sk_X509_num(stack.get()) - 1);
1637     SHA256Block::HashType digest;
1638     if (!X509_digest(root, EVP_sha256(), digest.data(), nullptr)) {
1639         return {ErrorCodes::BadValue, "Unable to digest root certificate"};
1640     }
1641 
1642     SHA256Block sha256(digest);
1643     auto it = tlsCATrusts.find(sha256);
1644     if (it == tlsCATrusts.end()) {
1645         return {
1646             ErrorCodes::BadValue,
1647             str::stream() << "CA: " << sha256.toHexString()
1648                           << " is not authorized to grant any roles due to tlsCATrusts parameter"};
1649     }
1650 
1651     auto allowedRoles = it->second;
1652     // See TLSCATrustsSetParameter::set() for a description of tlsCATrusts format.
1653     if (allowedRoles.count(RoleName("", ""))) {
1654         // CA is authorized for all role assignments.
1655         return Status::OK();
1656     }
1657 
1658     for (const auto& role : embeddedRoles) {
1659         // Check for exact match or wildcard matches.
1660         if (!allowedRoles.count(role) && !allowedRoles.count(RoleName(role.getRole(), "")) &&
1661             !allowedRoles.count(RoleName("", role.getDB()))) {
1662             return {ErrorCodes::BadValue,
1663                     str::stream() << "CA: " << sha256.toHexString()
1664                                   << " is not authorized to grant role "
1665                                   << role.toString()
1666                                   << " due to tlsCATrusts parameter"};
1667         }
1668     }
1669 
1670     return Status::OK();
1671 }
1672 }  // namespace
1673 
parseAndValidatePeerCertificate(SSL * conn,const std::string & remoteHost,const HostAndPort & hostForLogging)1674 StatusWith<SSLPeerInfo> SSLManager::parseAndValidatePeerCertificate(
1675     SSL* conn, const std::string& remoteHost, const HostAndPort& hostForLogging) {
1676     auto sniName = getRawSNIServerName(conn);
1677 
1678     auto tlsVersionStatus = mapTLSVersion(conn);
1679     if (!tlsVersionStatus.isOK()) {
1680         return tlsVersionStatus.getStatus();
1681     }
1682 
1683     recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging);
1684 
1685     if (!_sslConfiguration.hasCA && isSSLServer)
1686         return SSLPeerInfo(std::move(sniName));
1687 
1688     X509* peerCert = SSL_get_peer_certificate(conn);
1689 
1690     if (NULL == peerCert) {  // no certificate presented by peer
1691         if (_weakValidation) {
1692             // do not give warning if certificate warnings are suppressed
1693             if (!_suppressNoCertificateWarning) {
1694                 warning() << "no SSL certificate provided by peer";
1695             }
1696             return SSLPeerInfo(std::move(sniName));
1697         } else {
1698             auto msg = "no SSL certificate provided by peer; connection rejected";
1699             error() << msg;
1700             return Status(ErrorCodes::SSLHandshakeFailed, msg);
1701         }
1702         return SSLPeerInfo(std::move(sniName));
1703     }
1704     ON_BLOCK_EXIT(X509_free, peerCert);
1705 
1706     long result = SSL_get_verify_result(conn);
1707 
1708     if (result != X509_V_OK) {
1709         if (_allowInvalidCertificates) {
1710             warning() << "SSL peer certificate validation failed: "
1711                       << X509_verify_cert_error_string(result);
1712             return SSLPeerInfo(std::move(sniName));
1713         } else {
1714             str::stream msg;
1715             msg << "SSL peer certificate validation failed: "
1716                 << X509_verify_cert_error_string(result);
1717             error() << msg.ss.str();
1718             return Status(ErrorCodes::SSLHandshakeFailed, msg);
1719         }
1720     }
1721 
1722     // TODO: check optional cipher restriction, using cert.
1723     auto peerSubject = getCertificateSubjectX509Name(peerCert);
1724     LOG(2) << "Accepted TLS connection from peer: " << peerSubject;
1725 
1726     StatusWith<stdx::unordered_set<RoleName>> swPeerCertificateRoles = _parsePeerRoles(peerCert);
1727     if (!swPeerCertificateRoles.isOK()) {
1728         return swPeerCertificateRoles.getStatus();
1729     }
1730 
1731     {
1732         auto status = _validatePeerRoles(swPeerCertificateRoles.getValue(), conn);
1733         if (!status.isOK()) {
1734             return status;
1735         }
1736     }
1737 
1738     // If this is an SSL client context (on a MongoDB server or client)
1739     // perform hostname validation of the remote server
1740     if (remoteHost.empty()) {
1741         return SSLPeerInfo(
1742             peerSubject, std::move(sniName), std::move(swPeerCertificateRoles.getValue()));
1743     }
1744 
1745     // Try to match using the Subject Alternate Name, if it exists.
1746     // RFC-2818 requires the Subject Alternate Name to be used if present.
1747     // Otherwise, the most specific Common Name field in the subject field
1748     // must be used.
1749 
1750     bool sanMatch = false;
1751     bool cnMatch = false;
1752     StringBuilder certificateNames;
1753 
1754     STACK_OF(GENERAL_NAME)* sanNames = static_cast<STACK_OF(GENERAL_NAME)*>(
1755         X509_get_ext_d2i(peerCert, NID_subject_alt_name, NULL, NULL));
1756 
1757     if (sanNames != NULL) {
1758         int sanNamesList = sk_GENERAL_NAME_num(sanNames);
1759         certificateNames << "SAN(s): ";
1760         for (int i = 0; i < sanNamesList; i++) {
1761             const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(sanNames, i);
1762             if (currentName && currentName->type == GEN_DNS) {
1763                 char* dnsName = reinterpret_cast<char*>(ASN1_STRING_data(currentName->d.dNSName));
1764                 if (hostNameMatchForX509Certificates(remoteHost, dnsName)) {
1765                     sanMatch = true;
1766                     break;
1767                 }
1768                 certificateNames << std::string(dnsName) << " ";
1769             }
1770         }
1771         sk_GENERAL_NAME_pop_free(sanNames, GENERAL_NAME_free);
1772     } else {
1773         // If Subject Alternate Name (SAN) doesn't exist and Common Name (CN) does,
1774         // check Common Name.
1775         auto swCN = peerSubject.getOID(kOID_CommonName);
1776         if (swCN.isOK()) {
1777             auto commonName = std::move(swCN.getValue());
1778             if (hostNameMatchForX509Certificates(remoteHost, commonName)) {
1779                 cnMatch = true;
1780             }
1781             certificateNames << "CN: " << commonName;
1782         } else {
1783             certificateNames << "No Common Name (CN) or Subject Alternate Names (SAN) found";
1784         }
1785     }
1786 
1787     if (!sanMatch && !cnMatch) {
1788         StringBuilder msgBuilder;
1789         msgBuilder << "The server certificate does not match the host name. Hostname: "
1790                    << remoteHost << " does not match " << certificateNames.str();
1791         std::string msg = msgBuilder.str();
1792         if (_allowInvalidCertificates || _allowInvalidHostnames || isUnixDomainSocket(remoteHost)) {
1793             warning() << msg;
1794         } else {
1795             error() << msg;
1796             return Status(ErrorCodes::SSLHandshakeFailed, msg);
1797         }
1798     }
1799 
1800     return SSLPeerInfo(peerSubject);
1801 }
1802 
1803 
parseAndValidatePeerCertificateDeprecated(const SSLConnection * conn,const std::string & remoteHost,const HostAndPort & hostForLogging)1804 SSLPeerInfo SSLManager::parseAndValidatePeerCertificateDeprecated(
1805     const SSLConnection* conn, const std::string& remoteHost, const HostAndPort& hostForLogging) {
1806     auto swPeerSubjectName = parseAndValidatePeerCertificate(conn->ssl, remoteHost, hostForLogging);
1807     // We can't use uassertStatusOK here because we need to throw a SocketException.
1808     if (!swPeerSubjectName.isOK()) {
1809         throw SocketException(SocketException::CONNECT_ERROR,
1810                               swPeerSubjectName.getStatus().reason());
1811     }
1812     return swPeerSubjectName.getValue();
1813 }
1814 
recordTLSVersion(TLSVersion version,const HostAndPort & hostForLogging)1815 void recordTLSVersion(TLSVersion version, const HostAndPort& hostForLogging) {
1816     StringData versionString;
1817     auto& counts = mongo::TLSVersionCounts::get();
1818     switch (version) {
1819         case TLSVersion::kTLS10:
1820             counts.tls10.addAndFetch(1);
1821             if (std::find(sslGlobalParams.tlsLogVersions.cbegin(),
1822                           sslGlobalParams.tlsLogVersions.cend(),
1823                           SSLParams::Protocols::TLS1_0) != sslGlobalParams.tlsLogVersions.cend()) {
1824                 versionString = "1.0"_sd;
1825             }
1826             break;
1827         case TLSVersion::kTLS11:
1828             counts.tls11.addAndFetch(1);
1829             if (std::find(sslGlobalParams.tlsLogVersions.cbegin(),
1830                           sslGlobalParams.tlsLogVersions.cend(),
1831                           SSLParams::Protocols::TLS1_1) != sslGlobalParams.tlsLogVersions.cend()) {
1832                 versionString = "1.1"_sd;
1833             }
1834             break;
1835         case TLSVersion::kTLS12:
1836             counts.tls12.addAndFetch(1);
1837             if (std::find(sslGlobalParams.tlsLogVersions.cbegin(),
1838                           sslGlobalParams.tlsLogVersions.cend(),
1839                           SSLParams::Protocols::TLS1_2) != sslGlobalParams.tlsLogVersions.cend()) {
1840                 versionString = "1.2"_sd;
1841             }
1842             break;
1843         case TLSVersion::kTLS13:
1844             counts.tls13.addAndFetch(1);
1845             if (std::find(sslGlobalParams.tlsLogVersions.cbegin(),
1846                           sslGlobalParams.tlsLogVersions.cend(),
1847                           SSLParams::Protocols::TLS1_3) != sslGlobalParams.tlsLogVersions.cend()) {
1848                 versionString = "1.3"_sd;
1849             }
1850             break;
1851         default:
1852             counts.tlsUnknown.addAndFetch(1);
1853             if (!sslGlobalParams.tlsLogVersions.empty()) {
1854                 versionString = "unknown"_sd;
1855             }
1856             break;
1857     }
1858 
1859     if (!versionString.empty()) {
1860         log() << "Accepted connection with TLS Version " << versionString << " from connection "
1861               << hostForLogging;
1862     }
1863 }
1864 
_parsePeerRoles(X509 * peerCert) const1865 StatusWith<stdx::unordered_set<RoleName>> SSLManager::_parsePeerRoles(X509* peerCert) const {
1866     // exts is owned by the peerCert
1867     const STACK_OF(X509_EXTENSION)* exts = X509_get0_extensions(peerCert);
1868 
1869     int extCount = 0;
1870     if (exts) {
1871         extCount = sk_X509_EXTENSION_num(exts);
1872     }
1873 
1874     ASN1_OBJECT* rolesObj = OBJ_nid2obj(_rolesNid);
1875 
1876 
1877     // Search all certificate extensions for our own
1878     stdx::unordered_set<RoleName> roles;
1879     for (int i = 0; i < extCount; i++) {
1880         X509_EXTENSION* ex = sk_X509_EXTENSION_value(exts, i);
1881         ASN1_OBJECT* obj = X509_EXTENSION_get_object(ex);
1882 
1883         if (!OBJ_cmp(obj, rolesObj)) {
1884             // We've found an extension which has our roles OID
1885             ASN1_OCTET_STRING* data = X509_EXTENSION_get_data(ex);
1886 
1887             /*
1888              * MongoDBAuthorizationGrant ::= CHOICE {
1889              *  MongoDBRole,
1890              *  ...!UTF8String:"Unrecognized entity in MongoDBAuthorizationGrant"
1891              * }
1892              * MongoDBAuthorizationGrants ::= SET OF MongoDBAuthorizationGrant
1893              */
1894             // Extract the set of roles from our extension, and load them into an OpenSSL stack.
1895             STACK_OF(ASN1_TYPE)* mongoDBAuthorizationGrants = nullptr;
1896 
1897             // OpenSSL's parsing function will try and manipulate the pointer it's passed. If we
1898             // passed it 'data->data' directly, it would modify structures owned by peerCert.
1899             const unsigned char* dataBytes = data->data;
1900             mongoDBAuthorizationGrants =
1901                 d2i_ASN1_SET_ANY(&mongoDBAuthorizationGrants, &dataBytes, data->length);
1902             if (!mongoDBAuthorizationGrants) {
1903                 return Status(ErrorCodes::FailedToParse,
1904                               "Failed to parse x509 authorization grants");
1905             }
1906             const auto grantGuard = MakeGuard([&mongoDBAuthorizationGrants]() {
1907                 sk_ASN1_TYPE_pop_free(mongoDBAuthorizationGrants, ASN1_TYPE_free);
1908             });
1909 
1910             /*
1911              * MongoDBRole ::= SEQUENCE {
1912              *  role     UTF8String,
1913              *  database UTF8String
1914              * }
1915              */
1916             // Loop through every role in the stack.
1917             ASN1_TYPE* MongoDBRoleWrapped = nullptr;
1918             while ((MongoDBRoleWrapped = sk_ASN1_TYPE_pop(mongoDBAuthorizationGrants))) {
1919                 const auto roleWrappedGuard =
1920                     MakeGuard([MongoDBRoleWrapped]() { ASN1_TYPE_free(MongoDBRoleWrapped); });
1921 
1922                 if (MongoDBRoleWrapped->type == V_ASN1_SEQUENCE) {
1923                     // Unwrap the ASN1Type into a STACK_OF(ASN1_TYPE)
1924                     unsigned char* roleBytes = ASN1_STRING_data(MongoDBRoleWrapped->value.sequence);
1925                     int roleBytesLength = ASN1_STRING_length(MongoDBRoleWrapped->value.sequence);
1926                     ASN1_SEQUENCE_ANY* MongoDBRole = nullptr;
1927                     MongoDBRole = d2i_ASN1_SEQUENCE_ANY(
1928                         &MongoDBRole, (const unsigned char**)&roleBytes, roleBytesLength);
1929                     if (!MongoDBRole) {
1930                         return Status(ErrorCodes::FailedToParse,
1931                                       "Failed to parse role in x509 authorization grant");
1932                     }
1933                     const auto roleGuard = MakeGuard(
1934                         [&MongoDBRole]() { sk_ASN1_TYPE_pop_free(MongoDBRole, ASN1_TYPE_free); });
1935 
1936                     if (sk_ASN1_TYPE_num(MongoDBRole) != 2) {
1937                         return Status(ErrorCodes::FailedToParse,
1938                                       "Role entity in MongoDBAuthorizationGrant must have exactly "
1939                                       "2 sequence elements");
1940                     }
1941                     // Extract the subcomponents of the sequence, which are popped off the stack in
1942                     // reverse order. Here, parse the role's database.
1943                     ASN1_TYPE* roleComponent = sk_ASN1_TYPE_pop(MongoDBRole);
1944                     const auto roleDBGuard =
1945                         MakeGuard([roleComponent]() { ASN1_TYPE_free(roleComponent); });
1946                     if (roleComponent->type != V_ASN1_UTF8STRING) {
1947                         return Status(ErrorCodes::FailedToParse,
1948                                       "database in MongoDBRole must be a UTF8 string");
1949                     }
1950                     std::string roleDB(
1951                         reinterpret_cast<char*>(ASN1_STRING_data(roleComponent->value.utf8string)));
1952 
1953                     // Parse the role's name.
1954                     roleComponent = sk_ASN1_TYPE_pop(MongoDBRole);
1955                     const auto roleNameGuard =
1956                         MakeGuard([roleComponent]() { ASN1_TYPE_free(roleComponent); });
1957                     if (roleComponent->type != V_ASN1_UTF8STRING) {
1958                         return Status(ErrorCodes::FailedToParse,
1959                                       "role in MongoDBRole must be a UTF8 string");
1960                     }
1961                     std::string roleName(
1962                         reinterpret_cast<char*>(ASN1_STRING_data(roleComponent->value.utf8string)));
1963 
1964                     // Construct a RoleName from the subcomponents
1965                     roles.emplace(RoleName(roleName, roleDB));
1966 
1967                 } else {
1968                     return Status(ErrorCodes::FailedToParse,
1969                                   "Unrecognized entity in MongoDBAuthorizationGrant");
1970                 }
1971             }
1972             LOG(1) << "MONGODB-X509 authorization parsed the following roles from peer "
1973                       "certificate: "
1974                    << [&roles]() {
1975                           StringBuilder sb;
1976                           std::for_each(roles.begin(), roles.end(), [&sb](const RoleName& role) {
1977                               sb << role.toString();
1978                           });
1979                           return sb.str();
1980                       }();
1981         }
1982     }
1983 
1984     return roles;
1985 }
1986 
getSSLErrorMessage(int code)1987 std::string SSLManagerInterface::getSSLErrorMessage(int code) {
1988     // 120 from the SSL documentation for ERR_error_string
1989     static const size_t msglen = 120;
1990 
1991     char msg[msglen];
1992     ERR_error_string_n(code, msg, msglen);
1993     return msg;
1994 }
1995 
_handleSSLError(SSLConnection * conn,int ret)1996 void SSLManager::_handleSSLError(SSLConnection* conn, int ret) {
1997     int code = SSL_get_error(conn, ret);
1998     int err = ERR_get_error();
1999 
2000     switch (code) {
2001         case SSL_ERROR_WANT_READ:
2002         case SSL_ERROR_WANT_WRITE:
2003             // should not happen because we turned on AUTO_RETRY
2004             // However, it turns out this CAN happen during a connect, if the other side
2005             // accepts the socket connection but fails to do the SSL handshake in a timely
2006             // manner.
2007             error() << "SSL: " << code << ", possibly timed out during connect";
2008             break;
2009 
2010         case SSL_ERROR_ZERO_RETURN:
2011             // TODO: Check if we can avoid throwing an exception for this condition
2012             LOG(3) << "SSL network connection closed";
2013             break;
2014         case SSL_ERROR_SYSCALL:
2015             // If ERR_get_error returned 0, the error queue is empty
2016             // check the return value of the actual SSL operation
2017             if (err != 0) {
2018                 error() << "SSL: " << getSSLErrorMessage(err);
2019             } else if (ret == 0) {
2020                 error() << "Unexpected EOF encountered during SSL communication";
2021             } else {
2022                 error() << "The SSL BIO reported an I/O error " << errnoWithDescription();
2023             }
2024             break;
2025         case SSL_ERROR_SSL: {
2026             error() << "SSL: " << getSSLErrorMessage(err);
2027             break;
2028         }
2029 
2030         default:
2031             error() << "unrecognized SSL error";
2032             break;
2033     }
2034     _flushNetworkBIO(conn);
2035     throw SocketException(SocketException::CONNECT_ERROR, "");
2036 }
2037 }  // namespace mongo
2038 
2039 // TODO SERVER-11601 Use NFC Unicode canonicalization
hostNameMatchForX509Certificates(std::string nameToMatch,std::string certHostName)2040 bool mongo::hostNameMatchForX509Certificates(std::string nameToMatch, std::string certHostName) {
2041     nameToMatch = removeFQDNRoot(std::move(nameToMatch));
2042     certHostName = removeFQDNRoot(std::move(certHostName));
2043 
2044     if (certHostName.size() < 2) {
2045         return false;
2046     }
2047 
2048     // match wildcard DNS names
2049     if (certHostName[0] == '*' && certHostName[1] == '.') {
2050         // allow name.example.com if the cert is *.example.com, '*' does not match '.'
2051         const char* subName = strchr(nameToMatch.c_str(), '.');
2052         return subName && !strcasecmp(certHostName.c_str() + 1, subName);
2053     } else {
2054         return !strcasecmp(nameToMatch.c_str(), certHostName.c_str());
2055     }
2056 }
2057 
checkTLSRequest(ConstDataRange dataRange)2058 boost::optional<std::array<std::uint8_t, 7>> mongo::checkTLSRequest(ConstDataRange dataRange) {
2059     // This method's caller should have read in at least one MSGHEADER::Value's worth of data.
2060     // The fragment we are about to examine must be strictly smaller.
2061     static const size_t sizeOfTLSFragmentToRead = 11;
2062     invariant(dataRange.length() >= sizeOfTLSFragmentToRead);
2063 
2064     static_assert(sizeOfTLSFragmentToRead < sizeof(MSGHEADER::Value),
2065                   "checkTLSRequest's caller read a MSGHEADER::Value, which must be larger than "
2066                   "message containing the TLS version");
2067 
2068     ConstDataRangeCursor cdr(dataRange);
2069 
2070     /**
2071      * The fragment we are to examine is a record, containing a handshake, containing a
2072      * ClientHello. We wish to examine the advertised protocol version in the ClientHello.
2073      * The following roughly describes the contents of these structures. Note that we do not
2074      * need, or wish to, examine the entire ClientHello, we're looking exclusively for the
2075      * client_version.
2076      *
2077      * Below is a rough description of the payload we will be examining. We shall perform some
2078      * basic checks to ensure the payload matches these expectations. If it does not, we should
2079      * bail out, and not emit protocol version alerts.
2080      *
2081      * enum {alert(21), handshake(22)} ContentType;
2082      * TLSPlaintext {
2083      *   ContentType type = handshake(22),
2084      *   ProtocolVersion version; // Irrelevant. Clients send the real version in ClientHello.
2085      *   uint16 length;
2086      *   fragment, see Handshake stuct for contents
2087      * ...
2088      * }
2089      *
2090      * enum {client_hello(1)} HandshakeType;
2091      * Handshake {
2092      *   HandshakeType msg_type = client_hello(1);
2093      *   uint24_t length;
2094      *   ClientHello body;
2095      * }
2096      *
2097      * ClientHello {
2098      *   ProtocolVersion client_version; // <- This is the value we want to extract.
2099      * }
2100      */
2101 
2102     static const std::uint8_t ContentType_handshake = 22;
2103     static const std::uint8_t HandshakeType_client_hello = 1;
2104 
2105     using ProtocolVersion = std::array<std::uint8_t, 2>;
2106     static const ProtocolVersion tls10VersionBytes{3, 1};
2107     static const ProtocolVersion tls11VersionBytes{3, 2};
2108 
2109     // Parse the record header.
2110     // Extract the ContentType from the header, and ensure it is a handshake.
2111     StatusWith<std::uint8_t> record_ContentType = cdr.readAndAdvance<std::uint8_t>();
2112     if (!record_ContentType.isOK() || record_ContentType.getValue() != ContentType_handshake) {
2113         return boost::none;
2114     }
2115     // Skip the record's ProtocolVersion. Clients tend to send TLS 1.0 in
2116     // the record, but then their real protocol version in the enclosed ClientHello.
2117     StatusWith<ProtocolVersion> record_protocol_version = cdr.readAndAdvance<ProtocolVersion>();
2118     if (!record_protocol_version.isOK()) {
2119         return boost::none;
2120     }
2121     // Parse the record length. It should be be larger than the remaining expected payload.
2122     auto record_length = cdr.readAndAdvance<BigEndian<std::uint16_t>>();
2123     if (!record_length.isOK() || record_length.getValue() < cdr.length()) {
2124         return boost::none;
2125     }
2126 
2127     // Parse the handshake header.
2128     // Extract the HandshakeType, and ensure it is a ClientHello.
2129     StatusWith<std::uint8_t> handshake_type = cdr.readAndAdvance<std::uint8_t>();
2130     if (!handshake_type.isOK() || handshake_type.getValue() != HandshakeType_client_hello) {
2131         return boost::none;
2132     }
2133     // Extract the handshake length, and ensure it is larger than the remaining expected
2134     // payload. This requires a little work because the packet represents it with a uint24_t.
2135     StatusWith<std::array<std::uint8_t, 3>> handshake_length_bytes =
2136         cdr.readAndAdvance<std::array<std::uint8_t, 3>>();
2137     if (!handshake_length_bytes.isOK()) {
2138         return boost::none;
2139     }
2140     std::uint32_t handshake_length = 0;
2141     for (std::uint8_t handshake_byte : handshake_length_bytes.getValue()) {
2142         handshake_length <<= 8;
2143         handshake_length |= handshake_byte;
2144     }
2145     if (handshake_length < cdr.length()) {
2146         return boost::none;
2147     }
2148     StatusWith<ProtocolVersion> client_version = cdr.readAndAdvance<ProtocolVersion>();
2149     if (!client_version.isOK()) {
2150         return boost::none;
2151     }
2152 
2153     // Invariant: We read exactly as much data as expected.
2154     invariant(cdr.data() - dataRange.data() == sizeOfTLSFragmentToRead);
2155 
2156     auto isProtocolDisabled = [](SSLParams::Protocols protocol) {
2157         const auto& params = getSSLGlobalParams();
2158         return std::find(params.sslDisabledProtocols.begin(),
2159                          params.sslDisabledProtocols.end(),
2160                          protocol) != params.sslDisabledProtocols.end();
2161     };
2162 
2163     auto makeTLSProtocolVersionAlert =
2164         [](const std::array<std::uint8_t, 2>& versionBytes) -> std::array<std::uint8_t, 7> {
2165         /**
2166          * The structure for this alert packet is as follows:
2167          * TLSPlaintext {
2168          *   ContentType type = alert(21);
2169          *   ProtocolVersion = versionBytes;
2170          *   uint16_t length = 2
2171          *   fragment = AlertDescription {
2172          *     AlertLevel level = fatal(2);
2173          *     AlertDescription = protocol_version(70);
2174          *   }
2175          *
2176          */
2177         return std::array<std::uint8_t, 7>{
2178             0x15, versionBytes[0], versionBytes[1], 0x00, 0x02, 0x02, 0x46};
2179     };
2180 
2181     ProtocolVersion version = client_version.getValue();
2182     if (version == tls10VersionBytes && isProtocolDisabled(SSLParams::Protocols::TLS1_0)) {
2183         return makeTLSProtocolVersionAlert(version);
2184     } else if (client_version == tls11VersionBytes &&
2185                isProtocolDisabled(SSLParams::Protocols::TLS1_1)) {
2186         return makeTLSProtocolVersionAlert(version);
2187     }
2188     // TLS1.2 cannot be distinguished from TLS1.3, just by looking at the ProtocolVersion bytes.
2189     // TLS 1.3 compatible clients advertise a "supported_versions" extension, which we would
2190     // have to extract here.
2191     // Hopefully by the time this matters, OpenSSL will properly emit protocol_version alerts.
2192 
2193     return boost::none;
2194 }
2195 
2196 #else
2197 
2198 namespace mongo {
2199 namespace {
MONGO_INITIALIZER(SSLManager)2200 MONGO_INITIALIZER(SSLManager)(InitializerContext*) {
2201     // we need a no-op initializer so that we can depend on SSLManager as a prerequisite in
2202     // non-SSL builds.
2203     return Status::OK();
2204 }
2205 }  // namespace
2206 }  // namespace mongo
2207 
2208 #endif  // #ifdef MONGO_CONFIG_SSL
2209