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