/// <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;
}
}