public void NegotiateStream_StreamToStream_Authentication_TargetName_Success() { string targetName = "testTargetName"; VirtualNetwork network = new VirtualNetwork(); using (var clientStream = new VirtualNetworkStream(network, isServer: false)) using (var serverStream = new VirtualNetworkStream(network, isServer: true)) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { Assert.False(client.IsAuthenticated); Assert.False(server.IsAuthenticated); Task[] auth = new Task[2]; auth[0] = client.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, targetName); auth[1] = server.AuthenticateAsServerAsync(); bool finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Handshake completed in the allotted time"); // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); Assert.Equal(true, client.IsEncrypted); Assert.Equal(false, client.IsMutuallyAuthenticated); Assert.Equal(false, client.IsServer); Assert.Equal(true, client.IsSigned); Assert.Equal(false, client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; Assert.Equal("NTLM", serverIdentity.AuthenticationType); Assert.Equal(true, serverIdentity.IsAuthenticated); Assert.Equal(targetName, serverIdentity.Name); // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); Assert.Equal(true, server.IsEncrypted); Assert.Equal(false, server.IsMutuallyAuthenticated); Assert.Equal(true, server.IsServer); Assert.Equal(true, server.IsSigned); Assert.Equal(false, server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; Assert.Equal("NTLM", clientIdentity.AuthenticationType); Assert.Equal(true, clientIdentity.IsAuthenticated); IdentityValidator.AssertIsCurrentIdentity(clientIdentity); } }
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => server.AuthenticateAsServerAsync();
protected abstract Task AuthenticateAsServerAsync(NegotiateStream server);
public void NegotiateStream_StreamToStream_Authentication_EmptyCredentials_Fails() { string targetName = "testTargetName"; // Ensure there is no confusion between DefaultCredentials / DefaultNetworkCredentials and a // NetworkCredential object with empty user, password and domain. NetworkCredential emptyNetworkCredential = new NetworkCredential("", "", ""); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultCredentials); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultNetworkCredentials); VirtualNetwork network = new VirtualNetwork(); using (var clientStream = new VirtualNetworkStream(network, isServer: false)) using (var serverStream = new VirtualNetworkStream(network, isServer: true)) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { Assert.False(client.IsAuthenticated); Assert.False(server.IsAuthenticated); Task[] auth = new Task[2]; auth[0] = AuthenticateAsClientAsync(client, emptyNetworkCredential, targetName); auth[1] = AuthenticateAsServerAsync(server); bool finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Handshake completed in the allotted time"); // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); Assert.Equal(true, client.IsEncrypted); Assert.Equal(false, client.IsMutuallyAuthenticated); Assert.Equal(false, client.IsServer); Assert.Equal(true, client.IsSigned); Assert.Equal(false, client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; Assert.Equal("NTLM", serverIdentity.AuthenticationType); Assert.Equal(true, serverIdentity.IsAuthenticated); Assert.Equal(targetName, serverIdentity.Name); // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); Assert.Equal(true, server.IsEncrypted); Assert.Equal(false, server.IsMutuallyAuthenticated); Assert.Equal(true, server.IsServer); Assert.Equal(true, server.IsSigned); Assert.Equal(false, server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; Assert.Equal("NTLM", clientIdentity.AuthenticationType); // TODO #5241: Behavior difference: Assert.Equal(false, clientIdentity.IsAuthenticated); // On .Net Desktop: Assert.Equal(true, clientIdentity.IsAuthenticated); IdentityValidator.AssertHasName(clientIdentity, @"NT AUTHORITY\ANONYMOUS LOGON"); } }
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Run(() => client.AuthenticateAsClient(credential, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification));
public async Task NegotiateStream_StreamToStream_Authentication_EmptyCredentials_Fails() { string targetName = "testTargetName"; // Ensure there is no confusion between DefaultCredentials / DefaultNetworkCredentials and a // NetworkCredential object with empty user, password and domain. NetworkCredential emptyNetworkCredential = new NetworkCredential("", "", ""); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultCredentials); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultNetworkCredentials); VirtualNetwork network = new VirtualNetwork(); using (var clientStream = new VirtualNetworkStream(network, isServer: false)) using (var serverStream = new VirtualNetworkStream(network, isServer: true)) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { Assert.False(client.IsAuthenticated); Assert.False(server.IsAuthenticated); Task[] auth = new Task[2]; auth[0] = AuthenticateAsClientAsync(client, emptyNetworkCredential, targetName); auth[1] = AuthenticateAsServerAsync(server); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(auth); // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); Assert.Equal(true, client.IsEncrypted); Assert.Equal(false, client.IsMutuallyAuthenticated); Assert.Equal(false, client.IsServer); Assert.Equal(true, client.IsSigned); Assert.Equal(false, client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; Assert.Equal("NTLM", serverIdentity.AuthenticationType); Assert.Equal(true, serverIdentity.IsAuthenticated); Assert.Equal(targetName, serverIdentity.Name); // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); Assert.Equal(true, server.IsEncrypted); Assert.Equal(false, server.IsMutuallyAuthenticated); Assert.Equal(true, server.IsServer); Assert.Equal(true, server.IsSigned); Assert.Equal(false, server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; Assert.Equal("NTLM", clientIdentity.AuthenticationType); // TODO #5241: Behavior difference: Assert.Equal(false, clientIdentity.IsAuthenticated); // On .Net Desktop: Assert.Equal(true, clientIdentity.IsAuthenticated); IdentityValidator.AssertHasName(clientIdentity, new SecurityIdentifier(WellKnownSidType.AnonymousSid, null).Translate(typeof(NTAccount)).Value); } }
public void NegotiateStream_StreamToStream_Successive_ClientWrite_Async_Success() { byte[] recvBuf = new byte[_sampleMsg.Length]; VirtualNetwork network = new VirtualNetwork(); using (var clientStream = new VirtualNetworkStream(network, isServer: false)) using (var serverStream = new VirtualNetworkStream(network, isServer: true)) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { Assert.False(client.IsAuthenticated); Assert.False(server.IsAuthenticated); Task[] auth = new Task[2]; auth[0] = client.AuthenticateAsClientAsync(); auth[1] = server.AuthenticateAsServerAsync(); bool finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Handshake completed in the allotted time"); auth[0] = client.WriteAsync(_sampleMsg, 0, _sampleMsg.Length); auth[1] = server.ReadAsync(recvBuf, 0, _sampleMsg.Length); finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Send/receive completed in the allotted time"); Assert.True(_sampleMsg.SequenceEqual(recvBuf)); auth[0] = client.WriteAsync(_sampleMsg, 0, _sampleMsg.Length); auth[1] = server.ReadAsync(recvBuf, 0, _sampleMsg.Length); finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Send/receive completed in the allotted time"); Assert.True(_sampleMsg.SequenceEqual(recvBuf)); } }
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Factory.FromAsync(server.BeginAuthenticateAsServer, server.EndAuthenticateAsServer, null);
protected override IAsyncResult OnBegin(Stream stream, AsyncCallback callback) { this.negotiateStream = new NegotiateStream(stream); return(this.negotiateStream.BeginAuthenticateAsServer(this.acceptor.parent.ServerCredential, this.acceptor.parent.ProtectionLevel, TokenImpersonationLevel.Identification, callback, this)); }
/// <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 is null) { additionalChallenge = new byte[] { } } ; if (additionalChallenge.Length > short.MaxValue) { throw new ArgumentOutOfRangeException("additionalChallenge", "Must be less than 32767 bytes"); } using (NegotiateStream 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); } }
public static int Main(string[] args) { if (args.Length < 6) { Help(); return(-1); } int port; if (!Int32.TryParse(args[0], out port)) { Console.WriteLine("Got bad port number for arg 1"); return(-2); } Guid authGuid; if (!Guid.TryParse(args[1], out authGuid)) { Console.WriteLine("Got bad auth guid for arg 2"); return(-3); } var addrs = Dns.GetHostAddresses(args[2]); if (addrs.Length == 0) { Console.WriteLine("Cannot connect back to VisualStudio machine"); return(-4); } string curDir = args[3]; string projectDir = args[4]; string exe = args[5]; if (!File.Exists(exe)) { Console.WriteLine("{0} does not exist, please install the Python interpreter or update the project debug settings to point at the correct interpreter.", exe); } Guid launchId = Guid.NewGuid(); ManualResetEvent launchEvent = new ManualResetEvent(false); #pragma warning disable 618 // Handle is obsolete but we need it. string msVsMonArgs = "/__dbgautolaunch 0x" + launchEvent.Handle.ToString("X") + " 0x" + Process.GetCurrentProcess().Id.ToString("X") + " /name " + launchId.ToString() + " /timeout:600"; #pragma warning restore 618 Process msvsmonProc; try { var procStartInfo = new ProcessStartInfo( Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "msvsmon.exe"), msVsMonArgs); procStartInfo.UseShellExecute = false; msvsmonProc = Process.Start(procStartInfo); } catch (Exception e) { Console.WriteLine("Failed to start " + Path.Combine(Assembly.GetExecutingAssembly().Location, "msvsmon.exe")); Console.WriteLine(e); return(-7); } var processEvent = new ManualResetEvent(true); processEvent.SafeWaitHandle = new SafeWaitHandle(msvsmonProc.Handle, false); if (WaitHandle.WaitAny(new[] { launchEvent, processEvent }) != 0) { Console.WriteLine("Failed to initialize msvsmon"); return(-5); } try { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)) { socket.Blocking = true; socket.Connect(new IPEndPoint(addrs[0], port)); var secureStream = new NegotiateStream(new NetworkStream(socket, false), true); secureStream.AuthenticateAsClient(); var writer = new StreamWriter(secureStream); writer.WriteLine(authGuid.ToString()); writer.WriteLine(exe); writer.WriteLine(curDir); writer.WriteLine(projectDir); writer.WriteLine(String.Join(" ", args, 6, args.Length - 6)); writer.WriteLine(launchId + "@" + Environment.MachineName); writer.Flush(); var reader = new StreamReader(secureStream); var procId = reader.ReadLine(); var processId = Int32.Parse(procId); if (processId != 0) { var debuggee = Process.GetProcessById(processId); debuggee.WaitForExit(); msvsmonProc.WaitForExit(); } else { int errorLen = Int32.Parse(reader.ReadLine()); char[] buffer = new char[errorLen]; int bytesRead = reader.Read(buffer, 0, buffer.Length); Console.WriteLine("failed to get process to debug: {0}", new string(buffer, 0, bytesRead)); return(-6); } } } catch (SocketException) { Console.WriteLine("Failed to connect back to Visual Studio process."); msvsmonProc.Kill(); return(-8); } GC.KeepAlive(launchEvent); GC.KeepAlive(msvsmonProc); return(0); }
public static void Main() { NegotiateStream negotiateStream = null; try { // Set the TcpListener on port 13000. Int32 port = 13000; IPAddress localAddr = IPAddress.Loopback; // TcpListener server = new TcpListener(port); TcpListener server = new TcpListener(localAddr, port); // Start listening for client requests. server.Start(); // Buffer for reading data Byte[] bytes = new Byte[256]; String data = null; // Enter the listening loop. while (true) { Console.Write("Waiting for a connection... "); // Perform a blocking call to accept requests. // You could also user server.AcceptSocket() here. TcpClient client = server.AcceptTcpClient(); Console.WriteLine("Connected!"); data = null; // Get a stream object for reading and writing // Wrap it in a NegotiateStream. negotiateStream = new NegotiateStream(client.GetStream()); negotiateStream.AuthenticateAsServer(); if (negotiateStream.IsAuthenticated) { Console.WriteLine( "IsAuthenticated: {0}", negotiateStream.IsAuthenticated); Console.WriteLine( "IsMutuallyAuthenticated: {0}", negotiateStream.IsMutuallyAuthenticated); Console.WriteLine( "IsEncrypted: {0}", negotiateStream.IsEncrypted); Console.WriteLine( "IsSigned: {0}", negotiateStream.IsSigned); Console.WriteLine( "IsServer: {0}", negotiateStream.IsServer); IIdentity remoteIdentity = negotiateStream.RemoteIdentity; Console.WriteLine( "Client identity: {0}", remoteIdentity.Name); Console.WriteLine( "Authentication Type: {0}", remoteIdentity.AuthenticationType); } int i; // Loop to receive all the data sent by the client. while ( (i = negotiateStream.Read(bytes, 0, bytes.Length)) != 0) { // Translate data bytes to a string. // The encoding used is application specific. data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); Console.WriteLine("Received: {0}", data); // Process the data sent by the client. data = data.ToUpper( System.Globalization.CultureInfo.CurrentCulture); byte[] msg = System.Text.Encoding.ASCII.GetBytes(data); // Send back a response. negotiateStream.Write(msg, 0, msg.Length); Console.WriteLine("Sent: {0}", data); } } } catch (AuthenticationException ex) { Console.WriteLine(ex.Message); } catch (SocketException ex) { Console.WriteLine(ex.Message); } catch (IOException ex) { Console.WriteLine(ex.Message); } finally { if (negotiateStream != null) { negotiateStream.Close(); } } Console.WriteLine("\nHit enter to continue..."); Console.Read(); }
internal static bool TryOpenChannel(NetworkPath netPath, int timeoutInMs, out TcpClientChannel channel, out NetworkTransportException networkEx) { channel = null; networkEx = null; Exception ex = null; Socket socket = null; Stream stream = null; NegotiateStream negotiateStream = null; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { socket = new Socket(netPath.TargetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); if (netPath.Purpose == NetworkPath.ConnectionPurpose.Seeding) { socket.ReceiveBufferSize = Parameters.CurrentValues.SeedingNetworkTransferSize; socket.SendBufferSize = Parameters.CurrentValues.SeedingNetworkTransferSize; } else { socket.ReceiveBufferSize = Parameters.CurrentValues.LogCopyNetworkTransferSize; socket.SendBufferSize = Parameters.CurrentValues.LogCopyNetworkTransferSize; } if (netPath.HasSourceEndpoint()) { socket.Bind(netPath.SourceEndPoint); } TcpClientChannel.ConnectAbandon connectAbandon = new TcpClientChannel.ConnectAbandon(socket); IAsyncResult asyncResult = socket.BeginConnect(netPath.TargetEndPoint.Address, netPath.TargetEndPoint.Port, null, connectAbandon); if (!asyncResult.AsyncWaitHandle.WaitOne(timeoutInMs, false)) { socket = null; connectAbandon.Cancel(asyncResult); TcpChannel.ThrowTimeoutException(netPath.TargetNodeName, Strings.NetworkConnectionTimeout(timeoutInMs / 1000)); } socket.EndConnect(asyncResult); long elapsedMilliseconds = stopwatch.ElapsedMilliseconds; ExTraceGlobals.TcpClientTracer.TraceDebug <long>(0L, "Connection took {0}ms", elapsedMilliseconds); socket.LingerState = new LingerOption(true, 0); if (!netPath.UseSocketStream || Parameters.CurrentValues.DisableSocketStream) { stream = new NetworkStream(socket, false); } else { stream = new SocketStream(socket, netPath.SocketStreamBufferPool, netPath.SocketStreamAsyncArgPool, netPath.SocketStreamPerfCounters); } negotiateStream = new NegotiateStream(stream, false); stream = null; elapsedMilliseconds = stopwatch.ElapsedMilliseconds; if (elapsedMilliseconds >= (long)timeoutInMs) { TcpChannel.ThrowTimeoutException(netPath.TargetNodeName, Strings.NetworkConnectionTimeout(timeoutInMs / 1000)); } int num = timeoutInMs - (int)elapsedMilliseconds; negotiateStream.WriteTimeout = num; negotiateStream.ReadTimeout = num; TcpClientChannel.AuthAbandon authAbandon = new TcpClientChannel.AuthAbandon(socket, negotiateStream); string targetName; if (netPath.UseNullSpn) { targetName = ""; } else { targetName = "HOST/" + netPath.TargetNodeName; } bool encrypt = netPath.Encrypt; ProtectionLevel protectionLevel; if (encrypt) { protectionLevel = ProtectionLevel.EncryptAndSign; } else if (Parameters.CurrentValues.DisableNetworkSigning) { protectionLevel = ProtectionLevel.None; } else { protectionLevel = ProtectionLevel.Sign; } asyncResult = negotiateStream.BeginAuthenticateAsClient(CredentialCache.DefaultNetworkCredentials, targetName, protectionLevel, TokenImpersonationLevel.Identification, null, authAbandon); if (!asyncResult.AsyncWaitHandle.WaitOne(num, false)) { negotiateStream = null; socket = null; authAbandon.Abandon(asyncResult); TcpChannel.ThrowTimeoutException(netPath.TargetNodeName, Strings.NetworkConnectionTimeout(timeoutInMs / 1000)); } negotiateStream.EndAuthenticateAsClient(asyncResult); bool flag = false; if (!negotiateStream.IsAuthenticated) { flag = true; } else if (protectionLevel != ProtectionLevel.None && !negotiateStream.IsMutuallyAuthenticated) { if (netPath.IgnoreMutualAuth || MachineName.Comparer.Equals(netPath.TargetNodeName, Environment.MachineName)) { ExTraceGlobals.TcpClientTracer.TraceDebug(0L, "Ignoring mutual auth since we are local"); } else { flag = true; } } if (!flag && encrypt && !negotiateStream.IsEncrypted) { ExTraceGlobals.TcpClientTracer.TraceError(0L, "Encryption requested, but could not be negotiated"); flag = true; } if (flag) { ExTraceGlobals.TcpClientTracer.TraceError <bool, bool, bool>(0L, "Security Negotiation failed. Auth={0},MAuth={1},Encrypt={2}", negotiateStream.IsAuthenticated, negotiateStream.IsMutuallyAuthenticated, negotiateStream.IsEncrypted); throw new NetworkCommunicationException(netPath.TargetNodeName, Strings.NetworkSecurityFailed); } ExTraceGlobals.TcpClientTracer.TraceDebug <long, bool, ProtectionLevel>(0L, "Authenticated Connection took {0}ms. Encrypt={1} ProtRequested={2}", stopwatch.ElapsedMilliseconds, negotiateStream.IsEncrypted, protectionLevel); channel = new TcpClientChannel(netPath.TargetNodeName, socket, negotiateStream, timeoutInMs); return(true); } catch (SocketException ex2) { ex = ex2; } catch (IOException ex3) { ex = ex3; } catch (AuthenticationException ex4) { ex = ex4; } catch (NetworkTransportException ex5) { ex = ex5; } finally { if (channel == null) { if (negotiateStream != null) { negotiateStream.Dispose(); } else if (stream != null) { stream.Dispose(); } if (socket != null) { socket.Close(); } } else { ReplayCrimsonEvents.NetworkConnectionSuccess.Log <string, IPEndPoint, IPEndPoint>(netPath.TargetNodeName, netPath.TargetEndPoint, channel.LocalEndpoint); } } ExTraceGlobals.TcpClientTracer.TraceError <Exception>(0L, "TryOpenChannel failed. Ex={0}", ex); ReplayCrimsonEvents.NetworkConnectionFailure.Log <string, IPEndPoint, IPEndPoint, string>(netPath.TargetNodeName, netPath.TargetEndPoint, netPath.SourceEndPoint, ex.ToString()); if (ex is NetworkTransportException) { networkEx = (NetworkTransportException)ex; } else { networkEx = new NetworkCommunicationException(netPath.TargetNodeName, ex.Message, ex); } return(false); }
public AuthAbandon(Socket socket, NegotiateStream stream) { this.m_connection = socket; this.m_authStream = stream; }
protected TcpClientChannel(string serverNodeName, Socket channel, NegotiateStream s, int timeout) : base(channel, s, timeout) { base.PartnerNodeName = serverNodeName; }
private async Task VerifyAuthentication(NetworkCredential credential) { string serverName = Configuration.Security.NegotiateServer.Host; int port = Configuration.Security.NegotiateServer.Port; string serverSPN = "HOST/" + serverName; bool isLocalhost = await IsLocalHost(serverName); string expectedAuthenticationType = "Kerberos"; bool mutualAuthenitcated = true; if (credential == CredentialCache.DefaultNetworkCredentials && isLocalhost) { expectedAuthenticationType = "NTLM"; } else if (credential != CredentialCache.DefaultNetworkCredentials && (string.IsNullOrEmpty(credential.UserName) || string.IsNullOrEmpty(credential.Password))) { // Anonymous authentication. expectedAuthenticationType = "NTLM"; mutualAuthenitcated = false; } using (var client = new TcpClient()) { await client.ConnectAsync(serverName, port); NetworkStream clientStream = client.GetStream(); using (var auth = new NegotiateStream(clientStream, leaveInnerStreamOpen:false)) { await auth.AuthenticateAsClientAsync( credential, serverSPN, ProtectionLevel.EncryptAndSign, System.Security.Principal.TokenImpersonationLevel.Identification); Assert.Equal(expectedAuthenticationType, auth.RemoteIdentity.AuthenticationType); Assert.Equal(serverSPN, auth.RemoteIdentity.Name); Assert.Equal(true, auth.IsAuthenticated); Assert.Equal(true, auth.IsEncrypted); Assert.Equal(mutualAuthenitcated, auth.IsMutuallyAuthenticated); Assert.Equal(true, auth.IsSigned); // Send a message to the server. Encode the test data into a byte array. byte[] message = Encoding.UTF8.GetBytes("Hello from the client."); await auth.WriteAsync(message, 0, message.Length); } } }
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Run(() => server.AuthenticateAsServerAsync());
/// <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 is null) { additionalChallenge = new byte[] { } } ; if (additionalChallenge.Length > short.MaxValue) { throw new ArgumentOutOfRangeException("additionalChallenge", "Must be less than 32767 bytes"); } using (NegotiateStream 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); } } } }
public void NegotiateStream_StreamToStream_FlushAsync_Propagated() { VirtualNetwork network = new VirtualNetwork(); using (var stream = new VirtualNetworkStream(network, isServer: false)) using (var negotiateStream = new NegotiateStream(stream)) { Task task = negotiateStream.FlushAsync(); Assert.False(task.IsCompleted); stream.CompleteAsyncFlush(); Assert.True(task.IsCompleted); } }
protected abstract Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default);
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Run(() => server.AuthenticateAsServer(null));
protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => stream.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Run(() => server.AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification));
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, targetName, ProtectionLevel.None, TokenImpersonationLevel.Identification);
protected abstract Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName);
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => server.AuthenticateAsServerAsync(CredentialCache.DefaultNetworkCredentials, ProtectionLevel.None, TokenImpersonationLevel.Identification);
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, targetName);
protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, buffer, offset, count, null);
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Factory.FromAsync(client.BeginAuthenticateAsClient, client.EndAuthenticateAsClient, credential, targetName, null);
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Factory.FromAsync(server.BeginAuthenticateAsServer, server.EndAuthenticateAsServer, (ExtendedProtectionPolicy)null, null);
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Factory.FromAsync( (callback, state) => client.BeginAuthenticateAsClient(credential, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, callback, state), client.EndAuthenticateAsClient, null);
protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Factory.FromAsync( (callback, state) => server.BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, callback, state), server.EndAuthenticateAsServer, null);
protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Run(() => client.AuthenticateAsClient(credential, targetName));
protected override Task <int> ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => Task.FromResult(stream.Read(buffer, offset, count));
public void NegotiateStream_StreamToStream_Authentication_EmptyCredentials_Fails() { string targetName = "testTargetName"; // Ensure there is no confusion between DefaultCredentials / DefaultNetworkCredentials and a // NetworkCredential object with empty user, password and domain. NetworkCredential emptyNetworkCredential = new NetworkCredential("", "", ""); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultCredentials); Assert.NotEqual(emptyNetworkCredential, CredentialCache.DefaultNetworkCredentials); VirtualNetwork network = new VirtualNetwork(); using (var clientStream = new VirtualNetworkStream(network, isServer: false)) using (var serverStream = new VirtualNetworkStream(network, isServer: true)) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { Assert.False(client.IsAuthenticated); Assert.False(server.IsAuthenticated); Task[] auth = new Task[2]; auth[0] = client.AuthenticateAsClientAsync(emptyNetworkCredential, targetName); auth[1] = server.AuthenticateAsServerAsync(); bool finished = Task.WaitAll(auth, TestConfiguration.PassingTestTimeoutMilliseconds); Assert.True(finished, "Handshake completed in the allotted time"); // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); Assert.Equal(true, client.IsEncrypted); Assert.Equal(false, client.IsMutuallyAuthenticated); Assert.Equal(false, client.IsServer); Assert.Equal(true, client.IsSigned); Assert.Equal(false, client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; Assert.Equal("NTLM", serverIdentity.AuthenticationType); Assert.Equal(true, serverIdentity.IsAuthenticated); Assert.Equal(targetName, serverIdentity.Name); // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); Assert.Equal(true, server.IsEncrypted); Assert.Equal(false, server.IsMutuallyAuthenticated); Assert.Equal(true, server.IsServer); Assert.Equal(true, server.IsSigned); Assert.Equal(false, server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; Assert.Equal("NTLM", clientIdentity.AuthenticationType); // TODO #5241: Behavior difference: Assert.Equal(false, clientIdentity.IsAuthenticated); // On .Net Desktop: Assert.Equal(true, clientIdentity.IsAuthenticated); IdentityValidator.AssertHasName(clientIdentity, @"NT AUTHORITY\ANONYMOUS LOGON"); } }
protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) { stream.Write(buffer, offset, count); return(Task.CompletedTask); }
protected override async Task <IDuplexPipe> ConnectPipelineAsync(int sendMaxMessageSize, int receiveMaxMessageSize, CancellationToken cancellationToken) { // TODO: Implement cancellationToken somehow, but how?. ConnectAsync and AuthenticateAsClientAsync don't accept a CancellationToken. IDuplexPipe?connection; var endPoint = this.CreateNetEndPoint(); Stream?authenticatedStream = null; Stream?workStream = null; var sendOptions = new PipeOptions( pauseWriterThreshold: sendMaxMessageSize * 2, resumeWriterThreshold: sendMaxMessageSize, readerScheduler: PipeScheduler.ThreadPool, useSynchronizationContext: false); var receiveOptions = new PipeOptions( pauseWriterThreshold: receiveMaxMessageSize * 2, resumeWriterThreshold: receiveMaxMessageSize, readerScheduler: PipeScheduler.Inline, useSynchronizationContext: false); try { Socket?socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { SetRecommendedClientOptions(socket); string sslHost; switch (endPoint) { case IPEndPoint ipEndPoint: #if PLAT_CONNECT_CANCELLATION await socket.ConnectAsync(ipEndPoint.Address, ipEndPoint.Port, cancellationToken).ContextFree(); #else await socket.ConnectAsync(ipEndPoint.Address, ipEndPoint.Port).ContextFree(); #endif sslHost = ipEndPoint.Address.ToString(); break; case DnsEndPoint dnsEndPoint: #if PLAT_CONNECT_CANCELLATION await socket.ConnectAsync(dnsEndPoint.Host, dnsEndPoint.Port, cancellationToken).ContextFree(); #else await socket.ConnectAsync(dnsEndPoint.Host, dnsEndPoint.Port).ContextFree(); #endif sslHost = dnsEndPoint.Host; break; default: throw new NotSupportedException($"Unsupported end point '{endPoint}',"); } workStream = new NetworkStream(socket, true); socket = null; // Prevent closing, NetworkStream has taken ownership var selectedAuthentication = await this.GetAuthenticationOptionsAsync(workStream, cancellationToken).ContextFree(); if (selectedAuthentication is SslClientOptions sslOptions) { var sslStream = new SslStream(workStream, false, sslOptions.RemoteCertificateValidationCallback, sslOptions.LocalCertificateSelectionCallback, sslOptions.EncryptionPolicy); workStream = authenticatedStream = sslStream; #if PLAT_CONNECT_CANCELLATION var authOptions = new SslClientAuthenticationOptions() { TargetHost = sslHost, ClientCertificates = sslOptions.ClientCertificates, EnabledSslProtocols = sslOptions.EnabledSslProtocols, CertificateRevocationCheckMode = sslOptions.CertificateRevocationCheckMode }; await sslStream.AuthenticateAsClientAsync(authOptions, cancellationToken).ContextFree(); #else await sslStream.AuthenticateAsClientAsync(sslHost, sslOptions.ClientCertificates, sslOptions.EnabledSslProtocols, sslOptions.CertificateRevocationCheckMode != X509RevocationMode.NoCheck).ContextFree(); #endif } else if (selectedAuthentication is NegotiateClientOptions negotiateOptions) { var negotiateStream = new NegotiateStream(workStream, false); workStream = authenticatedStream = negotiateStream; await negotiateStream.AuthenticateAsClientAsync( negotiateOptions !.Credential ?? CredentialCache.DefaultNetworkCredentials, negotiateOptions.TargetName ?? "").ContextFree(); } else if (selectedAuthentication is AnonymousAuthenticationClientOptions) { authenticatedStream = workStream; } else { throw new NotSupportedException("Authentication options not supported."); } connection = new StreamDuplexPipe(authenticatedStream);//, sendOptions, receiveOptions); } finally { socket?.Dispose(); } this.authenticatedStream = authenticatedStream as AuthenticatedStream; workStream = null; return(connection); } finally { workStream?.Dispose(); } }
public void NegotiateStream_StreamToStream_Flush_Propagated() { VirtualNetwork network = new VirtualNetwork(); using (var stream = new VirtualNetworkStream(network, isServer: false)) using (var negotiateStream = new NegotiateStream(stream)) { Assert.False(stream.HasBeenSyncFlushed); negotiateStream.Flush(); Assert.True(stream.HasBeenSyncFlushed); } }