From faabc2984acd1449617ef52a5767e1cb2f1f17fb Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 25 Oct 2023 19:22:50 +0200 Subject: [PATCH] =?UTF-8?q?tokio-xmpp:=20Support=20channel=20binding=20on?= =?UTF-8?q?=20TLS=C2=A01.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is defined in RFC 9266, and relies on the Exported Keying Material to be passed to the SASL implementation. --- tokio-xmpp/src/client/simple_client.rs | 31 ++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tokio-xmpp/src/client/simple_client.rs b/tokio-xmpp/src/client/simple_client.rs index 2eef62fb..6d9a0d2c 100644 --- a/tokio-xmpp/src/client/simple_client.rs +++ b/tokio-xmpp/src/client/simple_client.rs @@ -1,5 +1,7 @@ use futures::{sink::SinkExt, Sink, Stream}; use idna; +#[cfg(feature = "tls-native")] +use log::warn; use sasl::common::{ChannelBinding, Credentials}; use std::pin::Pin; use std::str::FromStr; @@ -8,7 +10,7 @@ use tokio::net::TcpStream; #[cfg(feature = "tls-native")] use tokio_native_tls::TlsStream; #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] -use tokio_rustls::client::TlsStream; +use tokio_rustls::{client::TlsStream, rustls::ProtocolVersion}; use tokio_stream::StreamExt; use xmpp_parsers::{ns, Element, Jid}; @@ -62,9 +64,34 @@ impl Client { xmpp_stream::XMPPStream::start(tcp_stream, jid.clone(), ns::JABBER_CLIENT.to_owned()) .await?; + let channel_binding; let xmpp_stream = if xmpp_stream.stream_features.can_starttls() { // TlsStream let tls_stream = starttls(xmpp_stream).await?; + #[cfg(feature = "tls-native")] + { + warn!("tls-native doesn’t support channel binding, please use tls-rust if you want this feature!"); + channel_binding = ChannelBinding::None; + } + #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] + { + let (_, connection) = tls_stream.get_ref(); + match connection.protocol_version() { + // TODO: Add support for TLS 1.2 and earlier. + Some(ProtocolVersion::TLSv1_3) => { + let data = vec![0u8; 32]; + let data = connection.export_keying_material( + data, + b"EXPORTER-Channel-Binding", + None, + )?; + channel_binding = ChannelBinding::TlsExporter(data); + } + _ => { + channel_binding = ChannelBinding::None; + } + } + } // Encrypted XMPPStream xmpp_stream::XMPPStream::start(tls_stream, jid.clone(), ns::JABBER_CLIENT.to_owned()) .await? @@ -75,7 +102,7 @@ impl Client { let creds = Credentials::default() .with_username(username) .with_password(password) - .with_channel_binding(ChannelBinding::None); + .with_channel_binding(channel_binding); // Authenticated (unspecified) stream let stream = auth(xmpp_stream, creds).await?; // Authenticated XMPPStream