@@ -50,6 +50,18 @@ namespace mongo {
5050 return " " ;
5151 }
5252#else
53+
54+ // Old copies of OpenSSL will not have constants to disable protocols they don't support.
55+ // Define them to values we can OR together safely to generically disable these protocols across
56+ // all versions of OpenSSL.
57+ #ifndef SSL_OP_NO_TLSv1_1
58+ #define SSL_OP_NO_TLSv1_1 0
59+ #endif
60+ #ifndef SSL_OP_NO_TLSv1_2
61+ #define SSL_OP_NO_TLSv1_2 0
62+ #endif
63+
64+
5365 const std::string getSSLVersion (const std::string &prefix, const std::string &suffix) {
5466 return prefix + SSLeay_version (SSLEAY_VERSION) + suffix;
5567 }
@@ -139,8 +151,10 @@ namespace mongo {
139151 const std::string& pempwd,
140152 const std::string& clusterfile,
141153 const std::string& clusterpwd,
154+ const std::vector<client::Options::TLSProtocol>& disabledProtocols,
142155 const std::string& cafile = " " ,
143156 const std::string& crlfile = " " ,
157+ const std::string& cipherConfig = " " ,
144158 bool weakCertificateValidation = false ,
145159 bool allowInvalidCertificates = false ,
146160 bool allowInvalidHostnames = false ,
@@ -151,6 +165,8 @@ namespace mongo {
151165 clusterpwd (clusterpwd),
152166 cafile (cafile),
153167 crlfile (crlfile),
168+ cipherConfig (cipherConfig),
169+ disabledProtocols (disabledProtocols),
154170 weakCertificateValidation (weakCertificateValidation),
155171 allowInvalidCertificates (allowInvalidCertificates),
156172 allowInvalidHostnames (allowInvalidHostnames),
@@ -162,6 +178,8 @@ namespace mongo {
162178 std::string clusterpwd;
163179 std::string cafile;
164180 std::string crlfile;
181+ std::string cipherConfig;
182+ std::vector<client::Options::TLSProtocol> disabledProtocols;
165183 bool weakCertificateValidation;
166184 bool allowInvalidCertificates;
167185 bool allowInvalidHostnames;
@@ -301,8 +319,10 @@ namespace mongo {
301319 options.SSLPEMKeyPassword (),
302320 std::string (), // server only parameter
303321 std::string (), // server only parameter
322+ options.SSLDisabledTLSProtocols (),
304323 options.SSLCAFile (),
305324 options.SSLCRLFile (),
325+ options.SSLCipherConfig (),
306326 false , // server only parameter
307327 options.SSLAllowInvalidCertificates (),
308328 options.SSLAllowInvalidHostnames (),
@@ -544,13 +564,37 @@ namespace mongo {
544564 // SSL_OP_ALL - Activate all bug workaround options, to support buggy client SSL's.
545565 // SSL_OP_NO_SSLv2 - Disable SSL v2 support
546566 // SSL_OP_NO_SSLv3 - Disable SSL v3 support
547- SSL_CTX_set_options (*context, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
567+ long supportedProtocols = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
568+
569+ // Set the supported TLS protocols. Allow --disabledProtocols to disable selected ciphers.
570+ if (!params.disabledProtocols .empty ()) {
571+ for (std::vector<client::Options::TLSProtocol>::const_iterator it =
572+ params.disabledProtocols .begin (); it != params.disabledProtocols .end (); ++it) {
573+ if (*it == client::Options::kTLS1_0 ) {
574+ supportedProtocols |= SSL_OP_NO_TLSv1;
575+ } else if (*it == client::Options::kTLS1_1 ) {
576+ supportedProtocols |= SSL_OP_NO_TLSv1_1;
577+ } else if (*it == client::Options::kTLS1_2 ) {
578+ supportedProtocols |= SSL_OP_NO_TLSv1_2;
579+ }
580+ }
581+ }
582+ SSL_CTX_set_options (*context, supportedProtocols);
548583
549584 // HIGH - Enable strong ciphers
550585 // !EXPORT - Disable export ciphers (40/56 bit)
551586 // !aNULL - Disable anonymous auth ciphers
552587 // @STRENGTH - Sort ciphers based on strength
553- SSL_CTX_set_cipher_list (*context, " HIGH:!EXPORT:!aNULL@STRENGTH" );
588+ std::string cipherConfig = " HIGH:!EXPORT:!aNULL@STRENGTH" ;
589+
590+ // Allow the cipher configuration string to be overriden by --sslCipherConfig
591+ if (!params.cipherConfig .empty ()) {
592+ cipherConfig = params.cipherConfig ;
593+ }
594+
595+ massert (28615 , mongoutils::str::stream () << " can't set supported cipher suites: " <<
596+ getSSLErrorMessage (ERR_get_error ()),
597+ SSL_CTX_set_cipher_list (*context, cipherConfig.c_str ()));
554598
555599 // If renegotiation is needed, don't return from recv() or send() until it's successful.
556600 // Note: this is for blocking sockets only.
@@ -766,39 +810,31 @@ namespace mongo {
766810 }
767811
768812 SSLConnection* SSLManager::connect (Socket* socket) {
769- SSLConnection* sslConn = new SSLConnection (_clientContext, socket, NULL , 0 );
770- ScopeGuard sslGuard = MakeGuard (::SSL_free, sslConn->ssl );
771- ScopeGuard bioGuard = MakeGuard (::BIO_free, sslConn->networkBIO );
813+ std::auto_ptr<SSLConnection> sslConn (new SSLConnection (_clientContext, socket, NULL , 0 ));
772814
773815 int ret;
774816 do {
775817 ret = ::SSL_connect (sslConn->ssl );
776- } while (!_doneWithSSLOp (sslConn, ret));
818+ } while (!_doneWithSSLOp (sslConn. get () , ret));
777819
778820 if (ret != 1 )
779- _handleSSLError (SSL_get_error (sslConn, ret), ret);
821+ _handleSSLError (SSL_get_error (sslConn. get () , ret), ret);
780822
781- sslGuard.Dismiss ();
782- bioGuard.Dismiss ();
783- return sslConn;
823+ return sslConn.release ();
784824 }
785825
786826 SSLConnection* SSLManager::accept (Socket* socket, const char * initialBytes, int len) {
787- SSLConnection* sslConn = new SSLConnection (_serverContext, socket, initialBytes, len);
788- ScopeGuard sslGuard = MakeGuard (::SSL_free, sslConn->ssl );
789- ScopeGuard bioGuard = MakeGuard (::BIO_free, sslConn->networkBIO );
827+ std::auto_ptr<SSLConnection> sslConn (new SSLConnection (_serverContext, socket, initialBytes, len));
790828
791829 int ret;
792830 do {
793831 ret = ::SSL_accept (sslConn->ssl );
794- } while (!_doneWithSSLOp (sslConn, ret));
832+ } while (!_doneWithSSLOp (sslConn. get () , ret));
795833
796834 if (ret != 1 )
797- _handleSSLError (SSL_get_error (sslConn, ret), ret);
835+ _handleSSLError (SSL_get_error (sslConn. get () , ret), ret);
798836
799- sslGuard.Dismiss ();
800- bioGuard.Dismiss ();
801- return sslConn;
837+ return sslConn.release ();
802838 }
803839
804840 // TODO SERVER-11601 Use NFC Unicode canonicalization
0 commit comments