diff options
24 files changed, 1031 insertions, 252 deletions
diff --git a/SConstruct b/SConstruct index a231a57bf1a..b215c6108a6 100644 --- a/SConstruct +++ b/SConstruct @@ -1634,6 +1634,7 @@ elif env.TargetOSIs('windows'): 'version.lib', 'winmm.lib', 'ws2_32.lib', + 'secur32.lib', ], ) @@ -2867,8 +2868,12 @@ def doConfigure(myenv): if ssl_provider == 'native': if conf.env.TargetOSIs('windows'): - # TODO: Implement native crypto for windows - ssl_provider = 'openssl' + ssl_provider = 'windows' + env.SetConfigHeaderDefine("MONGO_CONFIG_SSL_PROVIDER", "SSL_PROVIDER_WINDOWS") + + # TODO: Implement native crypto for windows, for now use tom + conf.env.Append( MONGO_CRYPTO=["tom"] ) + elif conf.env.TargetOSIs('darwin', 'macOS'): conf.env.Append( MONGO_CRYPTO=["apple"] ) if has_option("ssl"): @@ -2880,6 +2885,8 @@ def doConfigure(myenv): if has_option("ssl"): checkOpenSSL(conf) # Working OpenSSL available, use it. + env.SetConfigHeaderDefine("MONGO_CONFIG_SSL_PROVIDER", "SSL_PROVIDER_OPENSSL") + conf.env.Append( MONGO_CRYPTO=["openssl"] ) else: # If we don't need an SSL build, we can get by with TomCrypt. diff --git a/src/mongo/SConscript b/src/mongo/SConscript index ee98793a053..b1030f3a380 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -255,6 +255,7 @@ config_header_substs = ( ('@mongo_config_max_extended_alignment@', 'MONGO_CONFIG_MAX_EXTENDED_ALIGNMENT'), ('@mongo_config_optimized_build@', 'MONGO_CONFIG_OPTIMIZED_BUILD'), ('@mongo_config_ssl@', 'MONGO_CONFIG_SSL'), + ('@mongo_config_ssl_provider@', 'MONGO_CONFIG_SSL_PROVIDER'), ('@mongo_config_ssl_has_asn1_any_definitions@', 'MONGO_CONFIG_HAVE_ASN1_ANY_DEFINITIONS'), ('@mongo_config_has_ssl_set_ecdh_auto@', 'MONGO_CONFIG_HAS_SSL_SET_ECDH_AUTO'), ('@mongo_config_wiredtiger_enabled@', 'MONGO_CONFIG_WIREDTIGER_ENABLED'), diff --git a/src/mongo/config.h.in b/src/mongo/config.h.in index c4c65d366d6..5808477e11f 100644 --- a/src/mongo/config.h.in +++ b/src/mongo/config.h.in @@ -28,6 +28,10 @@ #pragma once +// List of possible SSL providers +#define SSL_PROVIDER_OPENSSL 1 +#define SSL_PROVIDER_WINDOWS 2 + // Define to target byte order (1234 vs 4321) @mongo_config_byte_order@ @@ -67,6 +71,9 @@ // Defined if SSL support is enabled @mongo_config_ssl@ +// Defined if SSL support is enabled with chosen ssl provider +@mongo_config_ssl_provider@ + // Defined if OpenSSL has SEQUENCE_ANY @mongo_config_ssl_has_asn1_any_definitions@ diff --git a/src/mongo/crypto/sha_block_tom.cpp b/src/mongo/crypto/sha_block_tom.cpp index 20e11d34ce8..4908f5ffe20 100644 --- a/src/mongo/crypto/sha_block_tom.cpp +++ b/src/mongo/crypto/sha_block_tom.cpp @@ -35,8 +35,10 @@ #include "mongo/util/assert_util.h" #ifdef MONGO_CONFIG_SSL +#if MONGO_CONFIG_SSL_PROVIDER != SSL_PROVIDER_WINDOWS #error This file should not be included if compiling with SSL support #endif +#endif #include "tomcrypt.h" diff --git a/src/mongo/platform/windows_basic.h b/src/mongo/platform/windows_basic.h index 86e1396aefd..defe7b68b09 100644 --- a/src/mongo/platform/windows_basic.h +++ b/src/mongo/platform/windows_basic.h @@ -95,6 +95,8 @@ #include <sspi.h> +#include <schannel.h> + #undef WIN32_NO_STATUS // Obtain a definition for the ntstatus type. diff --git a/src/mongo/util/net/ssl/context.hpp b/src/mongo/util/net/ssl/context.hpp index bf2f464f1f4..e306f79c1de 100644 --- a/src/mongo/util/net/ssl/context.hpp +++ b/src/mongo/util/net/ssl/context.hpp @@ -1,95 +1,40 @@ -// -// ssl/context.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + +#include "mongo/util/net/ssl/context_schannel.hpp" + +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL + +#include "mongo/util/net/ssl/context_openssl.hpp" + +#else +#error "Unknown SSL Provider" +#endif -#ifndef ASIO_SSL_CONTEXT_HPP -#define ASIO_SSL_CONTEXT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include <string> -#include "asio/buffer.hpp" -#include "asio/io_context.hpp" -#include "mongo/util/net/ssl/context_base.hpp" -#include "mongo/util/net/ssl/detail/openssl_types.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace ssl { - -class context - : public context_base, - private noncopyable -{ -public: - /// The native handle type of the SSL context. - typedef SSL_CTX* native_handle_type; - - /// Constructor. - ASIO_DECL explicit context(method m); - -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a context from another. - /** - * This constructor moves an SSL context from one object to another. - * - * @param other The other context object from which the move will occur. - * - * @note Following the move, the following operations only are valid for the - * moved-from object: - * @li Destruction. - * @li As a target for move-assignment. - */ - ASIO_DECL context(context&& other); - - /// Move-assign a context from another. - /** - * This assignment operator moves an SSL context from one object to another. - * - * @param other The other context object from which the move will occur. - * - * @note Following the move, the following operations only are valid for the - * moved-from object: - * @li Destruction. - * @li As a target for move-assignment. - */ - ASIO_DECL context& operator=(context&& other); -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destructor. - ASIO_DECL ~context(); - - /// Get the underlying implementation in the native type. - /** - * This function may be used to obtain the underlying implementation of the - * context. This is intended to allow access to context functionality that is - * not otherwise provided. - */ - ASIO_DECL native_handle_type native_handle(); - -private: - // The underlying native implementation. - native_handle_type handle_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#if defined(ASIO_HEADER_ONLY) -# include "mongo/util/net/ssl/impl/context.ipp" -#endif // defined(ASIO_HEADER_ONLY) - -#endif // ASIO_SSL_CONTEXT_HPP diff --git a/src/mongo/util/net/ssl/context_base.hpp b/src/mongo/util/net/ssl/context_base.hpp index 0b3351ebeae..1eca98fa729 100644 --- a/src/mongo/util/net/ssl/context_base.hpp +++ b/src/mongo/util/net/ssl/context_base.hpp @@ -16,7 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" + +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL #include "mongo/util/net/ssl/detail/openssl_types.hpp" +#endif #include "asio/detail/push_options.hpp" @@ -98,6 +101,7 @@ public: /// Bitmask type for SSL options. typedef long options; +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL #if defined(GENERATING_DOCUMENTATION) /// Implement various bug workarounds. static const long default_workarounds = implementation_defined; @@ -144,6 +148,7 @@ public: ASIO_STATIC_CONSTANT(long, no_compression = 0x20000L); # endif // defined(SSL_OP_NO_COMPRESSION) #endif +#endif protected: /// Protected destructor to prevent deletion through this type. diff --git a/src/mongo/util/net/ssl/context_openssl.hpp b/src/mongo/util/net/ssl/context_openssl.hpp new file mode 100644 index 00000000000..e457886ff02 --- /dev/null +++ b/src/mongo/util/net/ssl/context_openssl.hpp @@ -0,0 +1,95 @@ +// +// ssl/context.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SSL_CONTEXT_OPENSSL_HPP +#define ASIO_SSL_CONTEXT_OPENSSL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#include <string> +#include "asio/buffer.hpp" +#include "asio/io_context.hpp" +#include "mongo/util/net/ssl/context_base.hpp" +#include "mongo/util/net/ssl/detail/openssl_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { + +class context + : public context_base, + private noncopyable +{ +public: + /// The native handle type of the SSL context. + typedef SSL_CTX* native_handle_type; + + /// Constructor. + ASIO_DECL explicit context(method m); + +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a context from another. + /** + * This constructor moves an SSL context from one object to another. + * + * @param other The other context object from which the move will occur. + * + * @note Following the move, the following operations only are valid for the + * moved-from object: + * @li Destruction. + * @li As a target for move-assignment. + */ + ASIO_DECL context(context&& other); + + /// Move-assign a context from another. + /** + * This assignment operator moves an SSL context from one object to another. + * + * @param other The other context object from which the move will occur. + * + * @note Following the move, the following operations only are valid for the + * moved-from object: + * @li Destruction. + * @li As a target for move-assignment. + */ + ASIO_DECL context& operator=(context&& other); +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destructor. + ASIO_DECL ~context(); + + /// Get the underlying implementation in the native type. + /** + * This function may be used to obtain the underlying implementation of the + * context. This is intended to allow access to context functionality that is + * not otherwise provided. + */ + ASIO_DECL native_handle_type native_handle(); + +private: + // The underlying native implementation. + native_handle_type handle_; +}; + +} // namespace ssl +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "mongo/util/net/ssl/impl/context_openssl.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // ASIO_SSL_CONTEXT_OPENSSL_HPP diff --git a/src/mongo/util/net/ssl/context_schannel.hpp b/src/mongo/util/net/ssl/context_schannel.hpp new file mode 100644 index 00000000000..12293cbc8e9 --- /dev/null +++ b/src/mongo/util/net/ssl/context_schannel.hpp @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "asio/detail/config.hpp" + +#include <string> +#include "asio/buffer.hpp" +#include "asio/io_context.hpp" +#include "mongo/util/net/ssl/context_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { + +class context + : public context_base, + private noncopyable +{ +public: + /// The native handle type of the SSL context. + typedef SCHANNEL_CRED* native_handle_type; + + /// Constructor. + ASIO_DECL explicit context(method m); + +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a context from another. + /** + * This constructor moves an SSL context from one object to another. + * + * @param other The other context object from which the move will occur. + * + * @note Following the move, the following operations only are valid for the + * moved-from object: + * @li Destruction. + * @li As a target for move-assignment. + */ + ASIO_DECL context(context&& other); + + /// Move-assign a context from another. + /** + * This assignment operator moves an SSL context from one object to another. + * + * @param other The other context object from which the move will occur. + * + * @note Following the move, the following operations only are valid for the + * moved-from object: + * @li Destruction. + * @li As a target for move-assignment. + */ + ASIO_DECL context& operator=(context&& other); +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destructor. + ASIO_DECL ~context(); + + /// Get the underlying implementation in the native type. + /** + * This function may be used to obtain the underlying implementation of the + * context. This is intended to allow access to context functionality that is + * not otherwise provided. + */ + ASIO_DECL native_handle_type native_handle(); + +private: + // The underlying native implementation. + native_handle_type handle_; +}; + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "mongo/util/net/ssl/impl/context_schannel.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +} // namespace ssl +} // namespace asio diff --git a/src/mongo/util/net/ssl/detail/engine.hpp b/src/mongo/util/net/ssl/detail/engine.hpp index e49332d59b6..e190753a3f1 100644 --- a/src/mongo/util/net/ssl/detail/engine.hpp +++ b/src/mongo/util/net/ssl/detail/engine.hpp @@ -1,142 +1,40 @@ -// -// ssl/detail/engine.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + +#include "mongo/util/net/ssl/detail/engine_schannel.hpp" + +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL + +#include "mongo/util/net/ssl/detail/engine_openssl.hpp" + +#else +#error "Unknown SSL Provider" +#endif -#ifndef ASIO_SSL_DETAIL_ENGINE_HPP -#define ASIO_SSL_DETAIL_ENGINE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include "asio/buffer.hpp" -#include "asio/detail/static_mutex.hpp" -#include "mongo/util/net/ssl/detail/openssl_types.hpp" -#include "mongo/util/net/ssl/stream_base.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -class engine -{ -public: - enum want - { - // Returned by functions to indicate that the engine wants input. The input - // buffer should be updated to point to the data. The engine then needs to - // be called again to retry the operation. - want_input_and_retry = -2, - - // Returned by functions to indicate that the engine wants to write output. - // The output buffer points to the data to be written. The engine then - // needs to be called again to retry the operation. - want_output_and_retry = -1, - - // Returned by functions to indicate that the engine doesn't need input or - // output. - want_nothing = 0, - - // Returned by functions to indicate that the engine wants to write output. - // The output buffer points to the data to be written. After that the - // operation is complete, and the engine does not need to be called again. - want_output = 1 - }; - - // Construct a new engine for the specified context. - ASIO_DECL explicit engine(SSL_CTX* context); - - // Destructor. - ASIO_DECL ~engine(); - - // Get the underlying implementation in the native type. - ASIO_DECL SSL* native_handle(); - - // Perform an SSL handshake using either SSL_connect (client-side) or - // SSL_accept (server-side). - ASIO_DECL want handshake( - stream_base::handshake_type type, asio::error_code& ec); - - // Perform a graceful shutdown of the SSL session. - ASIO_DECL want shutdown(asio::error_code& ec); - - // Write bytes to the SSL session. - ASIO_DECL want write(const asio::const_buffer& data, - asio::error_code& ec, std::size_t& bytes_transferred); - - // Read bytes from the SSL session. - ASIO_DECL want read(const asio::mutable_buffer& data, - asio::error_code& ec, std::size_t& bytes_transferred); - - // Get output data to be written to the transport. - ASIO_DECL asio::mutable_buffer get_output( - const asio::mutable_buffer& data); - - // Put input data that was read from the transport. - ASIO_DECL asio::const_buffer put_input( - const asio::const_buffer& data); - - // Map an error::eof code returned by the underlying transport according to - // the type and state of the SSL session. Returns a const reference to the - // error code object, suitable for passing to a completion handler. - ASIO_DECL const asio::error_code& map_error_code( - asio::error_code& ec) const; - -private: - // Disallow copying and assignment. - engine(const engine&); - engine& operator=(const engine&); - -#if (OPENSSL_VERSION_NUMBER < 0x10000000L) - // The SSL_accept function may not be thread safe. This mutex is used to - // protect all calls to the SSL_accept function. - ASIO_DECL static asio::detail::static_mutex& accept_mutex(); -#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) - - // Perform one operation. Returns >= 0 on success or error, want_read if the - // operation needs more input, or want_write if it needs to write some output - // before the operation can complete. - ASIO_DECL want perform(int (engine::* op)(void*, std::size_t), - void* data, std::size_t length, asio::error_code& ec, - std::size_t* bytes_transferred); - - // Adapt the SSL_accept function to the signature needed for perform(). - ASIO_DECL int do_accept(void*, std::size_t); - - // Adapt the SSL_connect function to the signature needed for perform(). - ASIO_DECL int do_connect(void*, std::size_t); - - // Adapt the SSL_shutdown function to the signature needed for perform(). - ASIO_DECL int do_shutdown(void*, std::size_t); - - // Adapt the SSL_read function to the signature needed for perform(). - ASIO_DECL int do_read(void* data, std::size_t length); - - // Adapt the SSL_write function to the signature needed for perform(). - ASIO_DECL int do_write(void* data, std::size_t length); - - SSL* ssl_; - BIO* ext_bio_; -}; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#if defined(ASIO_HEADER_ONLY) -# include "mongo/util/net/ssl/detail/impl/engine.ipp" -#endif // defined(ASIO_HEADER_ONLY) - -#endif // ASIO_SSL_DETAIL_ENGINE_HPP diff --git a/src/mongo/util/net/ssl/detail/engine_openssl.hpp b/src/mongo/util/net/ssl/detail/engine_openssl.hpp new file mode 100644 index 00000000000..75657d6307d --- /dev/null +++ b/src/mongo/util/net/ssl/detail/engine_openssl.hpp @@ -0,0 +1,142 @@ +// +// ssl/detail/engine.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SSL_DETAIL_ENGINE_OPENSSL_HPP +#define ASIO_SSL_DETAIL_ENGINE_OPENSSL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#include "asio/buffer.hpp" +#include "asio/detail/static_mutex.hpp" +#include "mongo/util/net/ssl/detail/openssl_types.hpp" +#include "mongo/util/net/ssl/stream_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +class engine +{ +public: + enum want + { + // Returned by functions to indicate that the engine wants input. The input + // buffer should be updated to point to the data. The engine then needs to + // be called again to retry the operation. + want_input_and_retry = -2, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. The engine then + // needs to be called again to retry the operation. + want_output_and_retry = -1, + + // Returned by functions to indicate that the engine doesn't need input or + // output. + want_nothing = 0, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. After that the + // operation is complete, and the engine does not need to be called again. + want_output = 1 + }; + + // Construct a new engine for the specified context. + ASIO_DECL explicit engine(SSL_CTX* context); + + // Destructor. + ASIO_DECL ~engine(); + + // Get the underlying implementation in the native type. + ASIO_DECL SSL* native_handle(); + + // Perform an SSL handshake using either SSL_connect (client-side) or + // SSL_accept (server-side). + ASIO_DECL want handshake( + stream_base::handshake_type type, asio::error_code& ec); + + // Perform a graceful shutdown of the SSL session. + ASIO_DECL want shutdown(asio::error_code& ec); + + // Write bytes to the SSL session. + ASIO_DECL want write(const asio::const_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred); + + // Read bytes from the SSL session. + ASIO_DECL want read(const asio::mutable_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred); + + // Get output data to be written to the transport. + ASIO_DECL asio::mutable_buffer get_output( + const asio::mutable_buffer& data); + + // Put input data that was read from the transport. + ASIO_DECL asio::const_buffer put_input( + const asio::const_buffer& data); + + // Map an error::eof code returned by the underlying transport according to + // the type and state of the SSL session. Returns a const reference to the + // error code object, suitable for passing to a completion handler. + ASIO_DECL const asio::error_code& map_error_code( + asio::error_code& ec) const; + +private: + // Disallow copying and assignment. + engine(const engine&); + engine& operator=(const engine&); + +#if (OPENSSL_VERSION_NUMBER < 0x10000000L) + // The SSL_accept function may not be thread safe. This mutex is used to + // protect all calls to the SSL_accept function. + ASIO_DECL static asio::detail::static_mutex& accept_mutex(); +#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + + // Perform one operation. Returns >= 0 on success or error, want_read if the + // operation needs more input, or want_write if it needs to write some output + // before the operation can complete. + ASIO_DECL want perform(int (engine::* op)(void*, std::size_t), + void* data, std::size_t length, asio::error_code& ec, + std::size_t* bytes_transferred); + + // Adapt the SSL_accept function to the signature needed for perform(). + ASIO_DECL int do_accept(void*, std::size_t); + + // Adapt the SSL_connect function to the signature needed for perform(). + ASIO_DECL int do_connect(void*, std::size_t); + + // Adapt the SSL_shutdown function to the signature needed for perform(). + ASIO_DECL int do_shutdown(void*, std::size_t); + + // Adapt the SSL_read function to the signature needed for perform(). + ASIO_DECL int do_read(void* data, std::size_t length); + + // Adapt the SSL_write function to the signature needed for perform(). + ASIO_DECL int do_write(void* data, std::size_t length); + + SSL* ssl_; + BIO* ext_bio_; +}; + +} // namespace detail +} // namespace ssl +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "mongo/util/net/ssl/detail/impl/engine_openssl.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // ASIO_SSL_DETAIL_ENGINE_OPENSSL_HPP diff --git a/src/mongo/util/net/ssl/detail/engine_schannel.hpp b/src/mongo/util/net/ssl/detail/engine_schannel.hpp new file mode 100644 index 00000000000..fa3bad1a7af --- /dev/null +++ b/src/mongo/util/net/ssl/detail/engine_schannel.hpp @@ -0,0 +1,120 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "asio/detail/config.hpp" + +#include "asio/buffer.hpp" +#include "asio/detail/static_mutex.hpp" +#include "mongo/util/net/ssl/stream_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +class engine +{ +public: + enum want + { + // Returned by functions to indicate that the engine wants input. The input + // buffer should be updated to point to the data. The engine then needs to + // be called again to retry the operation. + want_input_and_retry = -2, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. The engine then + // needs to be called again to retry the operation. + want_output_and_retry = -1, + + // Returned by functions to indicate that the engine doesn't need input or + // output. + want_nothing = 0, + + // Returned by functions to indicate that the engine wants to write output. + // The output buffer points to the data to be written. After that the + // operation is complete, and the engine does not need to be called again. + want_output = 1 + }; + + // Construct a new engine for the specified context. + ASIO_DECL explicit engine(SCHANNEL_CRED* context); + + // Destructor. + ASIO_DECL ~engine(); + + // Get the underlying implementation in the native type. + ASIO_DECL PCtxtHandle native_handle(); + + // Perform an SSL handshake using either SSL_connect (client-side) or + // SSL_accept (server-side). + ASIO_DECL want handshake( + stream_base::handshake_type type, asio::error_code& ec); + + // Perform a graceful shutdown of the SSL session. + ASIO_DECL want shutdown(asio::error_code& ec); + + // Write bytes to the SSL session. + ASIO_DECL want write(const asio::const_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred); + + // Read bytes from the SSL session. + ASIO_DECL want read(const asio::mutable_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred); + + // Get output data to be written to the transport. + ASIO_DECL asio::mutable_buffer get_output( + const asio::mutable_buffer& data); + + // Put input data that was read from the transport. + ASIO_DECL asio::const_buffer put_input( + const asio::const_buffer& data); + + // Map an error::eof code returned by the underlying transport according to + // the type and state of the SSL session. Returns a const reference to the + // error code object, suitable for passing to a completion handler. + ASIO_DECL const asio::error_code& map_error_code( + asio::error_code& ec) const; + +private: + // Disallow copying and assignment. + engine(const engine&); + engine& operator=(const engine&); + +private: + +}; + +#include "asio/detail/pop_options.hpp" + +} // namespace detail +} // namespace ssl +} // namespace asio diff --git a/src/mongo/util/net/ssl/detail/impl/engine.ipp b/src/mongo/util/net/ssl/detail/impl/engine_openssl.ipp index 6f29cc2d478..c53a31e6a26 100644 --- a/src/mongo/util/net/ssl/detail/impl/engine.ipp +++ b/src/mongo/util/net/ssl/detail/impl/engine_openssl.ipp @@ -8,8 +8,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_SSL_DETAIL_IMPL_ENGINE_IPP -#define ASIO_SSL_DETAIL_IMPL_ENGINE_IPP +#ifndef ASIO_SSL_DETAIL_IMPL_ENGINE_OPENSSL_IPP +#define ASIO_SSL_DETAIL_IMPL_ENGINE_OPENSSL_IPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -261,4 +261,4 @@ int engine::do_write(void* data, std::size_t length) #include "asio/detail/pop_options.hpp" -#endif // ASIO_SSL_DETAIL_IMPL_ENGINE_IPP +#endif // ASIO_SSL_DETAIL_IMPL_ENGINE_OPENSSL_IPP diff --git a/src/mongo/util/net/ssl/detail/impl/engine_schannel.ipp b/src/mongo/util/net/ssl/detail/impl/engine_schannel.ipp new file mode 100644 index 00000000000..41aca7f789f --- /dev/null +++ b/src/mongo/util/net/ssl/detail/impl/engine_schannel.ipp @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "asio/detail/config.hpp" + +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "mongo/util/net/ssl/detail/engine.hpp" +#include "mongo/util/net/ssl/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +engine::engine(SCHANNEL_CRED* context) +{ +} + +engine::~engine() +{ +} + +PCtxtHandle engine::native_handle() +{ + return nullptr; +} + +engine::want engine::handshake( + stream_base::handshake_type type, asio::error_code& ec) +{ + return want::want_nothing; +} + +engine::want engine::shutdown(asio::error_code& ec) +{ + return want::want_nothing; +} + +engine::want engine::write(const asio::const_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + return want::want_nothing; +} + +engine::want engine::read(const asio::mutable_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + return want::want_nothing; +} + +asio::mutable_buffer engine::get_output( + const asio::mutable_buffer& data) +{ + return asio::mutable_buffer(nullptr, 0); +} + +asio::const_buffer engine::put_input( + const asio::const_buffer& data) +{ + return asio::const_buffer(nullptr, 0); +} + +const asio::error_code& engine::map_error_code( + asio::error_code& ec) const +{ + return ec; +} + +#include "asio/detail/pop_options.hpp" + +} // namespace detail +} // namespace ssl +} // namespace asio diff --git a/src/mongo/util/net/ssl/detail/stream_core.hpp b/src/mongo/util/net/ssl/detail/stream_core.hpp index ddd97418402..ae240d463af 100644 --- a/src/mongo/util/net/ssl/detail/stream_core.hpp +++ b/src/mongo/util/net/ssl/detail/stream_core.hpp @@ -37,7 +37,13 @@ struct stream_core // sufficient to hold the largest possible TLS record. enum { max_tls_record_size = 17 * 1024 }; +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + stream_core(SCHANNEL_CRED* context, asio::io_context& io_context) +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL stream_core(SSL_CTX* context, asio::io_context& io_context) +#else +#error "Unknown SSL Provider" +#endif : engine_(context), pending_read_(io_context), pending_write_(io_context), diff --git a/src/mongo/util/net/ssl/error.hpp b/src/mongo/util/net/ssl/error.hpp index 18cb2f193a0..6c96c3efe93 100644 --- a/src/mongo/util/net/ssl/error.hpp +++ b/src/mongo/util/net/ssl/error.hpp @@ -17,7 +17,10 @@ #include "asio/detail/config.hpp" #include "asio/error_code.hpp" + +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL #include "mongo/util/net/ssl/detail/openssl_types.hpp" +#endif #include "asio/detail/push_options.hpp" @@ -45,7 +48,7 @@ enum stream_errors #if defined(GENERATING_DOCUMENTATION) /// The underlying stream closed before the ssl stream gracefully shut down. stream_truncated -#elif (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL) +#elif (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL) && MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL stream_truncated = ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) #else stream_truncated = 1 diff --git a/src/mongo/util/net/ssl/impl/context.ipp b/src/mongo/util/net/ssl/impl/context_openssl.ipp index 52ce75c1e52..e2eeb2b83d4 100644 --- a/src/mongo/util/net/ssl/impl/context.ipp +++ b/src/mongo/util/net/ssl/impl/context_openssl.ipp @@ -9,8 +9,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_SSL_IMPL_CONTEXT_IPP -#define ASIO_SSL_IMPL_CONTEXT_IPP +#ifndef ASIO_SSL_IMPL_CONTEXT_OPENSSL_IPP +#define ASIO_SSL_IMPL_CONTEXT_OPENSSL_IPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -328,4 +328,4 @@ context::native_handle_type context::native_handle() #include "asio/detail/pop_options.hpp" -#endif // ASIO_SSL_IMPL_CONTEXT_IPP +#endif // ASIO_SSL_IMPL_CONTEXT_OPENSSL_IPP diff --git a/src/mongo/util/net/ssl/impl/context_schannel.ipp b/src/mongo/util/net/ssl/impl/context_schannel.ipp new file mode 100644 index 00000000000..99f6541c24d --- /dev/null +++ b/src/mongo/util/net/ssl/impl/context_schannel.ipp @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "asio/detail/config.hpp" + +#include <cstring> +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "mongo/util/net/ssl/context.hpp" +#include "mongo/util/net/ssl/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { + + +context::context(context::method m) + : handle_(0) +{ +} + +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +context::context(context&& other) +{ + handle_ = other.handle_; + other.handle_ = 0; +} + +context& context::operator=(context&& other) +{ + context tmp(ASIO_MOVE_CAST(context)(*this)); + handle_ = other.handle_; + other.handle_ = 0; + return *this; +} +#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + +context::~context() +{ +} + +context::native_handle_type context::native_handle() +{ + return handle_; +} + +} // namespace ssl +} // namespace asio + +#include "asio/detail/pop_options.hpp" diff --git a/src/mongo/util/net/ssl/impl/error.ipp b/src/mongo/util/net/ssl/impl/error.ipp index 76ef5bdadda..5de8a890454 100644 --- a/src/mongo/util/net/ssl/impl/error.ipp +++ b/src/mongo/util/net/ssl/impl/error.ipp @@ -32,11 +32,22 @@ public: return "asio.ssl"; } +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + std::string message(int value) const + { + // TODO: call FormatMessage + ASIO_ASSERT(false); + return "asio.ssl error"; + } +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL std::string message(int value) const { const char* s = ::ERR_reason_error_string(value); return s ? s : "asio.ssl error"; } +#else +#error "Unknown SSL Provider" +#endif }; } // namespace detail diff --git a/src/mongo/util/net/ssl/impl/src.hpp b/src/mongo/util/net/ssl/impl/src.hpp index 45b5b3533d1..81b903d0f5e 100644 --- a/src/mongo/util/net/ssl/impl/src.hpp +++ b/src/mongo/util/net/ssl/impl/src.hpp @@ -19,8 +19,23 @@ # error Do not compile Asio library source with ASIO_HEADER_ONLY defined #endif -#include "mongo/util/net/ssl/impl/context.ipp" +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + +#include "mongo/util/net/ssl/impl/context_schannel.ipp" +#include "mongo/util/net/ssl/impl/error.ipp" +#include "mongo/util/net/ssl/detail/impl/engine_schannel.ipp" + + +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL + +#include "mongo/util/net/ssl/impl/context_openssl.ipp" #include "mongo/util/net/ssl/impl/error.ipp" -#include "mongo/util/net/ssl/detail/impl/engine.ipp" +#include "mongo/util/net/ssl/detail/impl/engine_openssl.ipp" + +#else +#error "Unknown SSL Provider" +#endif + + #endif // ASIO_SSL_IMPL_SRC_HPP diff --git a/src/mongo/util/net/ssl/stream.hpp b/src/mongo/util/net/ssl/stream.hpp index 6677493fa80..bcf92cf9eaa 100644 --- a/src/mongo/util/net/ssl/stream.hpp +++ b/src/mongo/util/net/ssl/stream.hpp @@ -66,7 +66,13 @@ class stream : { public: /// The native handle type of the SSL stream. +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + typedef PCtxtHandle native_handle_type; +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL typedef SSL* native_handle_type; +#else +#error "Unknown SSL Provider" +#endif /// The type of the next layer. typedef typename remove_reference<Stream>::type next_layer_type; diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h index ea02f94496c..bc640dc4b88 100644 --- a/src/mongo/util/net/ssl_manager.h +++ b/src/mongo/util/net/ssl_manager.h @@ -43,9 +43,11 @@ #include "mongo/util/net/ssl_types.h" #include "mongo/util/time_support.h" +// SChannel implementation +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL #include <openssl/err.h> #include <openssl/ssl.h> - +#endif #endif // #ifdef MONGO_CONFIG_SSL namespace mongo { @@ -59,6 +61,16 @@ const std::string getSSLVersion(const std::string& prefix, const std::string& su namespace mongo { struct SSLParams; +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL +typedef SSL_CTX* SSLContextType; +typedef SSL* SSLConnectionType; +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS +typedef SCHANNEL_CRED* SSLContextType; +typedef PCtxtHandle SSLConnectionType; +#else +#error "Unknown SSL Provider" +#endif + /** * Maintain per connection SSL state for the Sock class. Used by SSLManagerInterface to perform SSL * operations. @@ -166,7 +178,7 @@ public: * acceptable on non-blocking connections are set. "direction" specifies whether the SSL_CTX * will be used to make outgoing connections or accept incoming connections. */ - virtual Status initSSLContext(SSL_CTX* context, + virtual Status initSSLContext(SSLContextType context, const SSLParams& params, ConnectionDirection direction) = 0; @@ -178,7 +190,7 @@ public: * X509 authorization will be returned. */ virtual StatusWith<boost::optional<SSLPeerInfo>> parseAndValidatePeerCertificate( - SSL* ssl, const std::string& remoteHost) = 0; + SSLConnectionType ssl, const std::string& remoteHost) = 0; }; // Access SSL functions through this instance. diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp new file mode 100644 index 00000000000..bcac27724a0 --- /dev/null +++ b/src/mongo/util/net/ssl_manager_windows.cpp @@ -0,0 +1,209 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kNetwork + +#include "mongo/platform/basic.h" + +#include "mongo/util/net/ssl_manager.h" + +#include <asio.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <fstream> +#include <iostream> +#include <sstream> +#include <stack> +#include <string> +#include <vector> + +#include "mongo/base/init.h" +#include "mongo/base/initializer_context.h" +#include "mongo/bson/bsonobjbuilder.h" +#include "mongo/config.h" +#include "mongo/db/server_parameters.h" +#include "mongo/platform/atomic_word.h" +#include "mongo/stdx/memory.h" +#include "mongo/transport/session.h" +#include "mongo/util/concurrency/mutex.h" +#include "mongo/util/debug_util.h" +#include "mongo/util/exit.h" +#include "mongo/util/log.h" +#include "mongo/util/mongoutils/str.h" +#include "mongo/util/net/private/ssl_expiration.h" +#include "mongo/util/net/sock.h" +#include "mongo/util/net/socket_exception.h" +#include "mongo/util/net/ssl.hpp" +#include "mongo/util/net/ssl_options.h" +#include "mongo/util/net/ssl_types.h" +#include "mongo/util/scopeguard.h" +#include "mongo/util/text.h" +#include "mongo/util/uuid.h" + +namespace mongo { + +namespace { + +SimpleMutex sslManagerMtx; +SSLManagerInterface* theSSLManagerWindows = NULL; + + +} // namespace + +/** + * Manage state for a SSL Connection. Used by the Socket class. + */ +class SSLConnectionWindows : public SSLConnectionInterface { +public: + ~SSLConnectionWindows(); + + std::string getSNIServerName() const final; +}; + + +class SSLManagerWindows : public SSLManagerInterface { +public: + explicit SSLManagerWindows(const SSLParams& params, bool isServer); + + /** + * Initializes an OpenSSL context according to the provided settings. Only settings which are + * acceptable on non-blocking connections are set. + */ + Status initSSLContext(SCHANNEL_CRED* cred, + const SSLParams& params, + ConnectionDirection direction) final; + + virtual SSLConnectionInterface* connect(Socket* socket); + + virtual SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len); + + virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated( + const SSLConnectionInterface* conn, const std::string& remoteHost); + + StatusWith<boost::optional<SSLPeerInfo>> parseAndValidatePeerCertificate( + PCtxtHandle ssl, const std::string& remoteHost) final; + + + virtual const SSLConfiguration& getSSLConfiguration() const { + return _sslConfiguration; + } + + virtual int SSL_read(SSLConnectionInterface* conn, void* buf, int num); + + virtual int SSL_write(SSLConnectionInterface* conn, const void* buf, int num); + + virtual int SSL_shutdown(SSLConnectionInterface* conn); + +private: + bool _weakValidation; + bool _allowInvalidCertificates; + bool _allowInvalidHostnames; + SSLConfiguration _sslConfiguration; +}; + +// Global variable indicating if this is a server or a client instance +bool isSSLServer = false; + +MONGO_INITIALIZER(SSLManager)(InitializerContext*) { + stdx::lock_guard<SimpleMutex> lck(sslManagerMtx); + if (!isSSLServer || (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled)) { + theSSLManagerWindows = new SSLManagerWindows(sslGlobalParams, isSSLServer); + } + + return Status::OK(); +} + +SSLConnectionWindows::~SSLConnectionWindows() {} + +std::string SSLConnectionWindows::getSNIServerName() const { + invariant(false); + return ""; +} + +std::unique_ptr<SSLManagerInterface> SSLManagerInterface::create(const SSLParams& params, + bool isServer) { + return stdx::make_unique<SSLManagerWindows>(params, isServer); +} + +SSLManagerInterface* getSSLManager() { + stdx::lock_guard<SimpleMutex> lck(sslManagerMtx); + if (theSSLManagerWindows) + return theSSLManagerWindows; + return NULL; +} + +SSLManagerWindows::SSLManagerWindows(const SSLParams& params, bool isServer) + : _weakValidation(params.sslWeakCertificateValidation), + _allowInvalidCertificates(params.sslAllowInvalidCertificates), + _allowInvalidHostnames(params.sslAllowInvalidHostnames) {} + +int SSLManagerWindows::SSL_read(SSLConnectionInterface* connInterface, void* buf, int num) { + invariant(false); + return 0; +} + +int SSLManagerWindows::SSL_write(SSLConnectionInterface* connInterface, const void* buf, int num) { + invariant(false); + return 0; +} + +int SSLManagerWindows::SSL_shutdown(SSLConnectionInterface* conn) { + invariant(false); + return 0; +} + +Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred, + const SSLParams& params, + ConnectionDirection direction) { + + return Status::OK(); +} + +SSLConnectionInterface* SSLManagerWindows::connect(Socket* socket) { + return nullptr; +} + +SSLConnectionInterface* SSLManagerWindows::accept(Socket* socket, + const char* initialBytes, + int len) { + return nullptr; +} + +SSLPeerInfo SSLManagerWindows::parseAndValidatePeerCertificateDeprecated( + const SSLConnectionInterface* conn, const std::string& remoteHost) { + return SSLPeerInfo(); +} + +StatusWith<boost::optional<SSLPeerInfo>> SSLManagerWindows::parseAndValidatePeerCertificate( + PCtxtHandle ssl, const std::string& remoteHost) { + + return {boost::none}; +} + + +} // namespace mongo diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp index 41933e8c9ac..9536caf1516 100644 --- a/src/mongo/util/version.cpp +++ b/src/mongo/util/version.cpp @@ -34,8 +34,10 @@ #include "mongo/config.h" #ifdef MONGO_CONFIG_SSL +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL #include <openssl/crypto.h> #endif +#endif #include <pcrecpp.h> @@ -145,7 +147,13 @@ void VersionInfoInterface::appendBuildInfo(BSONObjBuilder* result) const { BSONObjBuilder opensslInfo(result->subobjStart("openssl")); #ifdef MONGO_CONFIG_SSL +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL opensslInfo << "running" << openSSLVersion() << "compiled" << OPENSSL_VERSION_TEXT; +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_WINDOWS + opensslInfo << "Windows SChannel"; +#else +#error "Unknown SSL Provider" +#endif // MONGO_CONFIG_SSL_PROVIDER #else opensslInfo << "running" << "disabled" @@ -168,9 +176,9 @@ void VersionInfoInterface::appendBuildInfo(BSONObjBuilder* result) const { } std::string VersionInfoInterface::openSSLVersion(StringData prefix, StringData suffix) const { -#ifndef MONGO_CONFIG_SSL +#if !defined(MONGO_CONFIG_SSL) || MONGO_CONFIG_SSL_PROVIDER != SSL_PROVIDER_OPENSSL return ""; -#else +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL return prefix.toString() + SSLeay_version(SSLEAY_VERSION) + suffix; #endif } @@ -182,7 +190,7 @@ void VersionInfoInterface::logTargetMinOS() const { void VersionInfoInterface::logBuildInfo() const { log() << "git version: " << gitVersion(); -#ifdef MONGO_CONFIG_SSL +#if defined(MONGO_CONFIG_SSL) && MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL log() << openSSLVersion("OpenSSL version: "); #endif |