16
16
17
17
package com .mongodb .connection ;
18
18
19
+ import com .mongodb .AuthenticationMechanism ;
19
20
import com .mongodb .MongoCredential ;
20
21
import com .mongodb .ServerAddress ;
22
+ import com .mongodb .internal .authentication .SaslPrep ;
21
23
import org .bson .internal .Base64 ;
22
24
23
25
import javax .crypto .Mac ;
29
31
import java .security .MessageDigest ;
30
32
import java .security .NoSuchAlgorithmException ;
31
33
import java .security .SecureRandom ;
34
+ import java .util .Collections ;
32
35
import java .util .HashMap ;
36
+ import java .util .LinkedHashMap ;
37
+ import java .util .Map ;
33
38
import java .util .Random ;
34
39
40
+ import static com .mongodb .AuthenticationMechanism .SCRAM_SHA_1 ;
41
+ import static com .mongodb .AuthenticationMechanism .SCRAM_SHA_256 ;
35
42
import static com .mongodb .internal .authentication .NativeAuthenticationHelper .createAuthenticationHash ;
36
43
import static java .lang .String .format ;
37
44
38
45
class ScramShaAuthenticator extends SaslAuthenticator {
39
46
private final RandomStringGenerator randomStringGenerator ;
40
47
private final AuthenticationHashGenerator authenticationHashGenerator ;
48
+
41
49
private static final int MINIMUM_ITERATION_COUNT = 4096 ;
42
50
43
51
ScramShaAuthenticator (final MongoCredential credential ) {
44
- this (credential , new DefaultRandomStringGenerator (), AUTHENTICATION_HASH_GENERATOR );
52
+ this (credential , new DefaultRandomStringGenerator (), getAuthenicationHashGenerator ( credential . getAuthenticationMechanism ()) );
45
53
}
46
54
47
55
ScramShaAuthenticator (final MongoCredential credential , final RandomStringGenerator randomStringGenerator ) {
48
- this (credential , randomStringGenerator , AUTHENTICATION_HASH_GENERATOR );
56
+ this (credential , randomStringGenerator , getAuthenicationHashGenerator ( credential . getAuthenticationMechanism ()) );
49
57
}
50
58
51
59
ScramShaAuthenticator (final MongoCredential credential , final RandomStringGenerator randomStringGenerator ,
@@ -87,8 +95,13 @@ static class ScramShaSaslClient implements SaslClient {
87
95
this .credential = credential ;
88
96
this .randomStringGenerator = randomStringGenerator ;
89
97
this .authenticationHashGenerator = authenticationHashGenerator ;
90
- hAlgorithm = "SHA-1" ;
91
- hmacAlgorithm = "HmacSHA1" ;
98
+ if (credential .getAuthenticationMechanism ().equals (SCRAM_SHA_1 )) {
99
+ hAlgorithm = "SHA-1" ;
100
+ hmacAlgorithm = "HmacSHA1" ;
101
+ } else {
102
+ hAlgorithm = "SHA-256" ;
103
+ hmacAlgorithm = "HmacSHA256" ;
104
+ }
92
105
}
93
106
94
107
public String getMechanismName () {
@@ -122,7 +135,7 @@ private byte[] validateServerSignature(final byte[] challenge) throws SaslExcept
122
135
}
123
136
124
137
public boolean isComplete () {
125
- return step == 3 ;
138
+ return step == 2 ;
126
139
}
127
140
128
141
public byte [] unwrap (final byte [] incoming , final int offset , final int len ) {
@@ -280,11 +293,19 @@ private HashMap<String, String> parseServerResponse(final String response) {
280
293
}
281
294
282
295
private String getUserName () {
283
- return credential .getUserName ().replace ("=" , "=3D" ).replace ("," , "=2C" );
296
+ String userName = credential .getUserName ().replace ("=" , "=3D" ).replace ("," , "=2C" );
297
+ if (credential .getAuthenticationMechanism () == SCRAM_SHA_256 ) {
298
+ userName = SaslPrep .saslPrepStored (userName );
299
+ }
300
+ return userName ;
284
301
}
285
302
286
303
private String getAuthenicationHash () {
287
- return authenticationHashGenerator .generate (credential );
304
+ String password = authenticationHashGenerator .generate (credential );
305
+ if (credential .getAuthenticationMechanism () == SCRAM_SHA_256 ) {
306
+ password = SaslPrep .saslPrepStored (password );
307
+ }
308
+ return password ;
288
309
}
289
310
290
311
private byte [] xorInPlace (final byte [] a , final byte [] b ) {
@@ -330,7 +351,16 @@ public String generate(final int length) {
330
351
}
331
352
}
332
353
333
- private static final AuthenticationHashGenerator AUTHENTICATION_HASH_GENERATOR = new AuthenticationHashGenerator () {
354
+ private static final AuthenticationHashGenerator DEFAULT_AUTHENTICATION_HASH_GENERATOR = new AuthenticationHashGenerator () {
355
+ // Suppress warning of MongoCredential#getAuthenicationHash possibly returning null
356
+ @ SuppressWarnings ("ConstantConditions" )
357
+ @ Override
358
+ public String generate (final MongoCredential credential ) {
359
+ return new String (credential .getPassword ());
360
+ }
361
+ };
362
+
363
+ private static final AuthenticationHashGenerator LEGACY_AUTHENTICATION_HASH_GENERATOR = new AuthenticationHashGenerator () {
334
364
// Suppress warning of MongoCredential#getAuthenicationHash possibly returning null
335
365
@ SuppressWarnings ("ConstantConditions" )
336
366
@ Override
@@ -339,4 +369,8 @@ public String generate(final MongoCredential credential) {
339
369
return createAuthenticationHash (credential .getUserName (), credential .getPassword ());
340
370
}
341
371
};
372
+
373
+ private static AuthenticationHashGenerator getAuthenicationHashGenerator (final AuthenticationMechanism authenticationMechanism ) {
374
+ return authenticationMechanism == SCRAM_SHA_1 ? LEGACY_AUTHENTICATION_HASH_GENERATOR : DEFAULT_AUTHENTICATION_HASH_GENERATOR ;
375
+ }
342
376
}
0 commit comments