16
16
using System ;
17
17
using System . Security . Cryptography ;
18
18
using System . Text ;
19
+ using MongoDB . Bson ;
19
20
using MongoDB . Bson . IO ;
20
21
#if NET452
21
22
using MongoDB . Driver . Core . Authentication . Vendored ;
@@ -35,7 +36,7 @@ public abstract class ScramShaAuthenticator : SaslAuthenticator
35
36
/// </summary>
36
37
/// <param name="data">The data to hash. Also called "str" in RFC5802.</param>
37
38
protected internal delegate byte [ ] H ( byte [ ] data ) ;
38
-
39
+
39
40
/// <summary>
40
41
/// A Hi function used to compute the SaltedPassword as defined in RFC5802, except with "str" parameter replaced
41
42
/// with a UsernamePassword credential so that the password can be optionally digested/prepped in a secure fashion
@@ -46,15 +47,15 @@ public abstract class ScramShaAuthenticator : SaslAuthenticator
46
47
/// <param name="salt">The salt.</param>
47
48
/// <param name="iterations">The iteration count.</param>
48
49
protected internal delegate byte [ ] Hi ( UsernamePasswordCredential credentials , byte [ ] salt , int iterations ) ;
49
-
50
+
50
51
/// <summary>
51
52
/// An HMAC function as defined in RFC5802, plus the encoding of the data.
52
53
/// </summary>
53
54
/// <param name="encoding">The encoding of the data.</param>
54
55
/// <param name="data">The data. Also called "str" in RFC5802.</param>
55
56
/// <param name="key">The key.</param>
56
57
protected internal delegate byte [ ] Hmac ( UTF8Encoding encoding , byte [ ] data , string key ) ;
57
-
58
+
58
59
// fields
59
60
private readonly string _databaseName ;
60
61
@@ -67,7 +68,7 @@ public abstract class ScramShaAuthenticator : SaslAuthenticator
67
68
/// <param name="h">The H function to use.</param>
68
69
/// <param name="hi">The Hi function to use.</param>
69
70
/// <param name="hmac">The Hmac function to use.</param>
70
- protected ScramShaAuthenticator ( UsernamePasswordCredential credential ,
71
+ protected ScramShaAuthenticator ( UsernamePasswordCredential credential ,
71
72
HashAlgorithmName hashAlgorithmName ,
72
73
H h ,
73
74
Hi hi ,
@@ -85,7 +86,7 @@ protected ScramShaAuthenticator(UsernamePasswordCredential credential,
85
86
/// <param name="hmac">The Hmac function to use.</param>
86
87
/// <param name="cache">The cache to use.</param>
87
88
internal ScramShaAuthenticator (
88
- UsernamePasswordCredential credential ,
89
+ UsernamePasswordCredential credential ,
89
90
HashAlgorithmName hashAlgorithName ,
90
91
IRandomStringGenerator randomStringGenerator ,
91
92
H h ,
@@ -101,6 +102,24 @@ internal ScramShaAuthenticator(
101
102
/// <inheritdoc/>
102
103
public override string DatabaseName => _databaseName ;
103
104
105
+ /// <inheritdoc/>
106
+ public override BsonDocument CustomizeInitialIsMasterCommand ( BsonDocument isMasterCommand )
107
+ {
108
+ isMasterCommand = base . CustomizeInitialIsMasterCommand ( isMasterCommand ) ;
109
+ _speculativeFirstStep = _mechanism . Initialize ( connection : null , conversation : null , description : null ) ;
110
+ var firstCommand = CreateStartCommand ( _speculativeFirstStep ) ;
111
+ firstCommand . Add ( "db" , DatabaseName ) ;
112
+ isMasterCommand . Add ( "speculativeAuthenticate" , firstCommand ) ;
113
+ return isMasterCommand ;
114
+ }
115
+
116
+ private protected override BsonDocument CreateStartCommand ( ISaslStep currentStep )
117
+ {
118
+ var startCommand = base . CreateStartCommand ( currentStep ) ;
119
+ startCommand . Add ( "options" , new BsonDocument ( "skipEmptyExchange" , true ) ) ;
120
+ return startCommand ;
121
+ }
122
+
104
123
// nested classes
105
124
private class ScramShaMechanism : ISaslMechanism
106
125
{
@@ -113,8 +132,8 @@ private class ScramShaMechanism : ISaslMechanism
113
132
private ScramCache _cache ;
114
133
115
134
public ScramShaMechanism (
116
- UsernamePasswordCredential credential ,
117
- HashAlgorithmName hashAlgorithmName ,
135
+ UsernamePasswordCredential credential ,
136
+ HashAlgorithmName hashAlgorithmName ,
118
137
IRandomStringGenerator randomStringGenerator ,
119
138
H h ,
120
139
Hi hi ,
@@ -138,9 +157,6 @@ public ScramShaMechanism(
138
157
139
158
public ISaslStep Initialize ( IConnection connection , SaslConversation conversation , ConnectionDescription description )
140
159
{
141
- Ensure . IsNotNull ( connection , nameof ( connection ) ) ;
142
- Ensure . IsNotNull ( description , nameof ( description ) ) ;
143
-
144
160
const string gs2Header = "n,," ;
145
161
var username = "n=" + PrepUsername ( _credential . Username ) ;
146
162
var r = GenerateRandomString ( ) ;
@@ -165,13 +181,13 @@ private string PrepUsername(string username)
165
181
return username . Replace ( "=" , "=3D" ) . Replace ( "," , "=2C" ) ;
166
182
}
167
183
}
168
-
184
+
169
185
private class ClientFirst : ISaslStep
170
186
{
171
187
private readonly byte [ ] _bytesToSendToServer ;
172
188
private readonly string _clientFirstMessageBare ;
173
189
private readonly UsernamePasswordCredential _credential ;
174
-
190
+
175
191
private readonly string _rPrefix ;
176
192
private readonly H _h ;
177
193
private readonly Hi _hi ;
@@ -180,9 +196,9 @@ private class ClientFirst : ISaslStep
180
196
private ScramCache _cache ;
181
197
182
198
public ClientFirst (
183
- byte [ ] bytesToSendToServer ,
184
- string clientFirstMessageBare ,
185
- UsernamePasswordCredential credential ,
199
+ byte [ ] bytesToSendToServer ,
200
+ string clientFirstMessageBare ,
201
+ UsernamePasswordCredential credential ,
186
202
string rPrefix ,
187
203
H h ,
188
204
Hi hi ,
@@ -266,7 +282,7 @@ private byte[] XOR(byte[] a, byte[] b)
266
282
}
267
283
268
284
private class ClientLast : ISaslStep
269
- {
285
+ {
270
286
private readonly byte [ ] _bytesToSendToServer ;
271
287
private readonly byte [ ] _serverSignature64 ;
272
288
@@ -293,7 +309,7 @@ public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedF
293
309
294
310
return new CompletedStep ( ) ;
295
311
}
296
-
312
+
297
313
private bool ConstantTimeEquals ( byte [ ] a , byte [ ] b )
298
314
{
299
315
var diff = a . Length ^ b . Length ;
@@ -306,4 +322,4 @@ private bool ConstantTimeEquals(byte[] a, byte[] b)
306
322
}
307
323
}
308
324
}
309
- }
325
+ }
0 commit comments