Avoid enabling multiple rustls backends by accident

Jonas SchΓ€fer created

For this, we had to:

- Make the choice(s) of backend explicit in tokio-xmpp features
- Avoid picking a backend through transitive dependencies in xmpp
  (reqwest->hyper->rustls).

In addition, we choose the default rustls backend by default and adapt
the examples so that they can cope with either situation.

Change summary

tokio-xmpp/Cargo.toml                   |  6 ++++--
tokio-xmpp/ChangeLog                    |  7 +++++++
tokio-xmpp/examples/contact_addr.rs     | 18 ++++++++++++++++--
tokio-xmpp/examples/download_avatars.rs | 18 ++++++++++++++++--
tokio-xmpp/examples/echo_bot.rs         | 18 ++++++++++++++++--
tokio-xmpp/examples/echo_component.rs   | 18 ++++++++++++++++--
tokio-xmpp/examples/echo_server.rs      | 17 +++++++++++++++--
tokio-xmpp/examples/keep_connection.rs  | 17 +++++++++++++++--
xmpp/Cargo.toml                         |  4 +++-
xmpp/ChangeLog                          |  7 +++++++
xmpp/examples/hello_bot.rs              | 19 +++++++++++++++++++
11 files changed, 134 insertions(+), 15 deletions(-)

Detailed changes

tokio-xmpp/Cargo.toml πŸ”—

@@ -33,7 +33,7 @@ hickory-resolver = { version = "0.24", optional = true}
 idna = { version = "1.0", optional = true}
 native-tls = { version = "0.2", optional = true }
 tokio-native-tls = { version = "0.3", optional = true }
-tokio-rustls = { version = "0.26", optional = true }
+tokio-rustls = { version = "0.26", optional = true, default-features = false, features = ["logging", "tls12"] }
 ktls = { version = "6", optional = true }
 
 [dev-dependencies]
@@ -43,9 +43,11 @@ tokio = { version = "1", features = ["signal", "test-util"] }
 tokio-xmpp = { path = ".", features = ["insecure-tcp"]}
 
 [features]
-default = ["starttls-rust", "rustls-native-certs"]
+default = ["starttls-rust", "rustls-native-certs", "tls-rust-aws_lc_rs"]
 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"]

tokio-xmpp/ChangeLog πŸ”—

