public void Authenticate_should_throw_when_server_provides_invalid_serverSignature( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done: false, ok: 1}")); var saslContinueResponse = MessageHelper.BuildCommandResponse( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTBh'), done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(saslStartResponse); connection.EnqueueCommandResponseMessage(saslContinueResponse); connection.Description = __descriptionCommandWireProtocol; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } act.ShouldThrow <MongoAuthenticationException>(); }
public void Authenticate_should_throw_when_server_provides_invalid_r_value( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var poisonedSaslStart = PoisonSaslMessage(message: __clientRequest1, poison: "bluePill"); var poisonedSaslStartReply = CreateSaslStartReply(poisonedSaslStart, _serverNonce, _serverSalt, _iterationCount); var poisonedSaslStartReplyMessage = MessageHelper.BuildReply(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(poisonedSaslStartReply)}\")," + @" done: false, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(poisonedSaslStartReplyMessage); var act = async ? () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult() : (Action)(() => subject.Authenticate(connection, __description, CancellationToken.None)); var exception = Record.Exception(act); exception.Should().BeOfType <MongoAuthenticationException>(); }
public void AuthenticateAsync_should_not_throw_when_authentication_succeeds() { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildSuccessReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,\"cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw\"), done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildSuccessReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,\"dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9\"), done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); var currentRequestId = RequestMessage.CurrentGlobalRequestId; Action act = () => subject.AuthenticateAsync(connection, Timeout.InfiniteTimeSpan, CancellationToken.None).Wait(); act.ShouldNotThrow(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); sentMessages[0].Should().Be("{opcode: \"query\", requestId: " + (currentRequestId + 1) + ", database: \"source\", collection: \"$cmd\", batchSize: -1, slaveOk: true, query: {saslStart: 1, mechanism: \"SCRAM-SHA-1\", payload: new BinData(0, \"biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM\")}}"); sentMessages[1].Should().Be("{opcode: \"query\", requestId: " + (currentRequestId + 2) + ", database: \"source\", collection: \"$cmd\", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, payload: new BinData(0, \"Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9\")}}"); }
public void Authenticate_should_use_cache( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson( "{conversationId: 1, payload: BinData(0,\"cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw\"), done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson( "{conversationId: 1, payload: BinData(0,\"dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9\"), done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); if (async) { subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter() .GetResult(); } else { subject.Authenticate(connection, __description, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should() .BeTrue(); subject._cache().Should().NotBe(null); subject._cache()._cacheKey().Should().NotBe(null); subject._cache()._cachedEntry().Should().NotBe(null); }
public void Authenticate_should_throw_when_server_provides_invalid_r_value( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,\"cj1meWtvLWQybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw\"), done: false, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } act.ShouldThrow <MongoAuthenticationException>(); }
public void Authenticate_should_send_serverApi_with_command_wire_protocol_if_serverApi_is_provided( [Values(false, true)] bool useServerApi, [Values(false, true)] bool async) { var serverApi = useServerApi ? new ServerApi(ServerApiVersion.V1, true, true) : null; var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi); var connection = new MockConnection(__serverId); var saslStartReply = RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}'), done : false, ok : 1 }}"); var saslContinueReply = RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}'), done : true, ok : 1}}"); if (useServerApi) { connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslStartReply)); connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslContinueReply)); } else { connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslStartReply)); connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslContinueReply)); } connection.Description = __descriptionQueryWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionQueryWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { subject.Authenticate(connection, __descriptionQueryWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; if (useServerApi) { sentMessages[0].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId0}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"biwsbj11c2VyLHI9ck9wck5HZndFYmVSV2diTkVrcU8=\"), options : {{ skipEmptyExchange : true }}, \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); sentMessages[1].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId1}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"Yz1iaXdzLHI9ck9wck5HZndFYmVSV2diTkVrcU8laHZZRHBXVWEyUmFUQ0FmdXhGSWxqKWhObEYkazAscD1kSHpiWmFwV0lrNGpVaE4rVXRlOXl0YWc5empmTUhnc3FtbWl6N0FuZFZRPQ==\"), \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); } else { sentMessages[0].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId0}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\"), options : {{ \"skipEmptyExchange\" : true }} }} }}"); sentMessages[1].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId1}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\") }} }}"); } }
public void Authenticate_should_send_serverApi_with_command_wire_protocol_if_serverApi_is_provided( [Values(false, true)] bool useServerApi, [Values(false, true)] bool async) { var serverApi = useServerApi ? new ServerApi(ServerApiVersion.V1, true, true) : null; var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi); var connection = new MockConnection(__serverId); var saslStartReply = RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done : false, ok : 1 }"); var saslContinueReply = RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9'), done : true, ok : 1}"); if (useServerApi) { connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslStartReply)); connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslContinueReply)); } else { connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslStartReply)); connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslContinueReply)); } connection.Description = __descriptionQueryWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionQueryWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { subject.Authenticate(connection, __descriptionQueryWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; if (useServerApi) { sentMessages[0].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId0}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslStart : 1, mechanism : \"SCRAM-SHA-1\", payload : new BinData(0, \"biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM\"), options : {{ skipEmptyExchange : true }}, \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); sentMessages[1].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId1}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9\"), \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); } else { sentMessages[0].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId0}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslStart : 1, mechanism : \"SCRAM-SHA-1\", payload : new BinData(0, \"biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM\"), options : {{ \"skipEmptyExchange\" : true }} }} }}"); sentMessages[1].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId1}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9\") }} }}"); } }
public void Authenticate_should_work_regardless_of_culture( [Values("da-DK", "en-US")] string name, [Values(false, true)] bool async) { SetCultureAndResetAfterTest(name, () => { var randomStringGenerator = new ConstantRandomStringGenerator("a"); // ScramSha1Authenticator will have exactly the same code paths var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var mockConnection = new MockConnection(); var payload1 = $"r=aa,s={_serverSalt},i=1"; var serverResponse1 = $"{{ ok : 1, payload : BinData(0,\"{ToUtf8Base64(payload1)}\"), done : true, conversationId : 1 }}"; var serverResponseRawDocument1 = RawBsonDocumentHelper.FromJson(serverResponse1); var serverResponseMessage1 = MessageHelper.BuildCommandResponse(serverResponseRawDocument1); var payload2 = $"v=v1wZS02d7kZVSzuKoB7TuI+jIpSsKvnQUkU9Oqj2t+w="; var serverResponse2 = $"{{ ok : 1, payload : BinData(0,\"{ToUtf8Base64(payload2)}\"), done : true }}"; var serverResponseRawDocument2 = RawBsonDocumentHelper.FromJson(serverResponse2); var serverResponseMessage2 = MessageHelper.BuildCommandResponse(serverResponseRawDocument2); mockConnection.EnqueueCommandResponseMessage(serverResponseMessage1); mockConnection.EnqueueCommandResponseMessage(serverResponseMessage2); mockConnection.Description = __descriptionCommandWireProtocol; Authenticate(subject, mockConnection, async); }); void SetCultureAndResetAfterTest(string cultureName, Action test) { var originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName); try { test(); } finally { Thread.CurrentThread.CurrentCulture = originalCulture; } } }
public void AuthenticateAsync_should_throw_when_server_provides_invalid_r_value() { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildSuccessReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,\"cj1meWtvLWQybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw\"), done: false, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); var currentRequestId = RequestMessage.CurrentGlobalRequestId; Action act = () => subject.AuthenticateAsync(connection, Timeout.InfiniteTimeSpan, CancellationToken.None).Wait(); act.ShouldThrow <MongoAuthenticationException>(); }
public void Authenticate_should_use_cache( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse2)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(saslStartResponse); connection.EnqueueCommandResponseMessage(saslContinueResponse); connection.Description = __descriptionCommandWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None) .GetAwaiter() .GetResult(); } else { subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)) .Should() .BeTrue(); subject._cache().Should().NotBe(null); subject._cache()._cacheKey().Should().NotBe(null); subject._cache()._cachedEntry().Should().NotBe(null); }
public void Authenticate_should_send_serverApi_with_command_wire_protocol( [Values(false, true)] bool useServerApi, [Values(false, true)] bool async) { var serverApi = useServerApi ? new ServerApi(ServerApiVersion.V1, true, true) : null; var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi); var connection = new MockConnection(__serverId); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}'), done : false, ok : 1 }}")); connection.EnqueueCommandResponseMessage(saslStartResponse); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}'), done : true, ok : 1}}")); connection.EnqueueCommandResponseMessage(saslContinueResponse); connection.Description = __descriptionCommandWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; var expectedServerApiString = useServerApi ? ", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true" : ""; sentMessages[0].Should().Be($"{{ opcode : \"opmsg\", requestId : {actualRequestId0}, responseTo : 0, sections : [ {{ payloadType : 0, document : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\"), options : {{ \"skipEmptyExchange\" : true }}, $db : \"source\"{expectedServerApiString} }} }} ] }}"); sentMessages[1].Should().Be($"{{ opcode : \"opmsg\", requestId : {actualRequestId1}, responseTo : 0, sections : [ {{ payloadType : 0, document : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\"), $db : \"source\"{expectedServerApiString} }} }} ] }}"); }
public void Authenticate_should_throw_when_server_provides_invalid_serverSignature( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = CreateSaslStartReply(__clientRequest1, _serverNonce, _serverSalt, _iterationCount); var poisonedSaslContinueReply = PoisonSaslMessage(message: __serverResponse2, poison: "redApple"); var saslStartResponseMessage = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(saslStartReply)}\")," + @" done: false, ok: 1}")); var poisonedSaslContinueResponseMessage = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(poisonedSaslContinueReply)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(saslStartResponseMessage); connection.EnqueueCommandResponseMessage(poisonedSaslContinueResponseMessage); connection.Description = __descriptionCommandWireProtocol; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeOfType <MongoAuthenticationException>(); }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{conversationId: 1, payload: BinData(0,\"cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw\"), done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, payload: BinData(0,""dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9"")," + $" done: {new BsonBoolean(!useLongAuthentication)}, " + @" ok: 1}")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } act.ShouldNotThrow(); var expectedSentMessageCount = useLongAuthentication ? 3 : 2; SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } sentMessages[0].Should().Be( $"{{opcode: \"query\", " + $" requestId: {actualRequestIds[0]}, " + $" database: \"source\", collection: \"$cmd\", batchSize: -1, slaveOk: true, " + $" query: {{saslStart: 1, mechanism: \"SCRAM-SHA-1\", " + $" payload: new BinData(0, \"biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM\")" + @" options: { skipEmptyExchange: true }}}"); sentMessages[1].Should().Be("{opcode: \"query\", requestId: " + actualRequestIds[1] + ", database: \"source\", collection: \"$cmd\", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, payload: new BinData(0, \"Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9\")}}"); if (useLongAuthentication) { sentMessages[2].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[2]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"\")}}}}"); } }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done : false, ok : 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9')," + $" done : {new BsonBoolean(!useLongAuthentication)}, " + @" ok : 1}")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,''), done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var isMasterResult = (BsonDocument)__descriptionQueryWireProtocol.IsMasterResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { isMasterResult.Add("speculativeAuthenticate", saslStartReply.Documents[0].ToBsonDocument()); } /* set buildInfoResult to 3.4 to force authenticator to use Query Message Wire Protocol because MockConnection * does not support OP_MSG */ connection.Description = new ConnectionDescription( __descriptionQueryWireProtocol.ConnectionId, new IsMasterResult(isMasterResult), new BuildInfoResult(new BsonDocument("version", "3.4"))); BsonDocument isMasterCommand = null; if (useSpeculativeAuthenticate) { // Call CustomizeIsMasterCommand so that the authenticator thinks its started to speculatively // authenticate isMasterCommand = subject.CustomizeInitialIsMasterCommand(new BsonDocument { { "isMaster", 1 } }); } else { connection.EnqueueReplyMessage(saslStartReply); } connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {actualRequestIds[0]}, " + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslStart : 1, mechanism : 'SCRAM-SHA-1'," + $" payload : new BinData(0, 'biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM')" + @" options : { skipEmptyExchange: true }}}"); if (!useSpeculativeAuthenticate) { expectedMessages.Add(saslStartMessage); } var saslContinueMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[0] : actualRequestIds[1])}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, 'Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9')}}}}"); expectedMessages.Add(saslContinueMessage); if (useLongAuthentication) { var saslOptionalFinalMessage = BsonDocument.Parse( @"{opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[1] : actualRequestIds[2])}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, '')}}}}"); expectedMessages.Add(saslOptionalFinalMessage); } sentMessages.Should().Equal(expectedMessages); if (useSpeculativeAuthenticate) { isMasterCommand.Should().Contain("speculativeAuthenticate"); var speculativeAuthenticateDocument = isMasterCommand["speculativeAuthenticate"].AsBsonDocument; var expectedSpeculativeAuthenticateDocument = saslStartMessage["query"].AsBsonDocument.Add("db", __credential.Source); speculativeAuthenticateDocument.Should().Be(expectedSpeculativeAuthenticateDocument); } }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse( RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done : false, ok : 1}")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9')," + $" done : {new BsonBoolean(!useLongAuthentication)}, " + @" ok : 1}")); var saslLastStepResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,''), done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var helloResult = (BsonDocument)__descriptionCommandWireProtocol.HelloResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { helloResult.Add("speculativeAuthenticate", ((Type0CommandMessageSection <RawBsonDocument>)saslStartResponse.WrappedMessage.Sections[0]).Document); } connection.Description = new ConnectionDescription(__descriptionCommandWireProtocol.ConnectionId, new HelloResult(helloResult)); BsonDocument helloCommand = null; if (useSpeculativeAuthenticate) { // Call CustomizeInitialHelloCommand so that the authenticator thinks its started to speculatively // authenticate helloCommand = subject.CustomizeInitialHelloCommand(new BsonDocument { { OppressiveLanguageConstants.LegacyHelloCommandName, 1 } }); } else { connection.EnqueueCommandResponseMessage(saslStartResponse); } connection.EnqueueCommandResponseMessage(saslContinueResponse); if (useLongAuthentication) { connection.EnqueueCommandResponseMessage(saslLastStepResponse); } Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse(@$ " {{ opcode : 'opmsg', requestId : {actualRequestIds[0]},
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(_serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(_serverReponse2)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeNull(); SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; actualRequestId0.Should().BeInRange(expectedRequestId, expectedRequestId + 10); actualRequestId1.Should().BeInRange(actualRequestId0 + 1, actualRequestId0 + 11); sentMessages[0].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestId0}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslStart: 1, mechanism: ""SCRAM-SHA-256""," + $" payload: new BinData(0, \"{ToUtf8Base64(_clientRequest1)}\")}}}}"); sentMessages[1].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestId1}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(_clientRequest2)}\")}}}}"); }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse2)}\")," + $" done: {new BsonBoolean(!useLongAuthentication)}," + @" ok: 1}")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverOptionalFinalResponse)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeNull(); var expectedSentMessageCount = useLongAuthentication ? 3 : 2; SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } sentMessages[0].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[0]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslStart: 1, mechanism: ""SCRAM-SHA-256""," + $" payload: new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\")" + @" options: { skipEmptyExchange: true }}}"); sentMessages[1].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[1]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\")}}}}"); if (useLongAuthentication) { sentMessages[2].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[2]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(__clientOptionalFinalRequest)}\")}}}}"); } }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}')," + @" done : false, ok : 1 }")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}')," + $" done : {new BsonBoolean(!useLongAuthentication)}," + @" ok : 1 }")); var saslLastStepResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverOptionalFinalResponse)}')," + @" done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var helloResult = (BsonDocument)__descriptionCommandWireProtocol.HelloResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { helloResult.Add("speculativeAuthenticate", ((Type0CommandMessageSection <RawBsonDocument>)saslStartResponse.WrappedMessage.Sections[0]).Document); } connection.Description = new ConnectionDescription(__descriptionCommandWireProtocol.ConnectionId, new HelloResult(helloResult)); BsonDocument helloCommand = null; if (useSpeculativeAuthenticate) { // We must call CustomizeInitialHelloCommand so that the authenticator thinks its started to speculatively // authenticate helloCommand = subject.CustomizeInitialHelloCommand(new BsonDocument { { OppressiveLanguageConstants.LegacyHelloCommandName, 1 } }); } else { connection.EnqueueCommandResponseMessage(saslStartResponse); } connection.EnqueueCommandResponseMessage(saslContinueResponse); if (useLongAuthentication) { connection.EnqueueCommandResponseMessage(saslLastStepResponse); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse(@$ " {{ opcode : 'opmsg', requestId : {actualRequestIds[0]},
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}')," + @" done : false, ok : 1 }")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}')," + $" done : {new BsonBoolean(!useLongAuthentication)}," + @" ok : 1 }")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverOptionalFinalResponse)}')," + @" done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var isMasterResult = (BsonDocument)__descriptionQueryWireProtocol.IsMasterResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { isMasterResult.Add("speculativeAuthenticate", saslStartReply.Documents[0].ToBsonDocument()); } /* set buildInfoResult to 3.4 to force authenticator to use Query Message Wire Protocol because MockConnection * does not support OP_MSG */ connection.Description = new ConnectionDescription( __descriptionQueryWireProtocol.ConnectionId, new IsMasterResult(isMasterResult), new BuildInfoResult(new BsonDocument("version", "3.4"))); BsonDocument isMasterCommand = null; if (useSpeculativeAuthenticate) { // We must call CustomizeIsMasterCommand so that the authenticator thinks its started to speculatively // authenticate isMasterCommand = subject.CustomizeInitialIsMasterCommand(new BsonDocument { { "isMaster", 1 } }); } else { connection.EnqueueReplyMessage(saslStartReply); } connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {actualRequestIds[0]}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslStart : 1, mechanism : 'SCRAM-SHA-256'," + $" payload : new BinData(0, '{ToUtf8Base64(__clientRequest1)}')" + @" options : { skipEmptyExchange: true }}}"); if (!useSpeculativeAuthenticate) { expectedMessages.Add(saslStartMessage); } var saslContinueMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[0] : actualRequestIds[1])}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\")}}}}"); expectedMessages.Add(saslContinueMessage); if (useLongAuthentication) { var saslOptionalFinalMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[1] : actualRequestIds[2])}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, '{ToUtf8Base64(__clientOptionalFinalRequest)}')}}}}"); expectedMessages.Add(saslOptionalFinalMessage); } sentMessages.Should().Equal(expectedMessages); if (useSpeculativeAuthenticate) { isMasterCommand.Should().Contain("speculativeAuthenticate"); var speculativeAuthenticateDocument = isMasterCommand["speculativeAuthenticate"].AsBsonDocument; var expectedSpeculativeAuthenticateDocument = saslStartMessage["query"].AsBsonDocument.Add("db", __credential.Source); speculativeAuthenticateDocument.Should().Be(expectedSpeculativeAuthenticateDocument); } }