/// <summary> /// Authenticates the client stream /// </summary> /// <param name="stream">The stream to autenticate</param> /// <param name="userToken">the user token associated with the identity match</param> /// <param name="additionalChallenge">Additional data that much match between the client and server /// for the connection to succeed.</param> /// <returns>true if successful authentication. False otherwise.</returns> public bool TryAuthenticateAsServer(Stream stream, out Guid userToken, byte[] additionalChallenge = null) { userToken = Guid.Empty; if (additionalChallenge == null) additionalChallenge = new byte[] { }; if (additionalChallenge.Length > short.MaxValue) throw new ArgumentOutOfRangeException("additionalChallenge", "Must be less than 32767 bytes"); using (var negotiateStream = new NegotiateStream(stream, true)) { try { negotiateStream.AuthenticateAsServer(CredentialCache.DefaultNetworkCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); } catch (Exception ex) { Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", null, ex); return false; } negotiateStream.Write((short)additionalChallenge.Length); if (additionalChallenge.Length > 0) { negotiateStream.Write(additionalChallenge); } negotiateStream.Flush(); int len = negotiateStream.ReadInt16(); if (len < 0) { Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", "Challenge Length is invalid: " + len.ToString()); return false; } byte[] remoteChallenge; if (len == 0) { remoteChallenge = new byte[0]; } else { remoteChallenge = negotiateStream.ReadBytes(len); } if (remoteChallenge.SecureEquals(additionalChallenge)) { if (Users.TryGetToken(negotiateStream.RemoteIdentity, out userToken)) { return true; } Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", "User did not exist in the database: " + negotiateStream.RemoteIdentity.ToString()); return false; } Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", "Challenge did not match. Potential man in the middle attack."); return false; } }
/// <summary> /// Authenticates the client using the supplied stream. /// </summary> /// <param name="stream">the stream to use to authenticate the connection.</param> /// <param name="additionalChallenge">Additional data that much match between the client and server /// for the connection to succeed.</param> /// <returns> /// True if authentication succeded, false otherwise. /// </returns> public bool TryAuthenticateAsClient(Stream stream, byte[] additionalChallenge = null) { if (additionalChallenge == null) additionalChallenge = new byte[] { }; if (additionalChallenge.Length > short.MaxValue) throw new ArgumentOutOfRangeException("additionalChallenge","Must be less than 32767 bytes"); using (var negotiateStream = new NegotiateStream(stream, true)) { try { negotiateStream.AuthenticateAsClient(m_credentials, string.Empty, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); } catch (Exception ex) { Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", null, ex); return false; } //Exchange the challenge data. //Since NegotiateStream is already a trusted stream //Simply writing the raw is as secure as creating a challenge response negotiateStream.Write((short)additionalChallenge.Length); if (additionalChallenge.Length > 0) { negotiateStream.Write(additionalChallenge); } negotiateStream.Flush(); int len = negotiateStream.ReadInt16(); if (len < 0) { Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", "Challenge Length is invalid: " + len.ToString()); return false; } byte[] remoteChallenge; if (len == 0) { remoteChallenge = new byte[0]; } else { remoteChallenge = negotiateStream.ReadBytes(len); } if (remoteChallenge.SecureEquals(additionalChallenge)) { return true; } else { Log.Publish(MessageLevel.Info, "Security Login Failed", "Attempting an integrated security login failed", "Challenge did not match. Potential man in the middle attack."); return false; } } }