@@ -25,6 +25,13 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
       - `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)
     * Added:
       - Support for sending IQ requests while tracking their responses in a
         Future.

tokio-xmpp/examples/contact_addr.rs πŸ”—

@@ -2,7 +2,12 @@ use futures::stream::StreamExt;
 use std::env::args;
 use std::process::exit;
 use std::str::FromStr;
-use tokio_xmpp::{rustls, Client, IqRequest, IqResponse};
+#[cfg(all(
+    feature = "tls-rust",
+    any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring")
+))]
+use tokio_xmpp::rustls;
+use tokio_xmpp::{Client, IqRequest, IqResponse};
 use xmpp_parsers::{
     disco::{DiscoInfoQuery, DiscoInfoResult},
     jid::{BareJid, Jid},
@@ -14,11 +19,20 @@ use xmpp_parsers::{
 async fn main() {
     env_logger::init();
 
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() != 4 {
         println!("Usage: {} <jid> <password> <target>", args[0]);

tokio-xmpp/examples/download_avatars.rs πŸ”—

@@ -4,7 +4,12 @@ use std::fs::{create_dir_all, File};
 use std::io::{self, Write};
 use std::process::exit;
 use std::str::FromStr;
-use tokio_xmpp::{rustls, Client, Stanza};
+#[cfg(all(
+    feature = "tls-rust",
+    any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring")
+))]
+use tokio_xmpp::rustls;
+use tokio_xmpp::{Client, Stanza};
 use xmpp_parsers::{
     avatar::{Data as AvatarData, Metadata as AvatarMetadata},
     caps::{compute_disco, hash_caps, Caps},
@@ -26,11 +31,20 @@ use xmpp_parsers::{
 async fn main() {
     env_logger::init();
 
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() != 3 {
         println!("Usage: {} <jid> <password>", args[0]);

tokio-xmpp/examples/echo_bot.rs πŸ”—

@@ -2,7 +2,12 @@ use futures::stream::StreamExt;
 use std::env::args;
 use std::process::exit;
 use std::str::FromStr;
-use tokio_xmpp::{rustls, Client};
+#[cfg(all(
+    feature = "tls-rust",
+    any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring")
+))]
+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};
@@ -11,11 +16,20 @@ use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceTyp
 async fn main() {
     env_logger::init();
 
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() != 3 {
         println!("Usage: {} <jid> <password>", args[0]);

tokio-xmpp/examples/echo_component.rs πŸ”—

@@ -6,17 +6,31 @@ use xmpp_parsers::jid::Jid;
 use xmpp_parsers::message::{Lang, Message, MessageType};
 use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
 
-use tokio_xmpp::{connect::DnsConfig, rustls, Component};
+#[cfg(all(
+    feature = "tls-rust",
+    any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring")
+))]
+use tokio_xmpp::rustls;
+use tokio_xmpp::{connect::DnsConfig, Component};
 
 #[tokio::main]
 async fn main() {
     env_logger::init();
 
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() < 3 || args.len() > 4 {
         println!("Usage: {} <jid> <password> [server:port]", args[0]);

tokio-xmpp/examples/echo_server.rs πŸ”—

@@ -1,20 +1,33 @@
 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")
+))]
+use tokio_xmpp::rustls;
 use tokio_xmpp::{
     minidom::Element,
     parsers::stream_features::StreamFeatures,
-    rustls,
     xmlstream::{accept_stream, StreamHeader, Timeouts},
 };
 
 #[tokio::main]
 async fn main() -> Result<(), io::Error> {
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     // TCP socket
     let address = "127.0.0.1:5222".parse().unwrap();
     let socket = TcpSocket::new_v4()?;

tokio-xmpp/examples/keep_connection.rs πŸ”—

@@ -19,6 +19,11 @@ use rand::{thread_rng, Rng};
 
 use futures::StreamExt;
 
+#[cfg(all(
+    feature = "tls-rust",
+    any(feature = "tls-rust-aws_lc_rs", feature = "tls-rust-ring")
+))]
+use tokio_xmpp::rustls;
 use tokio_xmpp::{
     connect::{DnsConfig, StartTlsServerConnector},
     parsers::{
@@ -26,7 +31,6 @@ use tokio_xmpp::{
         jid::{BareJid, Jid},
         ping,
     },
-    rustls,
     stanzastream::StanzaStream,
     xmlstream::Timeouts,
 };
@@ -35,11 +39,20 @@ use tokio_xmpp::{
 async fn main() {
     env_logger::init();
 
-    #[cfg(feature = "tls-rust")]
+    #[cfg(all(feature = "tls-rust", feature = "tls-rust-aws_lc_rs"))]
     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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() != 3 {
         println!("Usage: {} <jid> <password>", args[0]);

xmpp/Cargo.toml πŸ”—

@@ -33,7 +33,9 @@ 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"]
+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"]
 avatars = []
 escape-hatch = []
 syntax-highlighting = [ "tokio-xmpp/syntax-highlighting" ]

xmpp/ChangeLog πŸ”—

@@ -15,6 +15,13 @@ XXXX-YY-ZZ [ RELEASER <admin@localhost> ]
       - Agent::send_room_private_message now takes RoomPrivateMessageSettings (!487)
       - Event now exposes Option<MessageId> 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)
     * Added:
       - Agent::send_room_message takes RoomMessageSettings argument (!483)
       - Agent::send_raw_message takes RawMessageSettings for any message type (!487)

xmpp/examples/hello_bot.rs πŸ”—

@@ -4,6 +4,11 @@
 // 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")
+))]
+use xmpp::tokio_xmpp::rustls;
 use xmpp::{
     jid::BareJid,
     muc::room::{JoinRoomSettings, RoomMessageSettings},
@@ -19,6 +24,20 @@ use std::str::FromStr;
 async fn main() -> Result<(), Option<()>> {
     env_logger::init();
 
+    #[cfg(all(feature = "starttls-rust", feature = "starttls-rust-aws_lc_rs"))]
+    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")
+    ))]
+    rustls::crypto::ring::default_provider()
+        .install_default()
+        .expect("failed to install rustls crypto provider");
+
     let args: Vec<String> = args().collect();
     if args.len() < 3 {
         println!("Usage: {} <jid> <password> [ROOM...]", args[0]);