From 959f5b463a057a4da546ef87a9e3ef1f7fc920a2 Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Mon, 9 Dec 2024 15:53:41 -0700 Subject: [PATCH] RDP: put the username in the load balancing cookie This doesn't change the behavior of the RDP server in any way, but load balancers sitting in front of the server may use the cookie to alter how they route connections. Note that this is the default behavior of IronRDP when using username/password authentication, but we must explicitly enable it because we use smart card authentication instead. --- lib/srv/desktop/rdp/rdpclient/client.go | 7 +++++++ lib/srv/desktop/rdp/rdpclient/src/client.rs | 7 ++++++- lib/srv/desktop/rdp/rdpclient/src/lib.rs | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 99d0cdb0930bd..4f9c1a4f368eb 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -291,6 +291,12 @@ func (c *Client) startRustRDP(ctx context.Context) error { return trace.Wrap(err) } + // [username] need only be valid for the duration of + // C.client_run. It is copied on the Rust side and + // thus can be freed here. + username := C.CString(c.username) + defer C.free(unsafe.Pointer(username)) + // [addr] need only be valid for the duration of // C.client_run. It is copied on the Rust side and // thus can be freed here. @@ -328,6 +334,7 @@ func (c *Client) startRustRDP(ctx context.Context) error { C.CGOConnectParams{ ad: C.bool(c.cfg.AD), nla: C.bool(c.cfg.NLA), + go_username: username, go_addr: addr, go_computer_name: computerName, go_kdc_addr: kdcAddr, diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index d4e010c8e1fa9..3dae0fc453b59 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -44,6 +44,7 @@ use ironrdp_pdu::input::fast_path::{ }; use ironrdp_pdu::input::mouse::PointerFlags; use ironrdp_pdu::input::{InputEventError, MousePdu}; +use ironrdp_pdu::nego::NegoRequestData; use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; use ironrdp_pdu::rdp::client_info::PerformanceFlags; use ironrdp_pdu::rdp::RdpError; @@ -1442,8 +1443,11 @@ fn create_config(params: &ConnectParams, pin: String) -> Config { platform: MajorPlatformType::UNSPECIFIED, no_server_pointer: false, autologon: true, - request_data: None, pointer_software_rendering: false, + // Send the username in the request cookie, which is sent in the initial connection request. + // The RDP server ignores this value, but load balancers sitting in front of the server + // can use it to implement persistence. + request_data: Some(NegoRequestData::cookie(params.username.clone())), performance_flags: PerformanceFlags::default() | PerformanceFlags::DISABLE_CURSOR_SHADOW // this is required for pointer to work correctly in Windows 2019 | if !params.show_desktop_wallpaper { @@ -1457,6 +1461,7 @@ fn create_config(params: &ConnectParams, pin: String) -> Config { #[derive(Debug)] pub struct ConnectParams { + pub username: String, pub addr: String, pub kdc_addr: Option, pub computer_name: Option, diff --git a/lib/srv/desktop/rdp/rdpclient/src/lib.rs b/lib/srv/desktop/rdp/rdpclient/src/lib.rs index 2a7bb6b8cd60d..01a7332fff27a 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/lib.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/lib.rs @@ -88,6 +88,7 @@ pub unsafe extern "C" fn free_string(ptr: *mut c_char) { pub unsafe extern "C" fn client_run(cgo_handle: CgoHandle, params: CGOConnectParams) -> CGOResult { trace!("client_run"); // Convert from C to Rust types. + let username = from_c_string(params.go_username); let addr = from_c_string(params.go_addr); let cert_der = from_go_array(params.cert_der, params.cert_der_len); let key_der = from_go_array(params.key_der, params.key_der_len); @@ -107,6 +108,7 @@ pub unsafe extern "C" fn client_run(cgo_handle: CgoHandle, params: CGOConnectPar ConnectParams { ad: params.ad, nla: params.nla, + username, addr, computer_name, cert_der, @@ -476,6 +478,7 @@ pub unsafe extern "C" fn client_write_screen_resize( pub struct CGOConnectParams { ad: bool, nla: bool, + go_username: *const c_char, go_addr: *const c_char, go_domain: *const c_char, go_kdc_addr: *const c_char,