Permalink
Browse files

CSHARP-603: initial commit for SASL authentication.

  • Loading branch information...
1 parent 275bf49 commit 6f33dde4b52ddeae1e47a60872ac56c16deb50f5 @craiggwilson craiggwilson committed Dec 18, 2012
Showing with 3,190 additions and 196 deletions.
  1. +16 −192 MongoDB.Driver/Communication/MongoConnection.cs
  2. +1 −1 MongoDB.Driver/Communication/MongoServerInstance.cs
  3. +136 −0 MongoDB.Driver/Communication/Security/Gsasl/Gsasl.cs
  4. +92 −0 MongoDB.Driver/Communication/Security/Gsasl/GsaslContext.cs
  5. +45 −0 MongoDB.Driver/Communication/Security/Gsasl/GsaslException.cs
  6. +47 −0 MongoDB.Driver/Communication/Security/Gsasl/GsaslProperty.cs
  7. +132 −0 MongoDB.Driver/Communication/Security/Gsasl/GsaslSession.cs
  8. +18 −0 MongoDB.Driver/Communication/Security/IAuthenticationStore.cs
  9. +26 −0 MongoDB.Driver/Communication/Security/ISaslMechanism.cs
  10. +23 −0 MongoDB.Driver/Communication/Security/ISaslStep.cs
  11. +175 −0 MongoDB.Driver/Communication/Security/LegacyAuthenticationStore.cs
  12. +120 −0 MongoDB.Driver/Communication/Security/Mechanisms/AbstractGsaslMechanism.cs
  13. +83 −0 MongoDB.Driver/Communication/Security/Mechanisms/CramMD5Mechanism.cs
  14. +69 −0 MongoDB.Driver/Communication/Security/Mechanisms/GsaslCramMD5Mechanism.cs
  15. +52 −0 MongoDB.Driver/Communication/Security/Mechanisms/GsaslGssApiMechanism.cs
  16. +190 −0 MongoDB.Driver/Communication/Security/Mechanisms/SspiMechanism.cs
  17. +44 −0 MongoDB.Driver/Communication/Security/MongoSecurityException.cs
  18. +119 −0 MongoDB.Driver/Communication/Security/SaslAuthenticationStore.cs
  19. +49 −0 MongoDB.Driver/Communication/Security/SaslCompletionStep.cs
  20. +108 −0 MongoDB.Driver/Communication/Security/SaslConversation.cs
  21. +47 −0 MongoDB.Driver/Communication/Security/SaslInitiationStep.cs
  22. +50 −0 MongoDB.Driver/Communication/Security/Sspi/AuthIdentity.cs
  23. +22 −0 MongoDB.Driver/Communication/Security/Sspi/AuthIdentityFlag.cs
  24. +26 −0 MongoDB.Driver/Communication/Security/Sspi/DataRepresentation.cs
  25. +22 −0 MongoDB.Driver/Communication/Security/Sspi/EncryptQualityOfProtection.cs
  26. +22 −0 MongoDB.Driver/Communication/Security/Sspi/QueryContextAttribute.cs
  27. +82 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityBuffer.cs
  28. +163 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityBufferDescriptor.cs
  29. +38 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityBufferType.cs
  30. +359 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityContext.cs
  31. +21 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityCredentialUse.cs
  32. +110 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityCredentials.cs
  33. +23 −0 MongoDB.Driver/Communication/Security/Sspi/SecurityPackageContextSizes.cs
  34. +32 −0 MongoDB.Driver/Communication/Security/Sspi/SspiContextFlags.cs
  35. +53 −0 MongoDB.Driver/Communication/Security/Sspi/SspiHandle.cs
  36. +18 −0 MongoDB.Driver/Communication/Security/Sspi/SspiPackage.cs
  37. +306 −0 MongoDB.Driver/Communication/Security/Sspi/Win32.cs
  38. +45 −0 MongoDB.Driver/Communication/Security/Sspi/Win32Exception.cs
  39. +136 −0 MongoDB.Driver/MongoClientIdentity.cs
  40. +15 −0 MongoDB.Driver/MongoClientSettings.cs
  41. +37 −0 MongoDB.Driver/MongoDB.Driver.csproj
  42. +2 −2 MongoDB.Driver/MongoServer.cs
  43. +16 −1 MongoDB.Driver/MongoServerSettings.cs
