예제 #1
0
        protected void ClientThreadEntry()
        {
            try
            {
                TcpListener listenerV4 = new TcpListener(IPAddress.Any, PortNumber);
                TcpListener listenerV6 = new TcpListener(IPAddress.IPv6Any, PortNumber);
                listenerV4.Start(10);
                listenerV6.Start(10);

                // Start listening for connections.

                Log.WriteLine("Listening for TCP connections on port " + PortNumber + "...\n", Severity.Debug);
                while (!Stopping)
                {
                    TcpClient ClientRequest;
                    try
                    {
                        if (listenerV4.Pending())
                        {
                            ClientRequest = listenerV4.AcceptTcpClient();
                        }
                        else if (listenerV6.Pending())
                        {
                            ClientRequest = listenerV6.AcceptTcpClient();
                        }
                        else
                        {
                            Thread.Sleep(250); continue;
                        }

                        Log.WriteLine("TCP Client accepted.\n", Severity.Debug);

                        NetworkStream = new SslStream(ClientRequest.GetStream(), false);
                        NetworkStream.AuthenticateAsServer(GetRemoteDesktopCertificate(), false, SslProtocols.Tls12, true);
                        if (!NetworkStream.IsAuthenticated)
                        {
                            NetworkStream = null;
                            Log.WriteLine("Unable to authenticate incoming connection from " + ((IPEndPoint)ClientRequest.Client.RemoteEndPoint).Address.ToString() + ".", Severity.Warning);
                            ClientRequest.Close();
                            continue;
                        }
                        if (!NetworkStream.IsEncrypted)
                        {
                            NetworkStream = null;
                            Log.WriteLine("Unable to encrypt incoming connection from " + ((IPEndPoint)ClientRequest.Client.RemoteEndPoint).Address.ToString() + ".", Severity.Warning);
                            ClientRequest.Close();
                            continue;
                        }
                        // Display the properties and settings for the authenticated stream.
                        Log.WriteLine("Authentication successful [host].\n", Severity.Debug);
#if DEBUG
                        DisplaySecurityLevel(Log, NetworkStream, Severity.Debug);
                        DisplaySecurityServices(Log, NetworkStream, Severity.Debug);
                        DisplayCertificateInformation(Log, NetworkStream, Severity.Debug);
                        DisplayStreamProperties(Log, NetworkStream, Severity.Debug);
#endif

                        // Transmit our version info as a hello.
                        System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
                        FileVersionInfo            fvi      = FileVersionInfo.GetVersionInfo(assembly.Location);
                        string version = fvi.FileVersion;
                        string XmlMsg  = "<Portal-Version Core-Library=\"" + fvi.FileVersion + "\" />";
                        byte[] RawMsg  = Encoding.Unicode.GetBytes(XmlMsg);
                        if (NetworkStream != null)
                        {
                            SendMessage(NetworkStream, RawMsg);
                        }
                    }
                    catch (Win32Exception ex)
                    {
                        Log.WriteLine("Exception accepting new connection: " + ex.ToString(), Severity.Debug);
                        if ((uint)ex.ErrorCode == 0x80004005)
                        {
                            // The credentials supplied to the pacakage were not recognized.
                            // This error comes up rom NetworkStream.AuthenticateAsServer() or GetRemoteDesktopCertificate() for localhost slave when there is no administrative access.
                            Log.WriteLine("This exception usually indicates that administrative access was required but not present.", Severity.Debug);
                        }
                        continue;
                    }
                    catch (Exception ex)
                    {
                        // Note: "The credentials supplied to the package were not recognized" is probably a sign that the code doesn't have Administrator access and can't access the subsystem or certificate it needs.
                        Log.WriteLine("Exception accepting new connection: " + ex.ToString(), Severity.Debug);
                        continue;
                    }

                    try
                    {
                        ServiceConnection(NetworkStream, ClientRequest, ClientRequest.GetStream());
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLine("Exception servicing connection: " + ex.ToString(), Severity.Debug);
                    }

                    lock (ProcessLock)
                    {
                        // Setting ConnectedProcess to null before accepting a new connection is essential to security.  It prevents access to the console without a new authentication and Connect-Terminal.
                        ConnectedProcess = null;

                        // If we aren't attached to a console, FreeConsole() would return ERROR_INVALID_PARAMETER.
                        ConsoleApi.FreeConsole();

                        Log.WriteLine("Closing connection in SlaveCore (if it isn't already).", Severity.Debug);
                        if (ClientRequest != null)
                        {
                            ClientRequest.Dispose(); ClientRequest = null;
                        }

                        if (Conin != null)
                        {
                            Conin.Dispose(); Conin = null;
                        }
                        if (CT != null)
                        {
                            CT.Dispose(); CT = null;
                        }
                    }
                }

                lock (ProcessLock)
                {
                    ConnectedProcess = null;
                    foreach (var kvp in Processes)
                    {
                        kvp.Value.Dispose();
                    }
                    Processes.Clear();
                }
            }
            catch (Exception e)
            {
                Log.WriteLine("Error: " + e.ToString(), Severity.Error);
            }
        }