/* Copyright 2009 10gen 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 . * * 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 #include #include #include "mongo/config.h" #ifdef MONGO_CONFIG_SSL #include "mongo/base/disallow_copying.h" #include "mongo/base/string_data.h" #include "mongo/bson/bsonobj.h" #include "mongo/db/service_context.h" #include "mongo/platform/atomic_word.h" #include "mongo/util/decorable.h" #include "mongo/util/net/sock.h" #include "mongo/util/net/ssl/apple.hpp" #include "mongo/util/net/ssl_types.h" #include "mongo/util/time_support.h" // SChannel implementation #if MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL #include #include #endif #endif // #ifdef MONGO_CONFIG_SSL namespace mongo { /* * @return the SSL version std::string prefixed with prefix and suffixed with suffix */ const std::string getSSLVersion(const std::string& prefix, const std::string& suffix); } #ifdef MONGO_CONFIG_SSL namespace mongo { struct SSLParams; #if MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL typedef SSL_CTX* SSLContextType; typedef SSL* SSLConnectionType; #elif MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_WINDOWS typedef SCHANNEL_CRED* SSLContextType; typedef PCtxtHandle SSLConnectionType; #elif MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_APPLE typedef asio::ssl::apple::Context* SSLContextType; typedef SSLContextRef SSLConnectionType; #else #error "Unknown SSL Provider" #endif /** * Maintain per connection SSL state for the Sock class. Used by SSLManagerInterface to perform SSL * operations. */ class SSLConnectionInterface { public: virtual ~SSLConnectionInterface(); virtual std::string getSNIServerName() const = 0; }; struct SSLConfiguration { bool isClusterMember(StringData subjectName) const; bool isClusterMember(const SSLX509Name& subjectName) const; BSONObj getServerStatusBSON() const; SSLX509Name serverSubjectName; SSLX509Name clientSubjectName; Date_t serverCertificateExpirationDate; bool hasCA = false; }; /** * Stores information about a globally unique OID. */ class ASN1OID { public: ASN1OID(std::string identifier, std::string shortDescription, std::string longDescription) : identifier(std::move(identifier)), shortDescription(std::move(shortDescription)), longDescription(std::move(longDescription)) {} std::string identifier; // An OID std::string shortDescription; // A brief description of the entity associated with the OID std::string longDescription; // A long form description of the entity associated with the OID }; const ASN1OID mongodbRolesOID("1.3.6.1.4.1.34601.2.1.1", "MongoRoles", "Sequence of MongoDB Database Roles"); /** * Counts of negogtiated version used by TLS connections. */ struct TLSVersionCounts { AtomicInt64 tls10; AtomicInt64 tls11; AtomicInt64 tls12; static TLSVersionCounts& get(ServiceContext* serviceContext); }; class SSLManagerInterface : public Decorable { public: static std::unique_ptr create(const SSLParams& params, bool isServer); virtual ~SSLManagerInterface(); /** * Initiates a TLS connection. * Throws SocketException on failure. * @return a pointer to an SSLConnectionInterface. Resources are freed in * SSLConnectionInterface's destructor */ virtual SSLConnectionInterface* connect(Socket* socket) = 0; /** * Waits for the other side to initiate a TLS connection. * Throws SocketException on failure. * @return a pointer to an SSLConnectionInterface. Resources are freed in * SSLConnectionInterface's destructor */ virtual SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len) = 0; /** * Fetches a peer certificate and validates it if it exists * Throws NetworkException on failure * @return a std::string containing the certificate's subject name. * * This version of parseAndValidatePeerCertificate is deprecated because it throws a * NetworkException upon failure. New code should prefer the version that returns * a StatusWith instead. */ virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated( const SSLConnectionInterface* conn, const std::string& remoteHost) = 0; /** * Gets the SSLConfiguration containing all information about the current SSL setup * @return the SSLConfiguration */ virtual const SSLConfiguration& getSSLConfiguration() const = 0; /** * Fetches the error text for an error code, in a thread-safe manner. */ static std::string getSSLErrorMessage(int code); /** * SSL wrappers */ virtual int SSL_read(SSLConnectionInterface* conn, void* buf, int num) = 0; virtual int SSL_write(SSLConnectionInterface* conn, const void* buf, int num) = 0; virtual int SSL_shutdown(SSLConnectionInterface* conn) = 0; enum class ConnectionDirection { kIncoming, kOutgoing }; /** * Initializes an OpenSSL context according to the provided settings. Only settings which are * 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(SSLContextType context, const SSLParams& params, ConnectionDirection direction) = 0; /** * Fetches a peer certificate and validates it if it exists. If validation fails, but weak * validation is enabled, boost::none will be returned. If validation fails, and invalid * certificates are not allowed, a non-OK status will be returned. If validation is successful, * an engaged optional containing the certificate's subject name, and any roles acquired by * X509 authorization will be returned. */ virtual StatusWith> parseAndValidatePeerCertificate( SSLConnectionType ssl, const std::string& remoteHost) = 0; }; // Access SSL functions through this instance. SSLManagerInterface* getSSLManager(); extern bool isSSLServer; /** * Returns true if the `nameToMatch` is a valid match against the `certHostName` requirement from an * x.509 certificate. Matches a remote host name to an x.509 host name, including wildcards. */ bool hostNameMatchForX509Certificates(std::string nameToMatch, std::string certHostName); /** * Parse a binary blob of DER encoded ASN.1 into a set of RoleNames. */ StatusWith> parsePeerRoles(ConstDataRange cdrExtension); /** * Strip the trailing '.' in FQDN. */ std::string removeFQDNRoot(std::string name); /** * Escape a string per RGC 2253 * * See "2.4 Converting an AttributeValue from ASN.1 to a String" in RFC 2243 */ std::string escapeRfc2253(StringData str); } // namespace mongo #endif // #ifdef MONGO_CONFIG_SSL