// public methods /// <summary> /// Transitions to the next step in the conversation. /// </summary> /// <param name="conversation">The conversation.</param> /// <param name="input">The input.</param> /// <returns>An ISaslStep.</returns> /// <exception cref="MongoSecurityException">Unable to initialize context.</exception> public ISaslStep Transition(SaslConversation conversation, byte[] input) { GsaslContext context; try { context = GsaslContext.Initialize(); conversation.RegisterItemForDisposal(context); } catch (GsaslException ex) { throw new MongoSecurityException("Unable to initialize context.", ex); } GsaslSession session; try { session = context.BeginSession(_name); conversation.RegisterItemForDisposal(session); } catch (GsaslException ex) { throw new MongoSecurityException("Unable to start a session.", ex); } foreach (var property in GetProperties()) { session.SetProperty(property.Key, property.Value); } return new GsaslAuthenticateStep(session, null) .Transition(conversation, input); }
// methods /// <inheritdoc/> public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); using (var conversation = new SaslConversation(description.ConnectionId)) { var currentStep = _mechanism.Initialize(connection, description); var command = CreateStartCommand(currentStep); while (true) { BsonDocument result; try { var protocol = CreateCommandProtocol(command); result = protocol.Execute(connection, cancellationToken); } catch (MongoCommandException ex) { throw CreateException(connection, ex); } currentStep = Transition(conversation, currentStep, result); if (currentStep == null) { return; } command = CreateContinueCommand(currentStep, result); } } }
// methods /// <inheritdoc/> public async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); using (var conversation = new SaslConversation(description.ConnectionId)) { var currentStep = _mechanism.Initialize(connection, description); var command = new BsonDocument { { "saslStart", 1 }, { "mechanism", _mechanism.Name }, { "payload", currentStep.BytesToSendToServer } }; while (true) { BsonDocument result; try { var protocol = new CommandWireProtocol<BsonDocument>( new DatabaseNamespace(DatabaseName), command, true, BsonDocumentSerializer.Instance, null); result = await protocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); } catch (MongoCommandException ex) { var message = string.Format("Unable to authenticate using sasl protocol mechanism {0}.", Name); throw new MongoAuthenticationException(connection.ConnectionId, message, ex); } // we might be done here if the client is not expecting a reply from the server if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } currentStep = currentStep.Transition(conversation, result["payload"].AsByteArray); // we might be done here if the client had some final verification it needed to do if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } command = new BsonDocument { { "saslContinue", 1 }, { "conversationId", result["conversationId"].AsInt32 }, { "payload", currentStep.BytesToSendToServer } }; } } }
// methods public async Task AuthenticateAsync(IConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { using (var conversation = new SaslConversation()) { var currentStep = _mechanism.Initialize(connection); var command = new BsonDocument { { "saslStart", 1 }, { "mechanism", _mechanism.Name }, { "payload", currentStep.BytesToSendToServer } }; var slidingTimeout = new SlidingTimeout(timeout); while (true) { BsonDocument result; try { var protocol = new CommandWireProtocol(DatabaseName, command, true); result = await protocol.ExecuteAsync(connection, slidingTimeout, cancellationToken); } catch(MongoCommandException ex) { var message = string.Format("Unable to authenticate using sasl protocol mechanism {0}.", Name); throw new MongoAuthenticationException(message, ex); } // we might be done here if the client is not expecting a reply from the server if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } currentStep = currentStep.Transition(conversation, result["payload"].AsByteArray); // we might be done here if the client had some final verification it needed to do if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } command = new BsonDocument { { "saslContinue", 1 }, { "conversationId", result["conversationId"].AsInt32 }, { "payload", currentStep.BytesToSendToServer } }; } } }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = Utf8Encodings.Strict; var serverFirstMessage = encoding.GetString(bytesReceivedFromServer); var map = SaslMapParser.Parse(serverFirstMessage); var r = map['r']; if (!r.StartsWith(_rPrefix, StringComparison.Ordinal)) { throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server sent an invalid nonce."); } var s = map['s']; var i = map['i']; const string gs2Header = "n,,"; var channelBinding = "c=" + Convert.ToBase64String(encoding.GetBytes(gs2Header)); var nonce = "r=" + r; var clientFinalMessageWithoutProof = channelBinding + "," + nonce; var salt = Convert.FromBase64String(map['s']); var iterations = int.Parse(map['i']); byte[] clientKey; byte[] serverKey; var cacheKey = new ScramCacheKey(_credential.SaslPreppedPassword, salt, iterations); if (_cache.TryGet(cacheKey, out var cacheEntry)) { clientKey = cacheEntry.ClientKey; serverKey = cacheEntry.ServerKey; } else { var saltedPassword = _hi(_credential, salt, iterations); clientKey = _hmac(encoding, saltedPassword, "Client Key"); serverKey = _hmac(encoding, saltedPassword, "Server Key"); _cache.Add(cacheKey, new ScramCacheEntry(clientKey, serverKey)); } var storedKey = _h(clientKey); var authMessage = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof; var clientSignature = _hmac(encoding, storedKey, authMessage); var clientProof = XOR(clientKey, clientSignature); var serverSignature = _hmac(encoding, serverKey, authMessage); var proof = "p=" + Convert.ToBase64String(clientProof); var clientFinalMessage = clientFinalMessageWithoutProof + "," + proof; return(new ClientLast(encoding.GetBytes(clientFinalMessage), serverSignature)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = Utf8Encodings.Strict; var map = NVParser.Parse(encoding.GetString(bytesReceivedFromServer)); var serverSignature = map['v']; if (_serverSignature64 != serverSignature) { throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server signature was invalid."); } return(new CompletedStep()); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = new UTF8Encoding(false, true); var map = NVParser.Parse(encoding.GetString(bytesReceivedFromServer)); var serverSignature = map['v']; if (_serverSignature64 != serverSignature) { throw new AuthenticationException("Server signature was invalid."); } return(new CompletedStep()); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { if (bytesReceivedFromServer == null || bytesReceivedFromServer.Length != 32) //RFC specifies this must be 4 octets { throw new MongoSecurityException("Invalid server response."); } byte[] decryptedBytes; try { _context.DecryptMessage(0, bytesReceivedFromServer, out decryptedBytes); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { _context.EncryptMessage(bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to encrypt message.", ex); } return(new SaslCompletionStep(bytesToSendToServer)); }
public ISaslStep Initialize(IConnection connection, SaslConversation conversation, ConnectionDescription description) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); const string gs2Header = "n,,"; var username = "******" + PrepUsername(_credential.Username); var r = GenerateRandomString(); var nonce = "r=" + r; var clientFirstMessageBare = username + "," + nonce; var clientFirstMessage = gs2Header + clientFirstMessageBare; var clientFirstMessageBytes = Utf8Encodings.Strict.GetBytes(clientFirstMessage); return(new ClientFirst(clientFirstMessageBytes, clientFirstMessageBare, _credential, r, _h, _hi, _hmac, _cache)); }
public ISaslStep Initialize(IConnection connection, SaslConversation conversation, ConnectionDescription description) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); var nonce = GenerateRandomBytes(); var document = new BsonDocument { { "r", nonce }, { "p", (int)'n' } }; var clientMessageBytes = document.ToBson(); return(new ClientFirst(clientMessageBytes, nonce, _awsCredentials, _clock)); }
// public methods public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { try { var bytesToSendToServer = _session.Step(bytesReceivedFromServer); if (_session.IsComplete) { return(new SaslCompletionStep(bytesToSendToServer)); } return(new GsaslAuthenticateStep(_session, bytesToSendToServer)); } catch (GsaslException ex) { throw new MongoSecurityException("Unable to authenticate.", ex); } }
// public methods /// <summary> /// Transitions to the next step in the conversation. /// </summary> /// <param name="conversation">The conversation.</param> /// <param name="bytesReceivedFromServer">The bytes received from the server.</param> /// <returns>An ISaslStep.</returns> public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var directives = DirectiveParser.Parse(bytesReceivedFromServer); var encoding = Encoding.UTF8; var sb = new StringBuilder(); sb.AppendFormat("username=\"{0}\"", _username); sb.AppendFormat(",nonce=\"{0}\"", encoding.GetString(directives["nonce"]).Replace("\"", "\\\"")); sb.AppendFormat(",cnonce=\"{0}\"", encoding.GetString(_cnonce).Replace("\"", "\\\"")); sb.AppendFormat(",nc={0}", _nonceCount); sb.AppendFormat(",qop={0}", _qop); sb.AppendFormat(",digest-uri=\"{0}\"", _digestUri); sb.AppendFormat(",response={0}", ComputeResponse(encoding, directives["nonce"])); sb.Append(",charset=\"utf-8\""); return new ManagedDigestMD5FinalStep(encoding.GetBytes(sb.ToString())); }
private ISaslStep Transition(SaslConversation conversation, ISaslStep currentStep, BsonDocument result) { // we might be done here if the client is not expecting a reply from the server if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { return(null); } currentStep = currentStep.Transition(conversation, result["payload"].AsByteArray); // we might be done here if the client had some final verification it needed to do if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { return(null); } return(currentStep); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var serverFirstMessageDocument = BsonSerializer.Deserialize <BsonDocument>(bytesReceivedFromServer); var serverNonce = serverFirstMessageDocument["s"].AsByteArray; var host = serverFirstMessageDocument["h"].AsString; if (serverNonce.Length != ClientNonceLength * 2 || !serverNonce.Take(ClientNonceLength).SequenceEqual(_nonce)) { throw new MongoAuthenticationException(conversation.ConnectionId, "Server sent an invalid nonce."); } if (host.Length < 1 || host.Length > 255 || host.Contains("..")) { throw new MongoAuthenticationException(conversation.ConnectionId, "Server returned an invalid sts host."); } var unexpectedNames = serverFirstMessageDocument.Names.Except(new[] { "h", "s" }); if (unexpectedNames.Any()) { throw new MongoAuthenticationException( conversation.ConnectionId, $"Server returned unexpected fields: {string.Join(", ", unexpectedNames)}."); } AwsSignatureVersion4.CreateAuthorizationRequest( _clock.UtcNow, _awsCredentials.AccessKeyId, _awsCredentials.SecretAccessKey, _awsCredentials.SessionToken, serverNonce, host, out var authorizationHeader, out var timestamp); var document = new BsonDocument { { "a", authorizationHeader }, { "d", timestamp }, { "t", _awsCredentials.SessionToken, _awsCredentials.SessionToken != null } }; var clientSecondMessageBytes = document.ToBson(); return(new ClientLast(clientSecondMessageBytes)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { try { // NOTE: We simply check whether we can successfully decrypt the message, // but don't do anything with the decrypted plaintext _ = _context.DecryptMessage(0, bytesReceivedFromServer); } catch (GssapiException ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { bytesToSendToServer = _context.EncryptMessage(bytesReceivedFromServer); } catch (GssapiException ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to encrypt message.", ex); } return(new CompletedStep(bytesToSendToServer)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { byte[] bytesToSendToServer; try { bytesToSendToServer = _context.Next(bytesReceivedFromServer); } catch (GssapiException ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context", ex); } if (!_context.IsInitialized) { return(new InitializeStep(_authorizationId, _context, bytesToSendToServer)); } return(new NegotiateStep(_authorizationId, _context, bytesToSendToServer)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { byte[] bytesToSendToServer; try { _context.Initialize(_servicePrincipalName, bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context", ex); } if (!_context.IsInitialized) { return(new InitializeStep(_servicePrincipalName, _authorizationId, _context, bytesToSendToServer)); } return(new NegotiateStep(_authorizationId, _context, bytesToSendToServer)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { byte[] decryptedBytes; try { _context.DecryptMessage(0, bytesReceivedFromServer, out decryptedBytes); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unabled to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { _context.EncryptMessage(bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unabled to encrypt message.", ex); } return(new CompletedStep(bytesToSendToServer)); }
// public methods /// <summary> /// Transitions to the next step in the conversation. /// </summary> /// <param name="conversation">The conversation.</param> /// <param name="bytesReceivedFromServer">The bytes received from the server.</param> /// <returns>An ISaslStep.</returns> public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { SecurityCredential securityCredential; try { securityCredential = SecurityCredential.Acquire(SspiPackage.Kerberos, _authorizationId, _evidence); conversation.RegisterItemForDisposal(securityCredential); } catch (Win32Exception ex) { throw new MongoSecurityException("Unable to acquire security credential.", ex); } byte[] bytesToSendToServer; SecurityContext context; try { context = SecurityContext.Initialize(securityCredential, _servicePrincipalName, bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { if (_evidence is PasswordEvidence) { throw new MongoSecurityException("Unable to initialize security context. Ensure the username and password are correct.", ex); } else { throw new MongoSecurityException("Unable to initialize security context.", ex); } } if (!context.IsInitialized) { return(new SspiInitializeStep(_servicePrincipalName, _authorizationId, context, bytesToSendToServer)); } return(new SspiNegotiateStep(_authorizationId, context, bytesToSendToServer)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = Utf8Encodings.Strict; var serverFirstMessage = encoding.GetString(bytesReceivedFromServer); var map = NVParser.Parse(serverFirstMessage); var r = map['r']; if (!r.StartsWith(_rPrefix)) { throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server sent an invalid nonce."); } var s = map['s']; var i = map['i']; const string gs2Header = "n,,"; var channelBinding = "c=" + Convert.ToBase64String(encoding.GetBytes(gs2Header)); var nonce = "r=" + r; var clientFinalMessageWithoutProof = channelBinding + "," + nonce; var saltedPassword = Hi( AuthenticationHelper.MongoPasswordDigest(_credential.Username, _credential.Password), Convert.FromBase64String(s), int.Parse(i)); var clientKey = HMAC(encoding, saltedPassword, "Client Key"); var storedKey = H(clientKey); var authMessage = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof; var clientSignature = HMAC(encoding, storedKey, authMessage); var clientProof = XOR(clientKey, clientSignature); var serverKey = HMAC(encoding, saltedPassword, "Server Key"); var serverSignature = HMAC(encoding, serverKey, authMessage); var proof = "p=" + Convert.ToBase64String(clientProof); var clientFinalMessage = clientFinalMessageWithoutProof + "," + proof; return(new ClientLast(encoding.GetBytes(clientFinalMessage), serverSignature)); }
// public methods /// <summary> /// Transitions to the next step in the conversation. /// </summary> /// <param name="conversation">The conversation.</param> /// <param name="bytesReceivedFromServer">The bytes received from the server.</param> /// <returns>An ISaslStep.</returns> public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { SecurityCredential securityCredential; try { securityCredential = SecurityCredential.Acquire(SspiPackage.Kerberos, _authorizationId, _evidence); conversation.RegisterItemForDisposal(securityCredential); } catch (Win32Exception ex) { throw new MongoSecurityException("Unable to acquire security credential.", ex); } byte[] bytesToSendToServer; SecurityContext context; try { context = SecurityContext.Initialize(securityCredential, _servicePrincipalName, bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { if (_evidence is PasswordEvidence) { throw new MongoSecurityException("Unable to initialize security context. Ensure the username and password are correct.", ex); } else { throw new MongoSecurityException("Unable to initialize security context.", ex); } } if (!context.IsInitialized) { return new SspiInitializeStep(_servicePrincipalName, _authorizationId, context, bytesToSendToServer); } return new SspiNegotiateStep(_authorizationId, context, bytesToSendToServer); }
// public methods public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = Encoding.UTF8; var mongoPassword = _username + ":mongo:" + _password; byte[] password; using (var md5 = MD5.Create()) { password = GetMongoPassword(md5, encoding, _username, _password); var temp = ToHexString(password); password = encoding.GetBytes(temp); } byte[] digest; using (var hmacMd5 = new HMACMD5(password)) { digest = hmacMd5.ComputeHash(bytesReceivedFromServer); } var response = _username + " " + ToHexString(digest); var bytesToSendToServer = encoding.GetBytes(response); return new SaslCompletionStep(bytesToSendToServer); }
// methods /// <inheritdoc/> public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); using (var conversation = new SaslConversation(description.ConnectionId)) { ISaslStep currentStep; BsonDocument command; var speculativeAuthenticateResult = description.HelloResult.SpeculativeAuthenticate; if (_speculativeFirstStep != null && speculativeAuthenticateResult != null) { currentStep = Transition(conversation, _speculativeFirstStep, speculativeAuthenticateResult, out command); } else { currentStep = _mechanism.Initialize(connection, conversation, description); command = CreateStartCommand(currentStep); } while (currentStep != null) { BsonDocument result; try { var protocol = CreateCommandProtocol(command); result = protocol.Execute(connection, cancellationToken); } catch (MongoException ex) { throw CreateException(connection, ex); } currentStep = Transition(conversation, currentStep, result, out command); } } }
public ISaslStep Initialize(IConnection connection, SaslConversation conversation, ConnectionDescription description) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); string hostName; var dnsEndPoint = connection.EndPoint as DnsEndPoint; if (dnsEndPoint != null) { hostName = dnsEndPoint.Host; } else if (connection.EndPoint is IPEndPoint) { hostName = ((IPEndPoint)connection.EndPoint).Address.ToString(); } else { throw new MongoAuthenticationException(connection.ConnectionId, "Only DnsEndPoint and IPEndPoint are supported for GSSAPI authentication."); } if (_canonicalizeHostName) { #if NETSTANDARD1_5 var entry = Dns.GetHostEntryAsync(hostName).GetAwaiter().GetResult(); #else var entry = Dns.GetHostEntry(hostName); #endif if (entry != null) { hostName = entry.HostName; } } return(new FirstStep(_serviceName, hostName, _realm, _username, _password, conversation)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = new UTF8Encoding(false, true); var serverFirstMessage = encoding.GetString(bytesReceivedFromServer); var map = NVParser.Parse(serverFirstMessage); var r = map['r']; if (!r.StartsWith(_rPrefix)) { throw new MongoAuthenticationException("Server sent an invalid nonce."); } var s = map['s']; var i = map['i']; const string gs2Header = "n,,"; var channelBinding = "c=" + Convert.ToBase64String(encoding.GetBytes(gs2Header)); var nonce = "r=" + r; var clientFinalMessageWithoutProof = channelBinding + "," + nonce; var saltedPassword = Hi( AuthenticationHelper.MongoUsernamePasswordDigest(_credential.Username, _credential.Password), Convert.FromBase64String(s), int.Parse(i)); var clientKey = HMAC(encoding, saltedPassword, "Client Key"); var storedKey = H(clientKey); var authMessage = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof; var clientSignature = HMAC(encoding, storedKey, authMessage); var clientProof = XOR(clientKey, clientSignature); var serverKey = HMAC(encoding, saltedPassword, "Server Key"); var serverSignature = HMAC(encoding, serverKey, authMessage); var proof = "p=" + Convert.ToBase64String(clientProof); var clientFinalMessage = clientFinalMessageWithoutProof + "," + proof; return new ClientLast(encoding.GetBytes(clientFinalMessage), Convert.ToBase64String(serverSignature)); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { byte[] decryptedBytes; try { _context.DecryptMessage(0, bytesReceivedFromServer, out decryptedBytes); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unabled to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { _context.EncryptMessage(bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unabled to encrypt message.", ex); } return new CompletedStep(bytesToSendToServer); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { byte[] bytesToSendToServer; try { _context.Initialize(_servicePrincipalName, bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context", ex); } if (!_context.IsInitialized) { return new InitializeStep(_servicePrincipalName, _authorizationId, _context, bytesToSendToServer); } return new NegotiateStep(_authorizationId, _context, bytesToSendToServer); }
// public methods /// <summary> /// Transitions to the next step in the conversation. /// </summary> /// <param name="conversation">The conversation.</param> /// <param name="input">The input.</param> /// <returns>An ISaslStep.</returns> public ISaslStep Transition(SaslConversation conversation, byte[] input) { throw new MongoException("No more transitions available. The conversation is completed."); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { return new SaslCompletionStep(new byte[0]); }
public FirstStep(string serviceName, string hostName, string realm, string username, SecureString password, SaslConversation conversation) { _authorizationId = username; _password = password; _servicePrincipalName = string.Format("{0}/{1}", serviceName, hostName); if (!string.IsNullOrEmpty(realm)) { _servicePrincipalName += "@" + realm; } SecurityCredential securityCredential; try { securityCredential = SecurityCredential.Acquire(SspiPackage.Kerberos, _authorizationId, _password); conversation.RegisterItemForDisposal(securityCredential); } catch (Win32Exception ex) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to acquire security credential.", ex); } try { _context = Sspi.SecurityContext.Initialize(securityCredential, _servicePrincipalName, null, out _bytesToSendToServer); } catch (Win32Exception ex) { if (_password != null) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context. Ensure the username and password are correct.", ex); } else { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context.", ex); } } }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { // Even though RFC says that clients should specifically check this and raise an error // if it isn't true, this breaks on Windows XP, so we are skipping the check for windows // XP, identified as Win32NT 5.1: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major != 5 || Environment.OSVersion.Version.Minor != 1) { if (bytesReceivedFromServer == null || bytesReceivedFromServer.Length != 32) //RFC specifies this must be 4 octets { throw new MongoSecurityException("Invalid server response."); } } byte[] decryptedBytes; try { _context.DecryptMessage(0, bytesReceivedFromServer, out decryptedBytes); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { _context.EncryptMessage(bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to encrypt message.", ex); } return new SaslCompletionStep(bytesToSendToServer); }
// public methods public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { try { var bytesToSendToServer = _session.Step(bytesReceivedFromServer); if (_session.IsComplete) { return new SaslCompletionStep(bytesToSendToServer); } return new GsaslAuthenticateStep(_session, bytesToSendToServer); } catch (GsaslException ex) { throw new MongoSecurityException("Unable to authenticate.", ex); } }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { if (bytesReceivedFromServer == null || bytesReceivedFromServer.Length != 32) //RFC specifies this must be 4 octets { throw new MongoSecurityException("Invalid server response."); } byte[] decryptedBytes; try { _context.DecryptMessage(0, bytesReceivedFromServer, out decryptedBytes); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to decrypt message.", ex); } int length = 4; if (_authorizationId != null) { length += _authorizationId.Length; } bytesReceivedFromServer = new byte[length]; bytesReceivedFromServer[0] = 0x1; // NO_PROTECTION bytesReceivedFromServer[1] = 0x0; // NO_PROTECTION bytesReceivedFromServer[2] = 0x0; // NO_PROTECTION bytesReceivedFromServer[3] = 0x0; // NO_PROTECTION if (_authorizationId != null) { var authorizationIdBytes = Encoding.UTF8.GetBytes(_authorizationId); authorizationIdBytes.CopyTo(bytesReceivedFromServer, 4); } byte[] bytesToSendToServer; try { _context.EncryptMessage(bytesReceivedFromServer, out bytesToSendToServer); } catch (Win32Exception ex) { throw new MongoSecurityException("Unabled to encrypt message.", ex); } return new SaslCompletionStep(bytesToSendToServer); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = new UTF8Encoding(false, true); var map = NVParser.Parse(encoding.GetString(bytesReceivedFromServer)); var serverSignature = map['v']; if (_serverSignature64 != serverSignature) { throw new MongoAuthenticationException("Server signature was invalid."); } return new CompletedStep(); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { throw new InvalidOperationException("Sasl conversation has completed."); }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { return(new CompletedStep()); }
private ISaslStep Transition(SaslConversation conversation, ISaslStep currentStep, BsonDocument result) { // we might be done here if the client is not expecting a reply from the server if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { return null; } currentStep = currentStep.Transition(conversation, result["payload"].AsByteArray); // we might be done here if the client had some final verification it needed to do if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { return null; } return currentStep; }
public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer) { var encoding = Utf8Encodings.Strict; var map = NVParser.Parse(encoding.GetString(bytesReceivedFromServer)); var serverSignature = Convert.FromBase64String(map['v']); if (!ConstantTimeEquals(_serverSignature64, serverSignature)) { throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server signature was invalid."); } return new CompletedStep(); }
public FirstStep(string serviceName, string hostname, string realm, string username, SecureString password, SaslConversation conversation) { _authorizationId = username; try { _context = SecurityContextFactory.InitializeSecurityContext(serviceName, hostname, realm, _authorizationId, password); conversation.RegisterItemForDisposal(_context); _bytesToSendToServer = _context.Next(null); } catch (GssapiException ex) { if (password != null) { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context. Ensure the username and password are correct.", ex); } else { throw new MongoAuthenticationException(conversation.ConnectionId, "Unable to initialize security context.", ex); } } }