@@ -26,6 +26,8 @@
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
+using MongoDB.Driver.Security;
+using MongoDB.Driver.Communication.Security;
namespace MongoDB.Driver.Internal
{
@@ -54,6 +56,7 @@ public enum MongoConnectionState
public class MongoConnection
{
// private fields
+ private readonly IAuthenticationStore _authenticationStore;
private object _connectionLock = new object();
private MongoServerInstance _serverInstance;
private MongoConnectionPool _connectionPool;
@@ -65,23 +68,28 @@ public class MongoConnection
private DateTime _lastUsedAt; // set every time the connection is Released
private int _messageCounter;
private int _requestId;
- private Dictionary<string, Authentication> _authentications = new Dictionary<string, Authentication>();
// constructors
internal MongoConnection(MongoConnectionPool connectionPool)
+ : this(connectionPool.ServerInstance)
{
- _serverInstance = connectionPool.ServerInstance;
_connectionPool = connectionPool;
_generationId = connectionPool.GenerationId;
- _createdAt = DateTime.UtcNow;
- _state = MongoConnectionState.Initial;
}
internal MongoConnection(MongoServerInstance serverInstance)
{
_serverInstance = serverInstance;
_createdAt = DateTime.UtcNow;
_state = MongoConnectionState.Initial;
+ if (serverInstance.Settings.Identity != null)
+ {
+ _authenticationStore = new SaslAuthenticationStore(this, serverInstance.Settings.Identity);
+ }
+ else
+ {
+ _authenticationStore = new LegacyAuthenticationStore(this);
+ }
}
// public properties
@@ -154,133 +162,13 @@ public MongoConnectionState State
internal void Authenticate(string databaseName, MongoCredentials credentials)
{
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
- lock (_connectionLock)
- {
- var nonceCommand = new CommandDocument("getnonce", 1);
- var commandResult = RunCommand(databaseName, QueryFlags.None, nonceCommand, false);
- if (!commandResult.Ok)
- {
- throw new MongoAuthenticationException(
- "Error getting nonce for authentication.",
- new MongoCommandException(commandResult));
- }
-
- var nonce = commandResult.Response["nonce"].AsString;
- var passwordDigest = MongoUtils.Hash(credentials.Username + ":mongo:" + credentials.Password);
- var digest = MongoUtils.Hash(nonce + credentials.Username + passwordDigest);
- var authenticateCommand = new CommandDocument
- {
- { "authenticate", 1 },
- { "user", credentials.Username },
- { "nonce", nonce },
- { "key", digest }
- };
-
- commandResult = RunCommand(databaseName, QueryFlags.None, authenticateCommand, false);
- if (!commandResult.Ok)
- {
- var message = string.Format("Invalid credentials for database '{0}'.", databaseName);
- throw new MongoAuthenticationException(
- message,
- new MongoCommandException(commandResult));
- }
-
- var authentication = new Authentication(credentials);
- _authentications.Add(databaseName, authentication);
- }
+ _authenticationStore.Authenticate(databaseName, credentials);
}
- // check whether the connection can be used with the given database (and credentials)
- // the following are the only valid authentication states for a connection:
- // 1. the connection is not authenticated against any database
- // 2. the connection has a single authentication against the admin database (with a particular set of credentials)
- // 3. the connection has one or more authentications against any databases other than admin
- // (with the restriction that a particular database can only be authenticated against once and therefore with only one set of credentials)
-
- // assume that IsAuthenticated was called first and returned false
internal bool CanAuthenticate(string databaseName, MongoCredentials credentials)
{
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
- if (databaseName == null)
- {
- return true;
- }
-
- if (_authentications.Count == 0)
- {
- // a connection with no existing authentications can authenticate anything
- return true;
- }
- else
- {
- // a connection with existing authentications can't be used without credentials
- if (credentials == null)
- {
- return false;
- }
-
- // a connection with existing authentications can't be used with new admin credentials
- if (credentials.Admin)
- {
- return false;
- }
-
- // a connection with an existing authentication to the admin database can't be used with any other credentials
- if (_authentications.ContainsKey("admin"))
- {
- return false;
- }
-
- // a connection with an existing authentication to a database can't authenticate for the same database again
- if (_authentications.ContainsKey(databaseName))
- {
- return false;
- }
-
- return true;
- }
- }
-
- internal void CheckAuthentication(string databaseName, MongoCredentials credentials)
- {
- if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
- if (credentials == null)
- {
- if (_authentications.Count != 0)
- {
- throw new InvalidOperationException("Connection requires credentials.");
- }
- }
- else
- {
- var authenticationDatabaseName = credentials.Admin ? "admin" : databaseName;
- Authentication authentication;
- if (_authentications.TryGetValue(authenticationDatabaseName, out authentication))
- {
- if (authentication.Credentials != credentials)
- {
- // this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable
- if (authenticationDatabaseName == "admin")
- {
- throw new MongoInternalException("Connection already authenticated to the admin database with different credentials.");
- }
- else
- {
- throw new MongoInternalException("Connection already authenticated to the database with different credentials.");
- }
- }
- authentication.LastUsed = DateTime.UtcNow;
- }
- else
- {
- if (authenticationDatabaseName == "admin" && _authentications.Count != 0)
- {
- // this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable
- throw new MongoInternalException("The connection cannot be authenticated against the admin database because it is already authenticated against other databases.");
- }
- Authenticate(authenticationDatabaseName, credentials);
- }
- }
+ return _authenticationStore.CanAuthenticate(databaseName, credentials);
}
internal void Close()
@@ -312,31 +200,7 @@ internal void Close()
internal bool IsAuthenticated(string databaseName, MongoCredentials credentials)
{
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
- if (databaseName == null)
- {
- return true;
- }
-
- lock (_connectionLock)
- {
- if (credentials == null)
- {
- return _authentications.Count == 0;
- }
- else
- {
- var authenticationDatabaseName = credentials.Admin ? "admin" : databaseName;
- Authentication authentication;
- if (_authentications.TryGetValue(authenticationDatabaseName, out authentication))
- {
- return credentials == authentication.Credentials;
- }
- else
- {
- return false;
- }
- }
- }
+ return _authenticationStore.IsAuthenticated(databaseName, credentials);
}
internal bool IsExpired()
@@ -349,19 +213,7 @@ internal bool IsExpired()
internal void Logout(string databaseName)
{
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
- lock (_connectionLock)
- {
- var logoutCommand = new CommandDocument("logout", 1);
- var commandResult = RunCommand(databaseName, QueryFlags.None, logoutCommand, false);
- if (!commandResult.Ok)
- {
- throw new MongoAuthenticationException(
- "Error logging off.",
- new MongoCommandException(commandResult));
- }
-
- _authentications.Remove(databaseName);
- }
+ _authenticationStore.Logout(databaseName);
}
internal void Open()
@@ -633,33 +485,5 @@ private HandleExceptionAction DetermineAction(Exception ex)
return HandleExceptionAction.CloseConnection; // this should always be the default action
}
-
- // private nested classes
- // keeps track of what credentials were used with a given database
- // and when that database was last used on this connection
- private class Authentication
- {
- // private fields
- private MongoCredentials _credentials;
- private DateTime _lastUsed;
-
- // constructors
- public Authentication(MongoCredentials credentials)
- {
- _credentials = credentials;
- _lastUsed = DateTime.UtcNow;
- }
-
- public MongoCredentials Credentials
- {
- get { return _credentials; }
- }
-
- public DateTime LastUsed
- {
- get { return _lastUsed; }
- set { _lastUsed = value; }
- }
- }
}
}
@@ -389,7 +389,7 @@ internal MongoConnection AcquireConnection(string databaseName, MongoCredentials
try
{
- connection.CheckAuthentication(databaseName, credentials); // will authenticate if necessary
+ connection.Authenticate(databaseName, credentials); // will authenticate if necessary
}
catch (MongoAuthenticationException)
{
Oops, something went wrong.

0 comments on commit 6f33dde

Please sign in to comment.