diff --git a/tokio-xmpp/Cargo.toml b/tokio-xmpp/Cargo.toml index 0656a7c66a2c414f8bcfb0a8d1bda505324685b7..4c4bf4af3cbe57a9a9a37cf9e0dfce0a30514218 100644 --- a/tokio-xmpp/Cargo.toml +++ b/tokio-xmpp/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" bytes = "1" futures = "0.3" log = "0.4" -tokio = { version = "1", features = ["net", "rt", "rt-multi-thread", "macros"] } +tokio = { version = "1", features = ["net", "rt", "rt-multi-thread", "macros", "io-util"] } tokio-stream = { version = "0.1", features = ["sync"] } webpki-roots = { version = "0.26", optional = true } rustls-native-certs = { version = "0.7", optional = true } @@ -40,21 +40,47 @@ ktls = { version = "6", optional = true } env_logger = { version = "0.11", default-features = false, features = ["auto-color", "humantime"] } # this is needed for echo-component example tokio = { version = "1", features = ["signal", "test-util"] } -tokio-xmpp = { path = ".", default-features = false, features = ["insecure-tcp"]} +tokio-xmpp = { path = ".", default-features = false, features = ["rustls-native-certs"]} + +[[example]] +name = "contact_addr" +required-features = ["starttls"] + +[[example]] +name = "download_avatars" +required-features = ["starttls"] + +[[example]] +name = "echo_bot" +required-features = ["starttls"] + +[[example]] +name = "echo_component" +required-features = ["starttls", "insecure-tcp"] + +[[example]] +name = "echo_server" +required-features = ["starttls"] + +[[example]] +name = "keep_connection" +required-features = ["starttls"] [features] -default = ["starttls-rust", "rustls-native-certs", "tls-rust-aws_lc_rs"] +default = ["starttls", "aws_lc_rs", "rustls-native-certs"] starttls = ["dns"] -tls-rust = ["tokio-rustls"] -tls-rust-aws_lc_rs = ["tokio-rustls?/aws_lc_rs"] -tls-rust-ring = ["tokio-rustls?/ring"] -tls-rust-ktls = ["tls-rust", "ktls"] -tls-rust-native-certs = ["tls-rust", "rustls-native-certs"] -tls-rust-webpki-roots = ["tls-rust", "webpki-roots"] -tls-native = ["tokio-native-tls", "native-tls"] -starttls-native = ["starttls", "tls-native"] -starttls-rust = ["starttls", "tls-rust"] -insecure-tcp = ["tokio/io-util"] + +aws_lc_rs = ["rustls-any-backend", "tokio-rustls/aws_lc_rs"] +ring = ["rustls-any-backend", "tokio-rustls/ring"] +native-tls = ["dep:tokio-native-tls", "dep:native-tls"] +ktls = ["rustls-any-backend", "dep:ktls"] + +rustls-any-backend = ["dep:tokio-rustls"] + +rustls-native-certs = ["dep:rustls-native-certs"] +webpki-roots = ["dep:webpki-roots"] + +insecure-tcp = [] syntax-highlighting = ["syntect"] # Enable serde support in jid crate serde = [ "xmpp-parsers/serde" ] diff --git a/tokio-xmpp/ChangeLog b/tokio-xmpp/ChangeLog index bb249cefc1815713a387af4d54b81a7a4559c6c6..468f7e1bd4789a9c6c858c3b152bae81679f8441 100644 --- a/tokio-xmpp/ChangeLog +++ b/tokio-xmpp/ChangeLog @@ -25,13 +25,15 @@ XXXX-YY-ZZ RELEASER - `Component` is now gated behind `insecure-tcp` feature flag - `XMPPStream` and `XmppCodec` were removed in favour of the newly implemented `tokio_xmpp::xmlstream module. - - The `starttls-rust`, `tls-rust` and `tls-rust-ktls` feature flags do - not automatically enable a `rustls` crypto provider anymore. This is - to avoid conflict between two crypto providers and to avoid linking - unnecessary code. The `aws_lc_rs` crypto provider is still built by - default, however, applications which use `tokio_xmpp` without default - features will have to adapt their feature flags to explicitly enable - the `tls-rust-aws_lc_rs` or `tls-rust-ring` features. (!581) + - The TLS-related feature flags have been completely reworked to make + them easier to use. The `tls-rust-*`, `tls-native` and `starttls-*` + feature flags have been removed in favour of more concise flag names + identifying the TLS backends directly (`aws_lc_rs`, `ring`, + `native-tls`). The `starttls` feature is now independent of the + specific backend (but a backend still needs to be enabled for + compilation to succeed). + + Please refer to the crate docs for details. (!581) * Added: - Support for sending IQ requests while tracking their responses in a Future. diff --git a/tokio-xmpp/examples/contact_addr.rs b/tokio-xmpp/examples/contact_addr.rs index 1171dece3828a68afc2bf979dbd3aa3c54dfff5b..81ed5b1102f3b5a8d410a0214b85368e4eb04854 100644 --- a/tokio-xmpp/examples/contact_addr.rs +++ b/tokio-xmpp/examples/contact_addr.rs @@ -2,10 +2,7 @@ use futures::stream::StreamExt; use std::env::args; use std::process::exit; use std::str::FromStr; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::{Client, IqRequest, IqResponse}; use xmpp_parsers::{ @@ -15,20 +12,22 @@ use xmpp_parsers::{ server_info::ServerInfo, }; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() { env_logger::init(); - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/tokio-xmpp/examples/download_avatars.rs b/tokio-xmpp/examples/download_avatars.rs index aa6da1defed6936ee75c1113ad561efb8051dcda..56560473c3074f4ee78f05fcd7f380043f8b9fbc 100644 --- a/tokio-xmpp/examples/download_avatars.rs +++ b/tokio-xmpp/examples/download_avatars.rs @@ -4,10 +4,7 @@ use std::fs::{create_dir_all, File}; use std::io::{self, Write}; use std::process::exit; use std::str::FromStr; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::{Client, Stanza}; use xmpp_parsers::{ @@ -27,20 +24,22 @@ use xmpp_parsers::{ stanza_error::{DefinedCondition, ErrorType, StanzaError}, }; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() { env_logger::init(); - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/tokio-xmpp/examples/echo_bot.rs b/tokio-xmpp/examples/echo_bot.rs index bff3f4d0cd8477f8acc49652c248f91c64e7dca6..866f36d3df734213614f59000708edae8c4d2c6f 100644 --- a/tokio-xmpp/examples/echo_bot.rs +++ b/tokio-xmpp/examples/echo_bot.rs @@ -2,30 +2,29 @@ use futures::stream::StreamExt; use std::env::args; use std::process::exit; use std::str::FromStr; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::Client; use xmpp_parsers::jid::{BareJid, Jid}; use xmpp_parsers::message::{Lang, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() { env_logger::init(); - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/tokio-xmpp/examples/echo_component.rs b/tokio-xmpp/examples/echo_component.rs index 43c601daafd4a108ffe4d6f70f129b5dfcee787e..eb5b44666456b64cf988d28c9e169f1e4bc96ddf 100644 --- a/tokio-xmpp/examples/echo_component.rs +++ b/tokio-xmpp/examples/echo_component.rs @@ -6,27 +6,26 @@ use xmpp_parsers::jid::Jid; use xmpp_parsers::message::{Lang, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::{connect::DnsConfig, Component}; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() { env_logger::init(); - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/tokio-xmpp/examples/echo_server.rs b/tokio-xmpp/examples/echo_server.rs index 6a5ee89d899c1330998febe09726a38dbe07df5f..da00a6a637359bd86005cbd465992cf8b715434b 100644 --- a/tokio-xmpp/examples/echo_server.rs +++ b/tokio-xmpp/examples/echo_server.rs @@ -1,10 +1,7 @@ use futures::{SinkExt, StreamExt}; use tokio::{self, io, net::TcpSocket}; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::{ minidom::Element, @@ -12,18 +9,20 @@ use tokio_xmpp::{ xmlstream::{accept_stream, StreamHeader, Timeouts}, }; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() -> Result<(), io::Error> { - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/tokio-xmpp/examples/keep_connection.rs b/tokio-xmpp/examples/keep_connection.rs index 18d1841552485b2360eee07ad7ad79acec1f8c23..4e78b408093c40d86c67a6c551dee37e52fb24e6 100644 --- a/tokio-xmpp/examples/keep_connection.rs +++ b/tokio-xmpp/examples/keep_connection.rs @@ -19,10 +19,7 @@ use rand::{thread_rng, Rng}; use futures::StreamExt; -#[cfg(all( - feature = "tls-rust", - any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use tokio_xmpp::rustls; use tokio_xmpp::{ connect::{DnsConfig, StartTlsServerConnector}, @@ -35,20 +32,22 @@ use tokio_xmpp::{ xmlstream::Timeouts, }; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() { env_logger::init(); - #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "tls-rust", - feature = "tls-rust-ring", - not(feature = "tls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); @@ -93,8 +92,13 @@ async fn main() { iq.to = Some(domain.clone()); stream.send(Box::new(iq.into())).await; } - ev = stream.next() => { - log::info!("{:?}", ev); + ev = stream.next() => match ev { + Some(ev) => { + log::info!("{:?}", ev); + } + None => { + panic!("stream terminated unexpectedly!"); + } } } } diff --git a/tokio-xmpp/src/connect/starttls.rs b/tokio-xmpp/src/connect/starttls.rs index e2bb6289e060f01252866e9f1ad634341f2fdcae..f3a7fede6d32da296dfc5eb20b81a7384799f289 100644 --- a/tokio-xmpp/src/connect/starttls.rs +++ b/tokio-xmpp/src/connect/starttls.rs @@ -2,18 +2,22 @@ use alloc::borrow::Cow; use core::{error::Error as StdError, fmt}; -#[cfg(feature = "tls-native")] +#[cfg(feature = "native-tls")] use native_tls::Error as TlsError; use std::io; use std::os::fd::AsRawFd; -#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] +#[cfg(feature = "rustls-any-backend")] use tokio_rustls::rustls::pki_types::InvalidDnsNameError; -#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] +// Note: feature = "rustls-any-backend" and feature = "native-tls" are +// mutually exclusive during normal compiles, but we allow it for rustdoc +// builds. Thus, we have to make sure that the compilation still succeeds in +// such a case. +#[cfg(all(feature = "rustls-any-backend", not(feature = "native-tls")))] use tokio_rustls::rustls::Error as TlsError; use futures::{sink::SinkExt, stream::StreamExt}; -#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] +#[cfg(all(feature = "rustls-any-backend", not(feature = "native-tls")))] use { alloc::sync::Arc, tokio_rustls::{ @@ -24,16 +28,16 @@ use { }; #[cfg(all( - feature = "tls-rust", - not(feature = "tls-native"), - not(feature = "tls-rust-ktls") + feature = "rustls-any-backend", + not(feature = "ktls"), + not(feature = "native-tls") ))] use tokio_rustls::client::TlsStream; -#[cfg(all(feature = "tls-rust-ktls", not(feature = "tls-native")))] +#[cfg(all(feature = "ktls", not(feature = "native-tls")))] type TlsStream = ktls::KtlsStream; -#[cfg(feature = "tls-native")] +#[cfg(feature = "native-tls")] use { native_tls::TlsConnector as NativeTlsConnector, tokio_native_tls::{TlsConnector, TlsStream}, @@ -123,7 +127,7 @@ impl ServerConnector for StartTlsServerConnector { } } -#[cfg(feature = "tls-native")] +#[cfg(feature = "native-tls")] async fn get_tls_stream( xmpp_stream: XmppStream>, domain: &str, @@ -140,7 +144,7 @@ async fn get_tls_stream( Ok((tls_stream, ChannelBinding::None)) } -#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] +#[cfg(all(feature = "rustls-any-backend", not(feature = "native-tls")))] async fn get_tls_stream( xmpp_stream: XmppStream>, domain: &str, @@ -160,7 +164,7 @@ async fn get_tls_stream( let mut config = ClientConfig::builder() .with_root_certificates(root_store) .with_no_client_auth(); - #[cfg(feature = "tls-rust-ktls")] + #[cfg(feature = "ktls")] let stream = { config.enable_secret_extraction = true; ktls::CorkStream::new(stream) @@ -184,7 +188,7 @@ async fn get_tls_stream( _ => ChannelBinding::None, }; - #[cfg(feature = "tls-rust-ktls")] + #[cfg(feature = "ktls")] let tls_stream = ktls::config_ktls_client(tls_stream) .await .map_err(StartTlsError::KtlsError)?; @@ -228,10 +232,10 @@ pub async fn starttls( pub enum StartTlsError { /// TLS error Tls(TlsError), - #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] + #[cfg(feature = "rustls-any-backend")] /// DNS name parsing error DnsNameError(InvalidDnsNameError), - #[cfg(feature = "tls-rust-ktls")] + #[cfg(feature = "ktls")] /// Error while setting up kernel TLS KtlsError(ktls::Error), } @@ -242,9 +246,9 @@ impl fmt::Display for StartTlsError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { Self::Tls(e) => write!(fmt, "TLS error: {}", e), - #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] + #[cfg(feature = "rustls-any-backend")] Self::DnsNameError(e) => write!(fmt, "DNS name error: {}", e), - #[cfg(feature = "tls-rust-ktls")] + #[cfg(feature = "ktls")] Self::KtlsError(e) => write!(fmt, "Kernel TLS error: {}", e), } } @@ -258,7 +262,7 @@ impl From for StartTlsError { } } -#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] +#[cfg(feature = "rustls-any-backend")] impl From for StartTlsError { fn from(e: InvalidDnsNameError) -> Self { Self::DnsNameError(e) diff --git a/tokio-xmpp/src/lib.rs b/tokio-xmpp/src/lib.rs index 5f2dbe1de961bddfe077cf388cb60ce7f76cff89..a8a2d81ff1fbbedf6f72cb45ad0de6e9b6f9b935 100644 --- a/tokio-xmpp/src/lib.rs +++ b/tokio-xmpp/src/lib.rs @@ -22,6 +22,50 @@ //! - [ ] Websockets //! - [ ] BOSH //! +//! # Cargo features +//! +//! ## TLS backends +//! +//! - `aws_lc_rs` (default) enables rustls with the `aws_lc_rs` backend. +//! - `ring` enables rustls with the `ring` backend`. +//! - `rustls-any-backend` enables rustls, but without enabling a backend. It +//! is the application's responsibility to ensure that a backend is enabled +//! and installed. +//! - `ktls` enables the use of ktls. +//! **Important:** Currently, connections will fail if the `tls` kernel +//! module is not available. There is no fallback to non-ktls connections! +//! - `native-tls` enables the system-native TLS library (commonly +//! libssl/OpenSSL). +//! +//! **Note:** It is not allowed to mix rustls-based TLS backends with +//! `tls-native`. Attempting to do so will result in a compilation error. +//! +//! **Note:** The `ktls` feature requires at least one `rustls` backend to be +//! enabled (`aws_lc_rs` or `ring`). +//! +//! **Note:** When enabling not exactly one rustls backend, it is the +//! application's responsibility to make sure that a default crypto provider is +//! installed in `rustls`. Otherwise, all TLS connections will fail. +//! +//! ## Certificate validation +//! +//! When using `native-tls`, the system's native certificate store is used. +//! Otherwise, you need to pick one of the following to ensure that TLS +//! connections will succeed: +//! +//! - `rustls-native-certs` (default): Uses [rustls-native-certs](https://crates.io/crates/rustls-native-certs). +//! - `webpki-roots`: Uses [webpki-roots](https://crates.io/crates/webpki-roots). +//! +//! ## Other features +//! +//! - `starttls` (default): Enables support for ``. Required as per +//! RFC 6120. +//! - `insecure-tcp`: Allow the use of insecure TCP connections to connect to +//! XMPP servers. Required for XMPP components, but disabled by default to +//! prevent accidental use. +//! - `serde`: Enable the `serde` feature in `xmpp-parsers`. +//! - `component`: Enable component support (implies `insecure-tcp`). +//! //! # More information //! //! You can find more information on our website [xmpp.rs](https://xmpp.rs/) or by joining our chatroom [chat@xmpp.rs](xmpp:chat@xmpp.rs?join). @@ -29,21 +73,35 @@ #![deny(unsafe_code, missing_docs, bare_trait_objects)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#[cfg(all( - not(xmpprs_doc_build), - not(doc), - feature = "tls-native", - feature = "tls-rust" -))] -compile_error!("Both tls-native and tls-rust features can't be enabled at the same time."); +macro_rules! fail_native_with_any { + ($($feature:literal),+) => { + $( + #[cfg(all( + not(xmpprs_doc_build), + not(doc), + feature = "native-tls", + feature = $feature, + ))] + compile_error!( + concat!( + "native-tls cannot be mixed with the ", + $feature, + " feature. Pick one or the other." + ) + ); + )+ + } +} + +fail_native_with_any!("ring", "aws_lc_rs", "ktls", "rustls-any-backend"); #[cfg(all( feature = "starttls", - not(feature = "tls-native"), - not(feature = "tls-rust") + not(feature = "native-tls"), + not(any(feature = "rustls-any-backend")) ))] compile_error!( - "when starttls feature enabled one of tls-native and tls-rust features must be enabled." + "When the starttls feature is enabled, either native-tls or any of the rustls (aws_lc_rs, ring, or rustls-any-backend) features must be enabled." ); extern crate alloc; @@ -51,7 +109,7 @@ extern crate alloc; pub use parsers::{jid, minidom}; pub use xmpp_parsers as parsers; -#[cfg(feature = "tls-rust")] +#[cfg(any(feature = "ring", feature = "aws_lc_rs", feature = "ktls"))] pub use tokio_rustls::rustls; mod client; diff --git a/xmpp/Cargo.toml b/xmpp/Cargo.toml index 0732cbc477576d580f2a045fb2057cf0c517e4b2..05d9976e91b2a7b0260de10cc2f81da69fa79504 100644 --- a/xmpp/Cargo.toml +++ b/xmpp/Cargo.toml @@ -31,11 +31,20 @@ name = "hello_bot" required-features = ["avatars"] [features] -default = ["avatars", "starttls-rust"] -starttls-native = ["tokio-xmpp/starttls", "tokio-xmpp/tls-native", "reqwest/native-tls"] -starttls-rust = ["tokio-xmpp/starttls", "tokio-xmpp/tls-rust", "reqwest/rustls-tls-no-provider", "tokio-xmpp/tls-rust-webpki-roots"] -starttls-rust-aws_lc_rs = ["tokio-xmpp/tls-rust-aws_lc_rs", "starttls-rust"] -starttls-rust-ring = ["tokio-xmpp/tls-rust-ring", "starttls-rust"] +default = ["avatars", "aws_lc_rs", "starttls", "rustls-native-certs"] + +aws_lc_rs = ["rustls-any-backend", "tokio-xmpp/aws_lc_rs", "reqwest/rustls-tls-no-provider"] +ring = ["rustls-any-backend", "tokio-xmpp/ring", "reqwest/rustls-tls-no-provider"] +native-tls = ["tokio-xmpp/native-tls", "reqwest/native-tls"] +ktls = ["rustls-any-backend", "tokio-xmpp/ktls", "reqwest/rustls-tls"] + +rustls-any-backend = ["tokio-xmpp/rustls-any-backend"] + +rustls-native-certs = ["tokio-xmpp/rustls-native-certs"] +webpki-roots = ["tokio-xmpp/webpki-roots"] + +starttls = ["tokio-xmpp/starttls"] + avatars = [] escape-hatch = [] syntax-highlighting = [ "tokio-xmpp/syntax-highlighting" ] diff --git a/xmpp/ChangeLog b/xmpp/ChangeLog index 33236c7bfb2d7ce8ea8d9fa8aed3d6a8534ee8bf..35c72fe92da2b58055210a1a086cb9773295917c 100644 --- a/xmpp/ChangeLog +++ b/xmpp/ChangeLog @@ -15,13 +15,14 @@ XXXX-YY-ZZ [ RELEASER ] - Agent::send_room_private_message now takes RoomPrivateMessageSettings (!487) - Event now exposes Option for incoming messages, and MessageId for incoming message corrections; type alias Id has been removed (!504) - - The `starttls-rust` feature flag does not automatically enable a - `rustls` crypto provider anymore. This is to avoid conflict between - two crypto providers and to avoid linking unnecessary code. The - `aws_lc_rs` crypto provider is still built by default, however, - applications which use `xmpp` without default features will have to - adapt their feature flags to explicitly enable the - `starttls-rust-aws_lc_rs` or `starttls-rust-ring` features. (!581) + - The TLS-related feature flags have been completely reworked to make + them easier to use. The `starttls-*` feature flags have been removed + in favour of more concise flag names identifying the TLS backends + directly (`aws_lc_rs`, `ring`, `native-tls`). The `starttls` feature + is now independent of the specific backend (but a backend still needs + to be enabled for compilation to succeed). + + Please refer to the crate docs for details. (!581) * Added: - Agent::send_room_message takes RoomMessageSettings argument (!483) - Agent::send_raw_message takes RawMessageSettings for any message type (!487) diff --git a/xmpp/examples/hello_bot.rs b/xmpp/examples/hello_bot.rs index 8cc00c6e53b94e56d72a7eb7f7f15160ef78a40f..3f67be08ec21d423de5b9d91f2c473fd8511a055 100644 --- a/xmpp/examples/hello_bot.rs +++ b/xmpp/examples/hello_bot.rs @@ -4,10 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#[cfg(all( - feature = "starttls-rust", - any(feature = "starttls-rust-aws_lc_rs", feature = "starttls-rust-ring") -))] +#[cfg(feature = "rustls-any-backend")] use xmpp::tokio_xmpp::rustls; use xmpp::{ jid::BareJid, @@ -20,20 +17,22 @@ use tokio::signal::ctrl_c; use std::env::args; use std::str::FromStr; +#[cfg(all( + feature = "rustls-any-backend", + not(any(feature = "aws_lc_rs", feature = "ring")) +))] +compile_error!("using rustls (e.g. via the ktls feature) needs an enabled rustls backend feature (either aws_lc_rs or ring)."); + #[tokio::main] async fn main() -> Result<(), Option<()>> { env_logger::init(); - #[cfg(all(feature = "starttls-rust", feature = "starttls-rust-aws_lc_rs"))] + #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("failed to install rustls crypto provider"); - #[cfg(all( - feature = "starttls-rust", - feature = "starttls-rust-ring", - not(feature = "starttls-rust-aws_lc_rs") - ))] + #[cfg(all(feature = "ring"))] rustls::crypto::ring::default_provider() .install_default() .expect("failed to install rustls crypto provider"); diff --git a/xmpp/src/builder.rs b/xmpp/src/builder.rs index ace98e47489ad4a4e6bfdfaab635f4aadf256946..f8fdee3e0ce33723b0a423369f0e3abe57f1c461 100644 --- a/xmpp/src/builder.rs +++ b/xmpp/src/builder.rs @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#[cfg(any(feature = "starttls-rust", feature = "starttls-native"))] +#[cfg(feature = "starttls")] use crate::tokio_xmpp::connect::{DnsConfig, StartTlsServerConnector}; use core::str::FromStr; @@ -52,7 +52,7 @@ pub struct ClientBuilder<'a, C: ServerConnector> { timeouts: Timeouts, } -#[cfg(any(feature = "starttls-rust", feature = "starttls-native"))] +#[cfg(feature = "starttls")] impl ClientBuilder<'_, StartTlsServerConnector> { pub fn new<'a>(jid: BareJid, password: &'a str) -> ClientBuilder<'a, StartTlsServerConnector> { Self::new_with_connector( diff --git a/xmpp/src/lib.rs b/xmpp/src/lib.rs index aeb19a73d17b93e58bbe4237c373d7e4942897f6..c7993f982167ec2a0b79f078e2d4a90eb6422dbc 100644 --- a/xmpp/src/lib.rs +++ b/xmpp/src/lib.rs @@ -3,6 +3,46 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +//! # Cargo features +//! +//! ## TLS backends +//! +//! - `aws_lc_rs` (default) enables rustls with the `aws_lc_rs` backend. +//! - `ring` enables rustls with the `ring` backend`. +//! - `rustls-any-backend` enables rustls, but without enabling a backend. It +//! is the application's responsibility to ensure that a backend is enabled +//! and installed. +//! - `ktls` enables the use of ktls. +//! **Important:** Currently, connections will fail if the `tls` kernel +//! module is not available. There is no fallback to non-ktls connections! +//! - `native-tls` enables the system-native TLS library (commonly +//! libssl/OpenSSL). +//! +//! **Note:** It is not allowed to mix rustls-based TLS backends with +//! `tls-native`. Attempting to do so will result in a compilation error. +//! +//! **Note:** The `ktls` feature requires at least one `rustls` backend to be +//! enabled (`aws_lc_rs` or `ring`). +//! +//! **Note:** When enabling not exactly one rustls backend, it is the +//! application's responsibility to make sure that a default crypto provider is +//! installed in `rustls`. Otherwise, all TLS connections will fail. +//! +//! ## Certificate validation +//! +//! When using `native-tls`, the system's native certificate store is used. +//! Otherwise, you need to pick one of the following to ensure that TLS +//! connections will succeed: +//! +//! - `rustls-native-certs` (default): Uses [rustls-native-certs](https://crates.io/crates/rustls-native-certs). +//! - `webpki-roots`: Uses [webpki-roots](https://crates.io/crates/webpki-roots). +//! +//! ## Other features +//! +//! - `starttls` (default): Enables support for ``. Required as per +//! RFC 6120. +//! - `avatars` (default): Enables support for avatars. +//! - `serde`: Enable the `serde` feature in `tokio-xmpp`. #![deny(bare_trait_objects)] #![cfg_attr(docsrs, feature(doc_auto_cfg))]