Skip to content

Commit 4125fb2

Browse files
authored
CSHARP-3538: CSOT: Auth (#1720)
CSHARP-3538: CSOT: Auth CSHARP-3545: CSOT: MongoDB Handshake CSHARP-3548: CSOT: Server Discovery and Monitoring
1 parent ae496bc commit 4125fb2

33 files changed

+455
-612
lines changed

src/MongoDB.Driver/Authentication/AuthenticationHelper.cs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using System.Runtime.InteropServices;
1818
using System.Security;
1919
using System.Security.Cryptography;
20-
using System.Threading;
2120
using System.Threading.Tasks;
2221
using MongoDB.Bson;
2322
using MongoDB.Bson.IO;
@@ -28,8 +27,9 @@ namespace MongoDB.Driver.Authentication
2827
{
2928
internal static class AuthenticationHelper
3029
{
31-
public static void Authenticate(IConnection connection, ConnectionDescription description, IAuthenticator authenticator, CancellationToken cancellationToken)
30+
public static void Authenticate(OperationContext operationContext, IConnection connection, ConnectionDescription description, IAuthenticator authenticator)
3231
{
32+
Ensure.IsNotNull(operationContext, nameof(operationContext));
3333
Ensure.IsNotNull(connection, nameof(connection));
3434
Ensure.IsNotNull(description, nameof(description));
3535

@@ -41,12 +41,13 @@ public static void Authenticate(IConnection connection, ConnectionDescription de
4141
// authentication is currently broken on arbiters
4242
if (!description.HelloResult.IsArbiter)
4343
{
44-
authenticator.Authenticate(connection, description, cancellationToken);
44+
authenticator.Authenticate(operationContext, connection, description);
4545
}
4646
}
4747

48-
public static async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, IAuthenticator authenticator, CancellationToken cancellationToken)
48+
public static async Task AuthenticateAsync(OperationContext operationContext, IConnection connection, ConnectionDescription description, IAuthenticator authenticator)
4949
{
50+
Ensure.IsNotNull(operationContext, nameof(operationContext));
5051
Ensure.IsNotNull(connection, nameof(connection));
5152
Ensure.IsNotNull(description, nameof(description));
5253

@@ -58,7 +59,7 @@ public static async Task AuthenticateAsync(IConnection connection, ConnectionDes
5859
// authentication is currently broken on arbiters
5960
if (!description.HelloResult.IsArbiter)
6061
{
61-
await authenticator.AuthenticateAsync(connection, description, cancellationToken).ConfigureAwait(false);
62+
await authenticator.AuthenticateAsync(operationContext, connection, description).ConfigureAwait(false);
6263
}
6364
}
6465

@@ -68,30 +69,28 @@ public static string MongoPasswordDigest(string username, SecureString password)
6869
{
6970
return MongoPasswordDigest(username, new byte[0]);
7071
}
71-
else
72+
73+
var passwordIntPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
74+
try
7275
{
73-
var passwordIntPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
76+
var passwordChars = new char[password.Length];
77+
var passwordCharsHandle = GCHandle.Alloc(passwordChars, GCHandleType.Pinned);
7478
try
7579
{
76-
var passwordChars = new char[password.Length];
77-
var passwordCharsHandle = GCHandle.Alloc(passwordChars, GCHandleType.Pinned);
78-
try
79-
{
80-
Marshal.Copy(passwordIntPtr, passwordChars, 0, password.Length);
80+
Marshal.Copy(passwordIntPtr, passwordChars, 0, password.Length);
8181

82-
return MongoPasswordDigest(username, passwordChars);
83-
}
84-
finally
85-
{
86-
Array.Clear(passwordChars, 0, passwordChars.Length);
87-
passwordCharsHandle.Free();
88-
}
82+
return MongoPasswordDigest(username, passwordChars);
8983
}
9084
finally
9185
{
92-
Marshal.ZeroFreeGlobalAllocUnicode(passwordIntPtr);
86+
Array.Clear(passwordChars, 0, passwordChars.Length);
87+
passwordCharsHandle.Free();
9388
}
9489
}
90+
finally
91+
{
92+
Marshal.ZeroFreeGlobalAllocUnicode(passwordIntPtr);
93+
}
9594
}
9695

9796
private static string MongoPasswordDigest(string username, char[] passwordChars)

src/MongoDB.Driver/Authentication/DefaultAuthenticator.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using System.Collections.Generic;
1818
using System.Linq;
1919
using System.Net;
20-
using System.Threading;
2120
using System.Threading.Tasks;
2221
using MongoDB.Bson;
2322
using MongoDB.Driver.Authentication.ScramSha;
@@ -54,7 +53,7 @@ internal DefaultAuthenticator(
5453

5554
public string Name => "DEFAULT";
5655

57-
public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
56+
public void Authenticate(OperationContext operationContext, IConnection connection, ConnectionDescription description)
5857
{
5958
Ensure.IsNotNull(connection, nameof(connection));
6059
Ensure.IsNotNull(description, nameof(description));
@@ -65,20 +64,20 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
6564
if (!description.HelloResult.HasSaslSupportedMechs
6665
&& Feature.ScramSha256Authentication.IsSupported(description.MaxWireVersion))
6766
{
68-
var command = CustomizeInitialHelloCommand(HelloHelper.CreateCommand(_serverApi, loadBalanced: connection.Settings.LoadBalanced), cancellationToken);
67+
var command = CustomizeInitialHelloCommand(operationContext, HelloHelper.CreateCommand(_serverApi, loadBalanced: connection.Settings.LoadBalanced));
6968
var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi);
70-
var helloResult = HelloHelper.GetResult(connection, helloProtocol, cancellationToken);
69+
var helloResult = HelloHelper.GetResult(operationContext, connection, helloProtocol);
7170
var mergedHelloResult = new HelloResult(description.HelloResult.Wrapped.Merge(helloResult.Wrapped));
7271
description = new ConnectionDescription(
7372
description.ConnectionId,
7473
mergedHelloResult);
7574
}
7675

7776
var authenticator = GetOrCreateAuthenticator(connection, description);
78-
authenticator.Authenticate(connection, description, cancellationToken);
77+
authenticator.Authenticate(operationContext, connection, description);
7978
}
8079

81-
public async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
80+
public async Task AuthenticateAsync(OperationContext operationContext, IConnection connection, ConnectionDescription description)
8281
{
8382
Ensure.IsNotNull(connection, nameof(connection));
8483
Ensure.IsNotNull(description, nameof(description));
@@ -89,20 +88,20 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
8988
if (!description.HelloResult.HasSaslSupportedMechs
9089
&& Feature.ScramSha256Authentication.IsSupported(description.MaxWireVersion))
9190
{
92-
var command = CustomizeInitialHelloCommand(HelloHelper.CreateCommand(_serverApi, loadBalanced: connection.Settings.LoadBalanced), cancellationToken);
91+
var command = CustomizeInitialHelloCommand(operationContext, HelloHelper.CreateCommand(_serverApi, loadBalanced: connection.Settings.LoadBalanced));
9392
var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi);
94-
var helloResult = await HelloHelper.GetResultAsync(connection, helloProtocol, cancellationToken).ConfigureAwait(false);
93+
var helloResult = await HelloHelper.GetResultAsync(operationContext, connection, helloProtocol).ConfigureAwait(false);
9594
var mergedHelloResult = new HelloResult(description.HelloResult.Wrapped.Merge(helloResult.Wrapped));
9695
description = new ConnectionDescription(
9796
description.ConnectionId,
9897
mergedHelloResult);
9998
}
10099

101100
var authenticator = GetOrCreateAuthenticator(connection, description);
102-
await authenticator.AuthenticateAsync(connection, description, cancellationToken).ConfigureAwait(false);
101+
await authenticator.AuthenticateAsync(operationContext, connection, description).ConfigureAwait(false);
103102
}
104103

105-
public BsonDocument CustomizeInitialHelloCommand(BsonDocument helloCommand, CancellationToken cancellationToken)
104+
public BsonDocument CustomizeInitialHelloCommand(OperationContext operationContext, BsonDocument helloCommand)
106105
{
107106
var saslSupportedMechs = CreateSaslSupportedMechsRequest(_identity);
108107
helloCommand = helloCommand.Merge(saslSupportedMechs);
@@ -116,7 +115,7 @@ public BsonDocument CustomizeInitialHelloCommand(BsonDocument helloCommand, Canc
116115
out var authenticator))
117116
{
118117
_speculativeAuthenticator = authenticator;
119-
return _speculativeAuthenticator.CustomizeInitialHelloCommand(helloCommand, cancellationToken);
118+
return _speculativeAuthenticator.CustomizeInitialHelloCommand(operationContext, helloCommand);
120119
}
121120

122121
return helloCommand;

src/MongoDB.Driver/Authentication/IAuthenticator.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
* limitations under the License.
1414
*/
1515

16-
using System.Threading;
1716
using System.Threading.Tasks;
1817
using MongoDB.Bson;
1918
using MongoDB.Driver.Core.Connections;
@@ -24,10 +23,10 @@ internal interface IAuthenticator
2423
{
2524
string Name { get; }
2625

27-
void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken);
26+
void Authenticate(OperationContext operationContext, IConnection connection, ConnectionDescription description);
2827

29-
Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken);
28+
Task AuthenticateAsync(OperationContext operationContext, IConnection connection, ConnectionDescription description);
3029

31-
BsonDocument CustomizeInitialHelloCommand(BsonDocument helloCommand, CancellationToken cancellationToken);
30+
BsonDocument CustomizeInitialHelloCommand(OperationContext operationContext, BsonDocument helloCommand);
3231
}
3332
}

