Skip to content

Commit ef3ed2f

Browse files
committed
CXX-599 Backport server r3.0.2..r3.0.3 changes
Server SHAs cherry-picked (with modifications) into this commit: 8e808ee caa254d 4975cdb ca9aed9 b2c20d1 2366756 867aeb4
1 parent 6b5291d commit ef3ed2f

File tree

5 files changed

+126
-20
lines changed

5 files changed

+126
-20
lines changed

SConstruct

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,19 @@ add_option('cache-dir',
283283
"Specify the directory to use for caching objects if --cache is in use",
284284
1, False, default="$BUILD_DIR/scons/cache")
285285

286+
variable_parse_mode_choices=['auto', 'posix', 'other']
287+
add_option('variable-parse-mode',
288+
"Select which parsing mode is used to interpret command line variables",
289+
1, False,
290+
type='choice', default=variable_parse_mode_choices[0],
291+
choices=variable_parse_mode_choices)
292+
286293
# Setup the command-line variables
287294
def variable_shlex_converter(val):
288-
return shlex.split(val)
295+
parse_mode = get_option('variable-parse-mode')
296+
if parse_mode == 'auto':
297+
parse_mode = 'other' if windows else 'posix'
298+
return shlex.split(val, posix=(parse_mode == 'posix'))
289299

290300
env_vars = Variables()
291301

@@ -325,6 +335,10 @@ env_vars.Add('LINKFLAGS',
325335
help='Sets flags for the linker',
326336
converter=variable_shlex_converter)
327337

338+
env_vars.Add('RPATH',
339+
help='Set the RPATH for dynamic libraries and executables',
340+
converter=variable_shlex_converter)
341+
328342
env_vars.Add('SHCCFLAGS',
329343
help='Sets flags for the C and C++ compiler when building shared libraries',
330344
converter=variable_shlex_converter)

src/mongo/client/options.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ namespace client {
9999
return _useFIPSMode;
100100
}
101101

102+
Options& Options::setSSLDisabledTLSProtocols(const std::vector<TLSProtocol>& protocols) {
103+
_sslDisabledTLSProtocols = protocols;
104+
return *this;
105+
}
106+
107+
const std::vector<Options::TLSProtocol>& Options::SSLDisabledTLSProtocols() const {
108+
return _sslDisabledTLSProtocols;
109+
}
110+
102111
Options& Options::setSSLCAFile(const std::string& fileName) {
103112
_sslCAFile = fileName;
104113
return *this;
@@ -153,6 +162,15 @@ namespace client {
153162
return _sslAllowInvalidHostnames;
154163
}
155164

165+
Options& Options::setSSLCipherConfig(const std::string& config) {
166+
_sslCipherConfig = config;
167+
return *this;
168+
}
169+
170+
const std::string& Options::SSLCipherConfig() const {
171+
return _sslCipherConfig;
172+
}
173+
156174
Options& Options::setLogAppenderFactory(const Options::LogAppenderFactory& factory) {
157175
_appenderFactory = factory;
158176
return *this;

src/mongo/client/options.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ namespace client {
7676
kSSLRequired
7777
};
7878

79+
/** The TLS protocols */
80+
enum TLSProtocol {
81+
kTLS1_0,
82+
kTLS1_1,
83+
kTLS1_2
84+
};
7985

8086
//
8187
// Startup and shutdown
@@ -147,6 +153,14 @@ namespace client {
147153
Options& setFIPSMode(bool value = true);
148154
const bool FIPSMode() const;
149155

156+
/** Allow disabling particular TLS protocols
157+
*
158+
* Default: OpenSSL default
159+
*/
160+
161+
Options& setSSLDisabledTLSProtocols(const std::vector<TLSProtocol>& protocols);
162+
const std::vector<TLSProtocol>& SSLDisabledTLSProtocols() const;
163+
150164
/** Configure the SSL CA file to use. Has no effect if 'useSSL' is false.
151165
*
152166
* Default: false
@@ -189,6 +203,13 @@ namespace client {
189203
Options& setSSLAllowInvalidHostnames(bool value = true);
190204
const bool SSLAllowInvalidHostnames() const;
191205

206+
/** Override the default OpenSSL cipher configuration
207+
*
208+
* Default: OpenSSL default
209+
*/
210+
Options& setSSLCipherConfig(const std::string& config);
211+
const std::string& SSLCipherConfig() const;
212+
192213
//
193214
// Logging
194215
//
@@ -224,12 +245,14 @@ namespace client {
224245
unsigned int _autoShutdownGracePeriodMillis;
225246
SSLModes _sslMode;
226247
bool _useFIPSMode;
248+
std::vector<TLSProtocol> _sslDisabledTLSProtocols;
227249
std::string _sslCAFile;
228250
std::string _sslPEMKeyFile;
229251
std::string _sslPEMKeyPassword;
230252
std::string _sslCRLFile;
231253
bool _sslAllowInvalidCertificates;
232254
bool _sslAllowInvalidHostnames;
255+
std::string _sslCipherConfig;
233256
int _defaultLocalThresholdMillis;
234257
LogAppenderFactory _appenderFactory;
235258
logger::LogSeverity _minLoggedSeverity;

src/mongo/crypto/crypto_openssl.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "mongo/platform/basic.h"
2424

25+
#include "mongo/util/scopeguard.h"
26+
2527
#include <openssl/sha.h>
2628
#include <openssl/evp.h>
2729
#include <openssl/hmac.h>
@@ -34,7 +36,20 @@ namespace crypto {
3436
bool sha1(const unsigned char* input,
3537
const size_t inputLen,
3638
unsigned char* output) {
37-
return SHA1(input, inputLen, output);
39+
40+
EVP_MD_CTX digestCtx;
41+
EVP_MD_CTX_init(&digestCtx);
42+
ON_BLOCK_EXIT(EVP_MD_CTX_cleanup, &digestCtx);
43+
44+
if (1 != EVP_DigestInit_ex(&digestCtx, EVP_sha1(), NULL)) {
45+
return false;
46+
}
47+
48+
if (1 != EVP_DigestUpdate(&digestCtx, input, inputLen)) {
49+
return false;
50+
}
51+
52+
return (1 == EVP_DigestFinal_ex(&digestCtx, output, NULL));
3853
}
3954

4055
/*

src/mongo/util/net/ssl_manager.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)