Пример #1
0
        private void ReceiveThreadEntry()
        {
            try
            {
                while (this.running)
                {
                    if (serverCred == null)
                    {
                        serverCred = Credential.Current();

                        ContextDebugger.WriteLine("[Server] Creating Server Cred");
                    }

                    var request = new ServiceRequest(serverCred, this.serverSocket.Accept(), cancel.Token)
                    {
                        OnReceived = OnReceived
                    };

                    ThreadPool.QueueUserWorkItem(request.Process);
                }
            }
            catch (Exception e)
            {
                OnException(e);
            }
            finally
            {
                this.running = false;

                ContextDebugger.WriteLine("STOPPED");

                this.Stopped?.Invoke();
            }
        }
Пример #2
0
        public void Start()
        {
            if (this.running)
            {
                throw new InvalidOperationException("Already running");
            }

            this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            this.serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            this.serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            this.serverSocket.ExclusiveAddressUse = false;

            this.serverSocket.Bind(new IPEndPoint(IPAddress.Any, port));

            this.serverSocket.Listen(1);

            this.running = true;

            this.receiveThread = new Thread(ReceiveThreadEntry)
            {
                Name = "SSPI Server Receive Thread"
            };

            this.receiveThread.Start();

            ContextDebugger.WriteLine($"[Server] listening on ({port})");
        }
Пример #3
0
        public Server(int port = DefaultPort, Credential serverCred = null)
        {
            ContextDebugger.WriteLine($"[Server] Running As {Thread.CurrentPrincipal.Identity.Name}");

            if (port <= 0)
            {
                port = DefaultPort;
            }

            this.port       = port;
            this.serverCred = serverCred;
        }
Пример #4
0
        private static void Send(string delegatedHost, int delegatePort, string s4uProxyUser)
        {
            var message = new Message(Operation.WhoAmI)
            {
                DelegateHost = delegatedHost,
                DelegatePort = delegatePort,
                S4UToken     = s4uProxyUser
            };

            client.Send(message);

            ContextDebugger.WriteLine($"[Client {Thread.CurrentThread.ManagedThreadId}] send {message.Operation}");
        }
Пример #5
0
        public void Start(bool authenticate = true)
        {
            if (this.running)
            {
                throw new InvalidOperationException("Already running");
            }

            this.socket = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp
                );

            ContextDebugger.WriteLine($"[Client] Resolving host {host}");

            IPAddress ipv4Addr;

            try
            {
                ipv4Addr = Dns.GetHostAddresses(host)
                           .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork);
            }
            catch (Exception ex)
            {
                ContextDebugger.WriteLine("WTF: " + ex);

                ipv4Addr = IPAddress.Loopback;
            }

            ContextDebugger.WriteLine($"[Client] Connecting to {ipv4Addr.ToString()}:{port}");

            this.socket.Connect(ipv4Addr, port);

            this.running = true;

            this.receiveThread = new Thread(ReceiveThreadEntry)
            {
                Name = "SSPI Client Receive Thread"
            };

            this.receiveThread.Start();

            if (authenticate)
            {
                DoInit();
            }
            else
            {
                waitForAuthentication.Set();
            }
        }
        private static void CallDelegatedMethod(Message m)
        {
            switch (m.Operation)
            {
            case Operation.WhoAmI:
                var identity = Thread.CurrentPrincipal.Identity as WindowsIdentity;

                var name = identity?.Name;
                var imp  = identity?.ImpersonationLevel;

                ContextDebugger.WriteLine($"[Delegated] WhoAmI: {name} | {imp}");

                break;
            }
        }
Пример #7
0
        public void Stop()
        {
            if (this.running == false)
            {
                return;
            }

            if (!waitForCompletion.WaitOne(TimeSpan.FromSeconds(10)))
            {
                ContextDebugger.WriteLine("[Client] Wait time out");
            }

            this.socket.Close();
            this.receiveThread.Join();
        }
        private static Credential TryCreateCredential(string[] args)
        {
            var username = TryGet(args, 1, "");
            var password = TryGet(args, 2, "");
            var domain   = TryGet(args, 3, "");

            if (!string.IsNullOrWhiteSpace(username) &&
                !string.IsNullOrWhiteSpace(password) &&
                !string.IsNullOrWhiteSpace(domain))
            {
                ContextDebugger.WriteLine($"Starting as {username}@{domain}: {password}");

                return(new PasswordCredential(domain, username, password));
            }

            return(null);
        }
