Skip to content

Commit 8f76260

Browse files
authored
feat(tls): expose negotiated TLS version and cipher suite (#1384)
Adds a backend-neutral way to query the TLS parameters negotiated for an established ironrdp-tls::TlsStream, enabling downstream diagnostic tooling to report the negotiated protocol version and cipher suite alongside the existing certificate information.
1 parent d3705af commit 8f76260

4 files changed

Lines changed: 36 additions & 1 deletion

File tree

crates/ironrdp-tls/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,21 @@ compile_error!("a TLS backend must be selected by enabling a single feature out
2323

2424
// The whole public API of this crate.
2525
#[cfg(any(feature = "stub", feature = "native-tls", feature = "rustls"))]
26-
pub use impl_::{TlsStream, upgrade};
26+
pub use impl_::{TlsStream, negotiated, upgrade};
27+
28+
/// TLS parameters negotiated during the handshake, to the extent the active
29+
/// backend exposes them.
30+
///
31+
/// The `rustls` backend reports both fields. The `native-tls` and `stub`
32+
/// backends cannot introspect the negotiated parameters, so both are `None`
33+
/// there.
34+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
35+
pub struct NegotiatedTls {
36+
/// Negotiated protocol version, e.g. `"TLSv1_3"`.
37+
pub version: Option<String>,
38+
/// Negotiated cipher suite, e.g. `"TLS13_AES_256_GCM_SHA384"`.
39+
pub cipher_suite: Option<String>,
40+
}
2741

2842
pub fn extract_tls_server_public_key(cert: &x509_cert::Certificate) -> Option<&[u8]> {
2943
cert.tbs_certificate

crates/ironrdp-tls/src/native_tls.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ where
3939

4040
Ok((tls_stream, tls_cert))
4141
}
42+
43+
/// The `native-tls` backend does not expose the negotiated version or cipher.
44+
pub fn negotiated<S>(_stream: &TlsStream<S>) -> crate::NegotiatedTls {
45+
crate::NegotiatedTls::default()
46+
}

crates/ironrdp-tls/src/rustls.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ where
5151
Ok((tls_stream, tls_cert))
5252
}
5353

54+
/// Report the TLS version and cipher suite negotiated for `stream`.
55+
pub fn negotiated<S>(stream: &TlsStream<S>) -> crate::NegotiatedTls {
56+
let (_, connection) = stream.get_ref();
57+
crate::NegotiatedTls {
58+
version: connection.protocol_version().map(|version| format!("{version:?}")),
59+
cipher_suite: connection
60+
.negotiated_cipher_suite()
61+
.map(|suite| format!("{:?}", suite.suite())),
62+
}
63+
}
64+
5465
mod danger {
5566
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
5667
use tokio_rustls::rustls::{DigitallySignedStruct, Error, SignatureScheme, pki_types};

crates/ironrdp-tls/src/stub.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ where
3737
let _ = (stream, server_name);
3838
Err(io::Error::other("no TLS backend enabled for this build"))
3939
}
40+
41+
/// The stub backend performs no handshake and reports nothing.
42+
pub fn negotiated<S>(_stream: &TlsStream<S>) -> crate::NegotiatedTls {
43+
crate::NegotiatedTls::default()
44+
}

0 commit comments

Comments
 (0)