src/MongoDB.Driver/Authentication/MongoDBX509Authenticator.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
*/
1515

1616
using System;
17-
using System.Threading;
1817
using System.Threading.Tasks;
1918
using MongoDB.Bson;
2019
using MongoDB.Bson.Serialization.Serializers;
@@ -45,7 +44,7 @@ public string Name
4544
get { return MechanismName; }
4645
}
4746

48-
public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
47+
public void Authenticate(OperationContext operationContext, IConnection connection, ConnectionDescription description)
4948
{
5049
Ensure.IsNotNull(connection, nameof(connection));
5150
Ensure.IsNotNull(description, nameof(description));
@@ -58,16 +57,15 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
5857
try
5958
{
6059
var protocol = CreateAuthenticateProtocol();
61-
// TODO: CSOT: implement operationContext support for Auth.
62-
protocol.Execute(new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken), connection);
60+
protocol.Execute(operationContext, connection);
6361
}
6462
catch (MongoCommandException ex)
6563
{
6664
throw CreateException(connection, ex);
6765
}
6866
}
6967

70-
public async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
68+
public async Task AuthenticateAsync(OperationContext operationContext, IConnection connection, ConnectionDescription description)
7169
{
7270
Ensure.IsNotNull(connection, nameof(connection));
7371
Ensure.IsNotNull(description, nameof(description));
@@ -80,16 +78,15 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
8078
try
8179
{
8280
var protocol = CreateAuthenticateProtocol();
83-
// TODO: CSOT: implement operationContext support for Auth.
84-
await protocol.ExecuteAsync(new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken), connection).ConfigureAwait(false);
81+
await protocol.ExecuteAsync(operationContext, connection).ConfigureAwait(false);
8582
}
8683
catch (MongoCommandException ex)
8784
{
8885
throw CreateException(connection, ex);
8986
}
9087
}
9188