Пример #9
0
        public Client(string host, int port = DefaultPort, Credential clientCred = null)
        {
            if (port <= 0)
            {
                port = DefaultPort;
            }

            this.host = host.Trim();
            this.port = port;
            this.spn  = $"host/{host}";

            ContextDebugger.WriteLine($"[Client] SPN {spn}");

            this.cred = clientCred ?? Credential.Current();

            this.context = new Shared.SecurityContext(cred, "Negotiate");
        }
        private static void StartServer(int port, string username, string password, string domain)
        {
            Credential serverCred = null;

            if (!string.IsNullOrWhiteSpace(username) &&
                !string.IsNullOrWhiteSpace(password) &&
                !string.IsNullOrWhiteSpace(domain))
            {
                ContextDebugger.WriteLine($"Starting as {username}@{domain}: {password}");

                serverCred = new PasswordCredential(username, password, domain);
            }
            restart = new ManualResetEvent(false);

            if (server != null)
            {
                server.Stop();
            }

            server = null;

            server = new Server(port)
            {
                OnReceived = (m) =>
                {
                    CallDelegatedMethod(m);
                }
            };

            server.OnError += (s, e) =>
            {
                ContextDebugger.WriteLine("[Delegated] Error: " + e.ExceptionObject);
            };

            server.Stopped += () =>
            {
                restart.Set();
            };

            server.Start();

            restart.WaitOne();
        }
Пример #11
0
        private void DoInit()
        {
            var id = Thread.CurrentPrincipal.Identity as WindowsIdentity;

            ContextDebugger.WriteLine($"[Client] Calling as {id?.Name} | {id?.ImpersonationLevel}");

            var serverToken = "";

            if (this.lastServerToken != null && this.lastServerToken.Length > 0)
            {
                serverToken = Convert.ToBase64String(this.lastServerToken);
            }

            ContextDebugger.WriteLine($"[Client] Server Token ({initCounter}) {serverToken}");

            var status = this.context.InitializeSecurityContext(spn, this.lastServerToken, out byte[] outToken);

            ContextDebugger.WriteLine($"[Client] Init status ({initCounter}) {status} SPN {spn} outToken {outToken?.Length ?? 0}");

            initCounter++;

            if (status == ContextStatus.RequiresContinuation || (outToken?.Length ?? 0) > 0)
            {
                ContextDebugger.WriteLine("[Client] token " + Convert.ToBase64String(outToken));

                Message message = new Message(Operation.ClientToken)
                {
                    Token = outToken
                };

                this.SendInternal(message);
            }

            if (status == ContextStatus.Accepted)
            {
                ContextDebugger.WriteLine("[Client] DoInit Status = ok");

                this.lastServerToken = null;
                this.initCounter     = 0;

                waitForAuthentication.Set();
            }
        }
        private static void RelayDelegated(Message m)
        {
            var id = Thread.CurrentPrincipal.Identity as WindowsIdentity;

            ContextDebugger.WriteLine($"[Server] Impersonated {id.Name} | {id.ImpersonationLevel}");

            WindowsImpersonationContext impersonation = null;

            if (!string.IsNullOrWhiteSpace(m.S4UToken))
            {
                ContextDebugger.WriteLine($"[Server] S4U token received {m.S4UToken}");

                id = new WindowsIdentity(m.S4UToken);

                impersonation = id.Impersonate();

                Thread.CurrentPrincipal = new WindowsPrincipal(id);

                ContextDebugger.WriteLine($"[Server] S4U Impersonated {id.Name} | {id.ImpersonationLevel}");
            }

            ContextDebugger.WriteLine($"[Server] Relaying to {m.DelegateHost}:{m.DelegatePort}");

            var delegateClient = new Client(m.DelegateHost, m.DelegatePort);

            delegateClient.Start();

            delegateClient.Send(Message.Deserialize(m.Serialize()));

            Thread.Sleep(1500);

            delegateClient.Stop();

            impersonation?.Dispose();

            ContextDebugger.WriteLine();
            ContextDebugger.WriteLine();
        }
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

            Console.Title = "Delegate";

            while (true)
            {
                try
                {
                    StartServer(
                        TryGet(args, 0, Server.DefaultPort + 100),
                        TryGet(args, 1, ""),
                        TryGet(args, 2, ""),
                        TryGet(args, 3, "")
                        );
                }
                catch (Exception ex)
                {
                    ContextDebugger.WriteLine("[DelegateReceive] Error: " + ex.ToString());
                }
            }
            ;
        }
        private static void StartServer(int port, Credential serverCred)
        {
            server = new Server(port, serverCred)
            {
                OnReceived = (m) =>
                {
                    try
                    {
                        CallDelegatedServer(m);
                    }
                    catch (Exception ex)
                    {
                        ContextDebugger.WriteLine("ReceiveError: " + ex.ToString());
                    }
                }
            };

            server.OnError += (s, e) =>
            {
                ContextDebugger.WriteLine("Error: " + e.ExceptionObject.ToString());
            };

            server.Start();
        }
