diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2018-02-20 12:39:37 -0500 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2018-03-17 12:45:29 -0400 |
commit | 65191bbe5c00bb419a7466fb7db43e220035f776 (patch) | |
tree | 1f2c00082b35eafbcdaa1539ed680ac84949a640 /src/mongo/util/net/ssl | |
parent | 9eea82ee2a0e37da90cbb549d55c5eac8aa69a55 (diff) | |
download | mongo-65191bbe5c00bb419a7466fb7db43e220035f776.tar.gz |
SERVER-22412 Implement a secure transport ASIO backend
Diffstat (limited to 'src/mongo/util/net/ssl')
-rw-r--r-- | src/mongo/util/net/ssl/apple.hpp | 98 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/context.hpp | 4 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/context_apple.hpp | 82 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/detail/engine.hpp | 4 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/detail/engine_apple.hpp | 103 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/detail/impl/engine_apple.ipp | 347 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/detail/stream_core.hpp | 4 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/impl/error.ipp | 10 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/impl/src.hpp | 5 | ||||
-rw-r--r-- | src/mongo/util/net/ssl/stream.hpp | 3 |
10 files changed, 660 insertions, 0 deletions
diff --git a/src/mongo/util/net/ssl/apple.hpp b/src/mongo/util/net/ssl/apple.hpp new file mode 100644 index 00000000000..e38e2b46c97 --- /dev/null +++ b/src/mongo/util/net/ssl/apple.hpp @@ -0,0 +1,98 @@ +/** + * 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 + +#if MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + +#include <CoreFoundation/CoreFoundation.h> +#include <Security/Security.h> +#include <memory> +#include <string> + +namespace asio { +namespace ssl { +namespace apple { + +namespace { +template <typename T> +struct CFReleaser { + void operator()(T ptr) { + if (ptr) { + ::CFRelease(ptr); + } + } +}; +} // namespace + +/** + * CoreFoundation types are internally refcounted using CFRetain/CFRelease. + * Values received from a method using the word "Copy" typically follow "The Copy Rule" + * which requires that the caller explicitly invoke CFRelease on the obtained value. + * Values received from a method using the word "Get" typically follow "The Get Rule" + * which requires that the caller DOES NOT attempt to release any references, + * though it may invoke CFRetain to hold on to the object for longer. + * + * Use of the CFUniquePtr type assumes that a value was wither obtained from a "Copy" + * method, or that it has been explicitly retained. + */ +template <typename T> +using CFUniquePtr = std::unique_ptr<typename std::remove_pointer<T>::type, CFReleaser<T>>; + +/** + * Equivalent of OpenSSL's SSL_CTX type. + * Allows loading SecIdentity and SecCertificate chains + * separate from an SSLContext instance. + * + * Unlike OpenSSL, Secure Transport sets protocol range on + * each connection instance separately, so just stash them aside + * in the same place for now. + */ +struct Context { + Context() = default; + explicit Context(::SSLProtocol p) : protoMin(p), protoMax(p) {} + Context& operator=(const Context& src) { + protoMin = src.protoMin; + protoMax = src.protoMax; + if (src.certs) { + ::CFRetain(src.certs.get()); + } + certs.reset(src.certs.get()); + return *this; + } + + ::SSLProtocol protoMin = kTLSProtocol1; + ::SSLProtocol protoMax = kTLSProtocol12; + CFUniquePtr<::CFArrayRef> certs; +}; + +} // namespace apple +} // namespace ssl +} // namespace asio + +#endif diff --git a/src/mongo/util/net/ssl/context.hpp b/src/mongo/util/net/ssl/context.hpp index 278530f5916..2a23b8454c8 100644 --- a/src/mongo/util/net/ssl/context.hpp +++ b/src/mongo/util/net/ssl/context.hpp @@ -34,6 +34,10 @@ #include "mongo/util/net/ssl/context_openssl.hpp" +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + +#include "mongo/util/net/ssl/context_apple.hpp" + #else #error "Unknown SSL Provider" #endif diff --git a/src/mongo/util/net/ssl/context_apple.hpp b/src/mongo/util/net/ssl/context_apple.hpp new file mode 100644 index 00000000000..3fd7f7eabde --- /dev/null +++ b/src/mongo/util/net/ssl/context_apple.hpp @@ -0,0 +1,82 @@ +/** + * Copyright 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/noncopyable.hpp" +#include "mongo/util/net/ssl/apple.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: + using native_handle_type = apple::Context*; + + ASIO_DECL explicit context(method m) { + _context.protoMin = _mapProto(m); + _context.protoMax = _context.protoMax; + } + + ASIO_DECL context(context&& other) = default; + ASIO_DECL context& operator=(context&& other) = default; + + ASIO_DECL native_handle_type native_handle() { + return &_context; + } + +private: + static ::SSLProtocol _mapProto(method m) { + switch (m) { + case context::tlsv1: + case context::tlsv1_client: + case context::tlsv1_server: + return ::kTLSProtocol1; + case context::tlsv11: + case context::tlsv11_client: + case context::tlsv11_server: + return ::kTLSProtocol11; + case context::tlsv12: + case context::tlsv12_client: + case context::tlsv12_server: + default: + return ::kTLSProtocol12; + } + } + + apple::Context _context; +}; + +} // namespace ssl +} // namespace asio + +#include "asio/detail/pop_options.hpp" diff --git a/src/mongo/util/net/ssl/detail/engine.hpp b/src/mongo/util/net/ssl/detail/engine.hpp index 80fc21c5daf..9beb6724b7e 100644 --- a/src/mongo/util/net/ssl/detail/engine.hpp +++ b/src/mongo/util/net/ssl/detail/engine.hpp @@ -34,6 +34,10 @@ #include "mongo/util/net/ssl/detail/engine_openssl.hpp" +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + +#include "mongo/util/net/ssl/detail/engine_apple.hpp" + #else #error "Unknown SSL Provider" #endif diff --git a/src/mongo/util/net/ssl/detail/engine_apple.hpp b/src/mongo/util/net/ssl/detail/engine_apple.hpp new file mode 100644 index 00000000000..69b027ceaa2 --- /dev/null +++ b/src/mongo/util/net/ssl/detail/engine_apple.hpp @@ -0,0 +1,103 @@ +/** + * Copyright 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 <deque> + +#include "asio/buffer.hpp" +#include "asio/detail/config.hpp" +#include "mongo/util/net/ssl/apple.hpp" +#include "mongo/util/net/ssl/context_apple.hpp" +#include "mongo/util/net/ssl/stream_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +class engine { +public: + using native_handle_type = ::SSLContextRef; + enum want { + want_input_and_retry = -2, + want_output_and_retry = -1, + want_nothing = 0, + want_output = 1 + }; + + ASIO_DECL explicit engine(context::native_handle_type context); + + ASIO_DECL native_handle_type native_handle() { + return _ssl.get(); + } + + ASIO_DECL want handshake(stream_base::handshake_type type, asio::error_code& ec); + + ASIO_DECL want shutdown(asio::error_code& ec); + + ASIO_DECL want write(const asio::const_buffer& data, + asio::error_code& ec, + std::size_t& bytes_transferred); + + ASIO_DECL want read(const asio::mutable_buffer& data, + asio::error_code& ec, + std::size_t& bytes_transferred); + + ASIO_DECL asio::mutable_buffer get_output(const asio::mutable_buffer& data); + + ASIO_DECL asio::const_buffer put_input(const asio::const_buffer& data); + + ASIO_DECL const asio::error_code& map_error_code(asio::error_code& ec) const; + +private: + engine(const engine&) = delete; + engine& operator=(const engine&) = delete; + bool _initSSL(stream_base::handshake_type type, asio::error_code& ec); + static ::OSStatus read_func(::SSLConnectionRef ctx, void* data, size_t* data_len); + static ::OSStatus write_func(::SSLConnectionRef ctx, const void* data, size_t* data_len); + want wouldBlock() const; + + apple::CFUniquePtr<native_handle_type> _ssl; + apple::CFUniquePtr<::CFArrayRef> _certs; + apple::CFUniquePtr<::CFArrayRef> _ca; + ::SSLProtocol _protoMin, _protoMax; + std::deque<char> _inbuf; + std::deque<char> _outbuf; +}; + +} // 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_apple.ipp" +#endif // defined(ASIO_HEADER_ONLY) diff --git a/src/mongo/util/net/ssl/detail/impl/engine_apple.ipp b/src/mongo/util/net/ssl/detail/impl/engine_apple.ipp new file mode 100644 index 00000000000..25abd1a70bb --- /dev/null +++ b/src/mongo/util/net/ssl/detail/impl/engine_apple.ipp @@ -0,0 +1,347 @@ +/** + * 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 + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kNetwork + +#include "asio/detail/config.hpp" + +#include "asio/detail/push_options.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "mongo/util/log.h" +#include "mongo/util/mongoutils/str.h" +#include "mongo/util/net/ssl/apple.hpp" +#include "mongo/util/net/ssl/detail/engine.hpp" +#include "mongo/util/net/ssl/error.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +namespace { + +std::ostringstream& operator<<(std::ostringstream& ss, ::OSStatus status) { + apple::CFUniquePtr<::CFStringRef> errstr(::SecCopyErrorMessageString(status, nullptr)); + if (!errstr) { + ss << "Unknown Error: " << static_cast<int>(status); + return ss; + } + const auto len = ::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(errstr.get()), + ::kCFStringEncodingUTF8); + std::string ret; + ret.resize(len + 1); + if (!::CFStringGetCString(errstr.get(), &ret[0], len, ::kCFStringEncodingUTF8)) { + ss << "Unknown Error: " << static_cast<int>(status); + return ss; + } + + ret.resize(strlen(ret.c_str())); + ss << ret; + return ss; +} + +const class osstatus_category : public error_category { +public: + const char* name() const noexcept final { + return "Secure.Transport"; + } + + std::string message(int value) const noexcept final { + const auto status = static_cast<::OSStatus>(value); + return mongo::str::stream() << "Secure.Transport: " << status; + } +} OSStatus_category; + +asio::error_code errorCode(::OSStatus status) { + return asio::error_code(static_cast<int>(status), OSStatus_category); +} + +/** + * Verify that an SSL session is ready for I/O (state: Connected). + * In all other states, asio should be speaking to the socket directly. + */ +bool verifyConnected(::SSLContextRef ssl, asio::error_code* ec) { + auto state = ::kSSLAborted; + auto status = ::SSLGetSessionState(ssl, &state); + if (status != ::errSecSuccess) { + // Unable to determine session state. + *ec = errorCode(status); + return false; + } + switch (state) { + case ::kSSLIdle: + *ec = asio::error::not_connected; + return false; + case ::kSSLHandshake: + *ec = asio::error::in_progress; + return false; + case ::kSSLConnected: + return true; + case ::kSSLClosed: + *ec = asio::error::shut_down; + return false; + case ::kSSLAborted: + *ec = asio::error::connection_aborted; + return false; + default: + // Undefined state, call it an internal error. + *ec = errorCode(::errSSLInternal); + return false; + } +} + +} // namespace + +engine::engine(context::native_handle_type context) { + if (context) { + if (context->certs) { + ::CFRetain(context->certs.get()); + _certs.reset(context->certs.get()); + } + _protoMin = context->protoMin; + _protoMax = context->protoMax; + } else { + apple::Context def; + _protoMin = def.protoMin; + _protoMax = def.protoMax; + } +} + +bool engine::_initSSL(stream_base::handshake_type type, asio::error_code& ec) { + if (_ssl) { + return true; + } + + const auto side = (type == stream_base::client) ? ::kSSLClientSide : ::kSSLServerSide; + _ssl.reset(::SSLCreateContext(nullptr, side, ::kSSLStreamType)); + if (!_ssl) { + mongo::error() << "Failed allocating SSLContext"; + ec = errorCode(::errSSLInternal); + return false; + } + + auto status = ::SSLSetConnection(_ssl.get(), static_cast<void*>(this)); + + // TODO: ::SSLSetPeerDomainName() + + if (_certs && (status == ::errSecSuccess)) { + status = ::SSLSetCertificate(_ssl.get(), _certs.get()); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetPeerID(_ssl.get(), _ssl.get(), sizeof(native_handle_type)); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetIOFuncs(_ssl.get(), read_func, write_func); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetProtocolVersionMin(_ssl.get(), _protoMin); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetProtocolVersionMax(_ssl.get(), _protoMax); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetClientSideAuthenticate(_ssl.get(), ::kTryAuthenticate); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetSessionOption(_ssl.get(), ::kSSLSessionOptionBreakOnServerAuth, true); + } + + if (status == ::errSecSuccess) { + status = ::SSLSetSessionOption(_ssl.get(), ::kSSLSessionOptionBreakOnClientAuth, true); + } + + if (status != ::errSecSuccess) { + _ssl.reset(nullptr); + ec = errorCode(status); + return false; + } + + return true; +} + +engine::want engine::handshake(stream_base::handshake_type type, asio::error_code& ec) { + if (!_initSSL(type, ec)) { + // Error happened, ec has been set. + return want::want_nothing; + } + + // We use BreakOnClientAuth and BreakOnServerAuth above to + // convince the OS not to validate the certs for us. + // In practice, we'll be validating the peer in ssl_manager_apple.cpp later. + // As a side effect, we have to call SSLHandshake up to three times. + // Breaking once for client auth, then for server auth, and finally on completion. + ::OSStatus status; + do { + status = ::SSLHandshake(_ssl.get()); + } while ((status == ::errSSLServerAuthCompleted) || (status == ::errSSLClientAuthCompleted)); + + if (status == ::errSSLWouldBlock) { + return wouldBlock(); + } + + if (status != ::errSecSuccess) { + _ssl.reset(nullptr); + ec = errorCode(status); + return want::want_nothing; + } + + return _outbuf.size() ? want::want_output : want::want_nothing; +} + +engine::want engine::shutdown(asio::error_code& ec) { + if (_ssl) { + const auto status = ::SSLClose(_ssl.get()); + if (status == ::errSSLWouldBlock) { + return wouldBlock(); + } + if (status == ::errSecSuccess) { + _ssl.reset(nullptr); + } else { + ec = errorCode(status); + } + } else { + mongo::error() << "SSL connection already shut down"; + ec = errorCode(::errSSLInternal); + } + return want::want_nothing; +} + +const asio::error_code& engine::map_error_code(asio::error_code& ec) const { + if (ec != asio::error::eof) { + return ec; + } + + if (_inbuf.size() || _outbuf.size()) { + ec = asio::ssl::error::stream_truncated; + return ec; + } + + invariant(_ssl); + auto state = ::kSSLAborted; + const auto status = ::SSLGetSessionState(_ssl.get(), &state); + if (status != ::errSecSuccess) { + ec = errorCode(status); + return ec; + } + + if (state == ::kSSLConnected) { + ec = asio::ssl::error::stream_truncated; + return ec; + } + + return ec; +} + +engine::want engine::write(const asio::const_buffer& data, + asio::error_code& ec, + std::size_t& bytes_transferred) { + if (!verifyConnected(_ssl.get(), &ec)) { + return want::want_nothing; + } + const auto status = ::SSLWrite(_ssl.get(), data.data(), data.size(), &bytes_transferred); + if (status == ::errSSLWouldBlock) { + return (bytes_transferred < data.size()) ? want::want_output_and_retry : want::want_nothing; + } + if (status != ::errSecSuccess) { + ec = errorCode(status); + } + return _outbuf.size() ? want::want_output : want::want_nothing; +} + +asio::mutable_buffer engine::get_output(const asio::mutable_buffer& data) { + const auto len = std::min<size_t>(data.size(), _outbuf.size()); + if (len > 0) { + auto* p = const_cast<char*>(static_cast<const char*>(data.data())); + std::copy(_outbuf.begin(), _outbuf.begin() + len, p); + _outbuf.erase(_outbuf.begin(), _outbuf.begin() + len); + } + + return asio::mutable_buffer(data.data(), len); +} + +::OSStatus engine::write_func(::SSLConnectionRef ctx, const void* data, size_t* data_len) { + auto* this_ = const_cast<engine*>(static_cast<const engine*>(ctx)); + const auto* p = static_cast<const char*>(data); + this_->_outbuf.insert(this_->_outbuf.end(), p, p + *data_len); + return ::errSecSuccess; +} + +engine::want engine::read(const asio::mutable_buffer& data, + asio::error_code& ec, + std::size_t& bytes_transferred) { + if (!verifyConnected(_ssl.get(), &ec)) { + return want::want_nothing; + } + const auto status = ::SSLRead(_ssl.get(), data.data(), data.size(), &bytes_transferred); + if ((status != ::errSSLWouldBlock) && (status != ::errSecSuccess)) { + ec = errorCode(status); + } + return bytes_transferred ? want::want_nothing : wouldBlock(); +} + +asio::const_buffer engine::put_input(const asio::const_buffer& data) { + const auto* p = static_cast<const char*>(data.data()); + _inbuf.insert(_inbuf.end(), p, p + data.size()); + return asio::buffer(data + data.size()); +} + +::OSStatus engine::read_func(::SSLConnectionRef ctx, void* data, size_t* data_len) { + ::OSStatus ret = ::errSecSuccess; + auto* this_ = const_cast<engine*>(static_cast<const engine*>(ctx)); + if (*data_len > this_->_inbuf.size()) { + // If we're able to 100% satisfy the read request Secure Transport made, + // then we should ultimately signal that the read is incomplete. + ret = ::errSSLWouldBlock; + } + *data_len = std::min<size_t>(*data_len, this_->_inbuf.size()); + if (*data_len > 0) { + std::copy( + this_->_inbuf.begin(), this_->_inbuf.begin() + *data_len, static_cast<char*>(data)); + this_->_inbuf.erase(this_->_inbuf.begin(), this_->_inbuf.begin() + *data_len); + } + return ret; +} + +engine::want engine::wouldBlock() const { + return _outbuf.empty() ? want::want_input_and_retry : want::want_output_and_retry; +} + +#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 21841fec2b9..1740a5bda29 100644 --- a/src/mongo/util/net/ssl/detail/stream_core.hpp +++ b/src/mongo/util/net/ssl/detail/stream_core.hpp @@ -22,7 +22,9 @@ #else // defined(ASIO_HAS_BOOST_DATE_TIME) #include "asio/steady_timer.hpp" #endif // defined(ASIO_HAS_BOOST_DATE_TIME) + #include "asio/buffer.hpp" +#include "mongo/util/net/ssl/apple.hpp" #include "mongo/util/net/ssl/detail/engine.hpp" #include "asio/detail/push_options.hpp" @@ -40,6 +42,8 @@ struct stream_core { 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) +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + stream_core(apple::Context* context, asio::io_context& io_context) #else #error "Unknown SSL Provider" #endif diff --git a/src/mongo/util/net/ssl/impl/error.ipp b/src/mongo/util/net/ssl/impl/error.ipp index 60b8f0da177..e2c6bea061e 100644 --- a/src/mongo/util/net/ssl/impl/error.ipp +++ b/src/mongo/util/net/ssl/impl/error.ipp @@ -15,8 +15,12 @@ #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include <string> + +#include "asio/detail/assert.hpp" #include "asio/detail/config.hpp" #include "mongo/util/errno_util.h" +#include "mongo/util/net/ssl/apple.hpp" #include "mongo/util/net/ssl/error.hpp" #include "asio/detail/push_options.hpp" @@ -40,6 +44,12 @@ public: const char* s = ::ERR_reason_error_string(value); return s ? s : "asio.ssl error"; } +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + std::string message(int value) const { + // engine_apple produces osstatus_errorcategory messages. + ASIO_ASSERT(false); + return "asio.ssl error"; + } #else #error "Unknown SSL Provider" #endif diff --git a/src/mongo/util/net/ssl/impl/src.hpp b/src/mongo/util/net/ssl/impl/src.hpp index f5bb866efee..5e300c2147e 100644 --- a/src/mongo/util/net/ssl/impl/src.hpp +++ b/src/mongo/util/net/ssl/impl/src.hpp @@ -33,6 +33,11 @@ #include "mongo/util/net/ssl/impl/context_openssl.ipp" #include "mongo/util/net/ssl/impl/error.ipp" +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + +#include "mongo/util/net/ssl/detail/impl/engine_apple.ipp" +#include "mongo/util/net/ssl/impl/error.ipp" + #else #error "Unknown SSL Provider" #endif diff --git a/src/mongo/util/net/ssl/stream.hpp b/src/mongo/util/net/ssl/stream.hpp index d44bdc4bd08..df933c0fe55 100644 --- a/src/mongo/util/net/ssl/stream.hpp +++ b/src/mongo/util/net/ssl/stream.hpp @@ -22,6 +22,7 @@ #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/type_traits.hpp" +#include "mongo/util/net/ssl/apple.hpp" #include "mongo/util/net/ssl/context.hpp" #include "mongo/util/net/ssl/detail/buffered_handshake_op.hpp" #include "mongo/util/net/ssl/detail/handshake_op.hpp" @@ -67,6 +68,8 @@ public: typedef PCtxtHandle native_handle_type; #elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_OPENSSL typedef SSL* native_handle_type; +#elif MONGO_CONFIG_SSL_PROVIDER == SSL_PROVIDER_APPLE + typedef ::SSLContextRef native_handle_type; #else #error "Unknown SSL Provider" #endif |