diff --git a/libdd-common/src/connector/conn_stream.rs b/libdd-common/src/connector/conn_stream.rs index 6fdedfdd56..03e222c720 100644 --- a/libdd-common/src/connector/conn_stream.rs +++ b/libdd-common/src/connector/conn_stream.rs @@ -63,7 +63,9 @@ impl ConnStream { let path = super::named_pipe::named_pipe_path_from_uri(&uri)?; Ok(ConnStream::NamedPipe { transport: TokioIo::new( - tokio::net::windows::named_pipe::ClientOptions::new().open(path)?, + tokio::net::windows::named_pipe::ClientOptions::new() + .security_qos_flags(super::named_pipe::ANONYMOUS_IMPERSONATION_QOS) + .open(path)?, ), }) } @@ -190,3 +192,43 @@ impl hyper::rt::Write for ConnStream { } } } + +#[cfg(all(test, windows))] +mod windows_named_pipe_tests { + use super::ConnStream; + use crate::connector::named_pipe::named_pipe_path_to_uri; + use std::path::Path; + use tokio::net::windows::named_pipe::ServerOptions; + + /// Verifies that `from_named_pipe_uri` opens a client connection successfully + /// when impersonation is disabled (Anonymous QoS). The server accepting the + /// connection confirms the `SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS` flags + /// produce a usable transport. + #[tokio::test] + async fn from_named_pipe_uri_connects_with_anonymous_qos() { + let pipe_name = format!( + r"\\.\pipe\libdd_common_conn_stream_test_{}_{}", + std::process::id(), + rand::random::() + ); + + let server = ServerOptions::new() + .first_pipe_instance(true) + .create(&pipe_name) + .expect("failed to create named pipe server"); + + let server_task = tokio::spawn(async move { + server.connect().await.expect("server failed to accept"); + }); + + let uri = named_pipe_path_to_uri(Path::new(&pipe_name)).expect("failed to build uri"); + let conn = ConnStream::from_named_pipe_uri(uri).await; + assert!( + conn.is_ok(), + "expected named pipe client to connect with Anonymous QoS: {:?}", + conn.err() + ); + + server_task.await.expect("server task panicked"); + } +} diff --git a/libdd-common/src/connector/named_pipe.rs b/libdd-common/src/connector/named_pipe.rs index ac83b908e9..1f02cecc8d 100644 --- a/libdd-common/src/connector/named_pipe.rs +++ b/libdd-common/src/connector/named_pipe.rs @@ -3,6 +3,20 @@ use std::path::{Path, PathBuf}; +/// Security Quality of Service flags used when opening a Windows named pipe client. +/// +/// We disable impersonation by requesting `SECURITY_ANONYMOUS`, mirroring the +/// dd-trace-dotnet change that sets `TokenImpersonationLevel.Anonymous`. The pipe is +/// only used as a byte transport to the agent, so the server end never needs to +/// identify or impersonate the (potentially privileged) connecting client. Denying +/// impersonation enforces least privilege and prevents a malicious/squatting pipe +/// server from reading the client's identity or acting on its behalf. +/// +/// `SECURITY_ANONYMOUS` has the value `0`; tokio's `ClientOptions::security_qos_flags` +/// automatically ORs in `SECURITY_SQOS_PRESENT`. +#[cfg(windows)] +pub const ANONYMOUS_IMPERSONATION_QOS: u32 = 0; // SECURITY_ANONYMOUS + /// Windows Named Pipe /// https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes ///