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(); } }
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})"); }
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; }
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}"); }
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; } }
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); }
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(); }
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(); }
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(); } } }
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(); } }