Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion libdd-common/src/connector/conn_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?,
),
})
}
Expand Down Expand Up @@ -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::<u64>()
);

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");
}
}
14 changes: 14 additions & 0 deletions libdd-common/src/connector/named_pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down
Loading