summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Cotter <matt.cotter@mongodb.com>2016-06-15 14:22:48 -0400
committerAndrew Morrow <acm@mongodb.com>2017-04-09 16:23:50 -0400
commit3aa8cf14fd7c6c821c81aac03cb4948663743d22 (patch)
tree0515250e5ca2d919c8b551f73893440a4c911305 /src
parent15d286b971df65e58184643a031bbe579ac040a5 (diff)
downloadmongo-3aa8cf14fd7c6c821c81aac03cb4948663743d22.tar.gz
SERVER-24595 enforce ismaster response has ok:1
(cherry picked from commit e9cd7667471eff437463e7de842af95747847be4)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/client/dbclient.cpp6
-rw-r--r--src/mongo/executor/SConscript1
-rw-r--r--src/mongo/executor/network_interface_asio_auth.cpp7
-rw-r--r--src/mongo/executor/network_interface_asio_test.cpp40
4 files changed, 54 insertions, 0 deletions
diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp
index 73a5e5d52a1..ab4ba058d00 100644
--- a/src/mongo/client/dbclient.cpp
+++ b/src/mongo/client/dbclient.cpp
@@ -924,6 +924,12 @@ Status DBClientConnection::connect(const HostAndPort& serverAddress) {
return swIsMasterReply.getStatus();
}
+ // Ensure that the isMaster response is "ok:1".
+ auto isMasterStatus = getStatusFromCommandResult(swIsMasterReply.getValue().data);
+ if (!isMasterStatus.isOK()) {
+ return isMasterStatus;
+ }
+
auto swProtocolSet = rpc::parseProtocolSetFromIsMasterReply(swIsMasterReply.getValue().data);
if (!swProtocolSet.isOK()) {
return swProtocolSet.getStatus();
diff --git a/src/mongo/executor/SConscript b/src/mongo/executor/SConscript
index c8ff0e69fd0..ec25fc15952 100644
--- a/src/mongo/executor/SConscript
+++ b/src/mongo/executor/SConscript
@@ -149,6 +149,7 @@ env.Library(
'$BUILD_DIR/mongo/base/system_error',
'$BUILD_DIR/mongo/db/auth/authcommon',
'$BUILD_DIR/mongo/db/commands/test_commands_enabled',
+ '$BUILD_DIR/mongo/rpc/command_status',
'$BUILD_DIR/mongo/rpc/rpc',
'$BUILD_DIR/third_party/shim_asio',
'async_stream',
diff --git a/src/mongo/executor/network_interface_asio_auth.cpp b/src/mongo/executor/network_interface_asio_auth.cpp
index b9a341d13d6..22a35ce8f8f 100644
--- a/src/mongo/executor/network_interface_asio_auth.cpp
+++ b/src/mongo/executor/network_interface_asio_auth.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/commands.h"
#include "mongo/db/server_options.h"
#include "mongo/rpc/factory.h"
+#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/rpc/legacy_request_builder.h"
#include "mongo/rpc/reply_interface.h"
#include "mongo/stdx/memory.h"
@@ -90,6 +91,12 @@ void NetworkInterfaceASIO::_runIsMaster(AsyncOp* op) {
auto commandReply = std::move(swCommandReply.getValue());
+ // Ensure that the isMaster response is "ok:1".
+ auto commandStatus = getStatusFromCommandResult(commandReply.data);
+ if (!commandStatus.isOK()) {
+ return _completeOperation(op, commandStatus);
+ }
+
auto protocolSet = rpc::parseProtocolSetFromIsMasterReply(commandReply.data);
if (!protocolSet.isOK())
return _completeOperation(op, protocolSet.getStatus());
diff --git a/src/mongo/executor/network_interface_asio_test.cpp b/src/mongo/executor/network_interface_asio_test.cpp
index bbe75be5f49..144a0ad91d4 100644
--- a/src/mongo/executor/network_interface_asio_test.cpp
+++ b/src/mongo/executor/network_interface_asio_test.cpp
@@ -533,6 +533,46 @@ public:
}
};
+TEST_F(NetworkInterfaceASIOConnectionHookTest, InvalidIsMaster) {
+ auto validationFailedStatus =
+ Status(ErrorCodes::InterruptedDueToReplStateChange, "operation was interrupted");
+
+ start(makeTestHook(
+ [&](const HostAndPort& remoteHost, const RemoteCommandResponse& isMasterReply) {
+ return Status(ErrorCodes::UnknownError, "unused");
+ },
+ [&](const HostAndPort& remoteHost)
+ -> StatusWith<boost::optional<RemoteCommandRequest>> { return {boost::none}; },
+ [&](const HostAndPort& remoteHost, RemoteCommandResponse&& response) {
+ return Status::OK();
+ }));
+
+ auto deferred = startCommand(makeCallbackHandle(),
+ {testHost,
+ "blah",
+ BSON("foo"
+ << "bar")});
+
+ auto stream = streamFactory().blockUntilStreamExists(testHost);
+
+ ConnectEvent{stream}.skip();
+
+ // simulate isMaster reply.
+ stream->simulateServer(rpc::Protocol::kOpQuery,
+ [](RemoteCommandRequest request) -> RemoteCommandResponse {
+ RemoteCommandResponse response;
+ response.data = BSON("ok" << 0.0 << "errmsg"
+ << "operation was interrupted"
+ << "code" << 11602);
+ return response;
+ });
+
+ // we should stop here.
+ auto& res = deferred.get();
+
+ ASSERT(res == validationFailedStatus);
+}
+
TEST_F(NetworkInterfaceASIOConnectionHookTest, ValidateHostInvalid) {
bool validateCalled = false;
bool hostCorrect = false;