public static void Main(string[] args) { if(args.Length != 1) { Console.WriteLine("need ipadress "); return; } IPAddress ipAddress = IPAddress.Parse(args[0]); int port = 7681; TcpClient client = new TcpClient(); client.ConnectAsync(ipAddress, port).Wait(); Console.WriteLine("connected"); using (NegotiateStream stream = new NegotiateStream(client.GetStream())) { Console.WriteLine("authenticating"); stream.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, null, "HOST/skapilac10.fareast.corp.microsoft.com").Wait(); Console.WriteLine("authenticated"); var sendBuffer = Encoding.UTF8.GetBytes("Request from client"); stream.Write(sendBuffer, 0, sendBuffer.Length); var recvBuffer = new byte[1024]; var byteCount = stream.Read(recvBuffer, 0, recvBuffer.Length); Console.WriteLine("Recieved: {0}", Encoding.UTF8.GetString(recvBuffer, 0, byteCount)); } }
/// <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; } }
private static async Task RespondToOneMsg(TcpListener listener) { var socket = await listener.AcceptSocketAsync(); var client = await listener.AcceptTcpClientAsync(); Console.WriteLine("Connected"); using (var stream = new NegotiateStream(client.GetStream())) { await stream.AuthenticateAsServerAsync(CredentialCache.DefaultNetworkCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); Console.WriteLine($"remote {stream.RemoteIdentity.AuthenticationType}"); Console.WriteLine($"remote name = {stream.RemoteIdentity.Name}"); var recvBuffer = new byte[1024]; var byteCount = stream.Read(recvBuffer, 0, recvBuffer.Length); Console.WriteLine(Encoding.UTF8.GetString(recvBuffer, 0, byteCount)); var sendBuffer = Encoding.UTF8.GetBytes("Reply from server"); stream.Write(sendBuffer, 0, sendBuffer.Length); } }
/// <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; } } }