Пример #15
0
        private void ReadResponseLoop()
        {
            byte[] readBuffer = new byte[4];

            while (this.running)
            {
                if (!this.socket.Connected)
                {
                    ContextDebugger.WriteLine("[Client] socket disconnected");
                    break;
                }

                try
                {
                    if (this.running == false)
                    {
                        break;
                    }

                    this.socket.Receive(readBuffer, 4, SocketFlags.None);

                    var messageLength = Endian.ConvertFromBigEndian(readBuffer);

                    if (readBuffer.Length < messageLength)
                    {
                        readBuffer = new byte[messageLength];
                    }

                    var remaining   = messageLength;
                    var chunkLength = 0;
                    var position    = 0;

                    while (remaining > 0)
                    {
                        chunkLength = this.socket.Receive(readBuffer, position, remaining, SocketFlags.None);
                        remaining  -= chunkLength;
                        position   += chunkLength;
                    }
                }
                catch (SocketException e)
                {
                    if (e.SocketErrorCode == SocketError.ConnectionAborted ||
                        e.SocketErrorCode == SocketError.Interrupted ||
                        e.SocketErrorCode == SocketError.OperationAborted ||
                        e.SocketErrorCode == SocketError.Shutdown ||
                        e.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        // Shutting down.
                        break;
                    }
                    else
                    {
                        throw;
                    }
                }

                Message message = Message.Deserialize(readBuffer);

                ContextDebugger.WriteLine($"[Client] Operation {message.Operation}");

                if (message.Operation == Operation.ServerToken)
                {
                    this.lastServerToken = message.Token;

                    DoInit();
                }
                else
                {
                    this.Received?.Invoke(message);

                    waitForCompletion.Set();
                }
            }
        }
Пример #16
0
        static void Main(string[] args)
        {
            ContextDebugger.WriteLine("");

            ContextDebugger.WriteLine("Usage: ClientApp.exe <host> <host-port> <delegated-host> <delegated-host-port> [<s4u-username>]");
            ContextDebugger.WriteLine("");

            ContextDebugger.WriteLine("Example: ClientApp.exe service.contoso.com 5555 delegated.contoso.com 5655 s4u");
            ContextDebugger.WriteLine("");

            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

            Console.Title = "Client";

            string host          = null;
            string delegatedHost = null;

            int    port         = Client.DefaultPort;
            int    delegatePort = port + 100;
            string s4uProxyUser = null;

            if (args.Length > 0)
            {
                host = args[0];

                if (args.Length <= 1 || !int.TryParse(args[1], out port))
                {
                    port = Client.DefaultPort;
                }

                if (args.Length > 2)
                {
                    delegatedHost = args[2];
                }

                if (args.Length <= 3 || !int.TryParse(args[3], out delegatePort))
                {
                    delegatePort = port + 100;
                }

                if (args.Length > 4)
                {
                    s4uProxyUser = args[4];
                }
            }

            host = host ?? "localhost";

            delegatedHost = delegatedHost ?? host ?? "localhost";

            ContextDebugger.WriteLine($"[Client] Connecting to {host}:{port}");

            var authenticate = string.IsNullOrWhiteSpace(s4uProxyUser);

            ContextDebugger.WriteLine($"Should auto authenticate: {authenticate}; s4u: {s4uProxyUser}");

            for (var i = 0; i < 10; i++)
            {
                ContextDebugger.Write(".");
                new ManualResetEvent(false).WaitOne(TimeSpan.FromSeconds(1));
            }

            ContextDebugger.WriteLine();

            bool disconnected = true;

            var tasks = new List <Task>();

            while (true)
            {
                for (var i = 0; i < 100; i++)
                {
                    if (disconnected)
                    {
                        StartClient(host, port, authenticate);

                        client.Disconnected += () => { disconnected = true; Thread.Sleep(50); };

                        disconnected = false;
                    }

                    if (!disconnected)
                    {
                        Send(delegatedHost, delegatePort, s4uProxyUser);

                        Thread.Sleep(1500);

                        //var task = Task.Run(() =>
                        //{
                        //    Send(delegatedHost, delegatePort);
                        //});

                        //tasks.Add(task);
                    }
                }

                //Task.WhenAll(tasks).Wait();
            }
        }