92-
public BsonDocument CustomizeInitialHelloCommand(BsonDocument helloCommand, CancellationToken cancellationToken)
89+
public BsonDocument CustomizeInitialHelloCommand(OperationContext operationContext, BsonDocument helloCommand)
9390
{
9491
helloCommand.Add("speculativeAuthenticate", CreateAuthenticateCommand());
9592
return helloCommand;

src/MongoDB.Driver/Authentication/SaslAuthenticator.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using System;
1717
using System.Collections.Generic;
1818
using System.Net;
19-
using System.Threading;
2019
using System.Threading.Tasks;
2120
using MongoDB.Bson;
2221
using MongoDB.Bson.Serialization.Serializers;
@@ -72,7 +71,7 @@ internal SaslAuthenticator(ISaslMechanism mechanism, ServerApi serverApi)
7271

7372
public string Name => Mechanism.Name;
7473

75-
public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
74+
public void Authenticate(OperationContext operationContext, IConnection connection, ConnectionDescription description)
7675
{
7776
Ensure.IsNotNull(connection, nameof(connection));
7877
Ensure.IsNotNull(description, nameof(description));
@@ -91,7 +90,10 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
9190

9291
while (currentStep != null)
9392
{
94-
var executionResult = currentStep.Execute(conversation, result?["payload"]?.AsByteArray, cancellationToken);
93+
operationContext.ThrowIfTimedOutOrCanceled();
94+
#pragma warning disable CS0618 // Type or member is obsolete
95+
var executionResult = currentStep.Execute(conversation, result?["payload"]?.AsByteArray, operationContext.CombinedCancellationToken);
96+
#pragma warning restore CS0618 // Type or member is obsolete
9597
if (executionResult.BytesToSendToServer == null)
9698
{
9799
currentStep = executionResult.NextStep;
@@ -109,8 +111,7 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
109111
try
110112
{
111113
var protocol = CreateCommandProtocol(command);
112-
// TODO: CSOT: implement operationContext support for Auth.
113-
result = protocol.Execute(new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken), connection);
114+
result = protocol.Execute(operationContext, connection);
114115
conversationId ??= result?.GetValue("conversationId").AsInt32;
115116
}
116117
catch (MongoException ex)
@@ -136,7 +137,7 @@ public void Authenticate(IConnection connection, ConnectionDescription descripti
136137
}
137138
}
138139

139-
public async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken)
140+
public async Task AuthenticateAsync(OperationContext operationContext, IConnection connection, ConnectionDescription description)
140141
{
141142
Ensure.IsNotNull(connection, nameof(connection));
142143
Ensure.IsNotNull(description, nameof(description));
@@ -155,7 +156,10 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
155156

156157
while (currentStep != null)
157158
{
158-
var executionResult = await currentStep.ExecuteAsync(conversation, result?["payload"]?.AsByteArray, cancellationToken).ConfigureAwait(false);
159+
operationContext.ThrowIfTimedOutOrCanceled();
160+
#pragma warning disable CS0618 // Type or member is obsolete
161+
var executionResult = await currentStep.ExecuteAsync(conversation, result?["payload"]?.AsByteArray, operationContext.CombinedCancellationToken).ConfigureAwait(false);
162+
#pragma warning restore CS0618 // Type or member is obsolete
159163
if (executionResult.BytesToSendToServer == null)
160164
{
161165
currentStep = executionResult.NextStep;
@@ -173,8 +177,7 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
173177
try
174178
{
175179
var protocol = CreateCommandProtocol(command);
176-
// TODO: CSOT: implement operationContext support for Auth.
177-
result = await protocol.ExecuteAsync(new OperationContext(Timeout.InfiniteTimeSpan, cancellationToken), connection).ConfigureAwait(false);
180+
result = await protocol.ExecuteAsync(operationContext, connection).ConfigureAwait(false);
178181
conversationId ??= result?.GetValue("conversationId").AsInt32;
179182
}
180183
catch (MongoException ex)
@@ -200,12 +203,14 @@ public async Task AuthenticateAsync(IConnection connection, ConnectionDescriptio
200203
}
201204
}
202205

203-
public BsonDocument CustomizeInitialHelloCommand(BsonDocument helloCommand, CancellationToken cancellationToken)
206+
public BsonDocument CustomizeInitialHelloCommand(OperationContext operationContext, BsonDocument helloCommand)
204207
{
205208
var speculativeStep = Mechanism.CreateSpeculativeAuthenticationStep();
206209
if (speculativeStep != null)
207210
{
208-
(var bytesToSend, _speculativeContinueStep) = speculativeStep.Execute(null, null, cancellationToken);
211+
#pragma warning disable CS0618 // Type or member is obsolete
212+
(var bytesToSend, _speculativeContinueStep) = speculativeStep.Execute(null, null, operationContext.CombinedCancellationToken);
213+
#pragma warning restore CS0618 // Type or member is obsolete
209214
var firstCommand = CreateStartCommand(bytesToSend);
210215
firstCommand.Add("db", Mechanism.DatabaseName);
211216
helloCommand.Add("speculativeAuthenticate", firstCommand);

0 commit comments

Comments
 (0)