diff --git a/parsers/ChangeLog b/parsers/ChangeLog index e80ee6cf..c928714e 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -9,6 +9,8 @@ XXXX-YY-ZZ RELEASER - The ibr::Query struct has been split into FieldsQuery, RemoveQuery, LegacyQuery and FormsQuery, to make it reflect more how it gets used in XMPP. + - Remove the unnecessary SaslMechanisms struct, to directly extract + SASL mechanisms in a Vec in StreamFeatures. * Improvements: - Make Priority’s inner i8 pub, which had been broken since the conversion to xso. (!632) diff --git a/parsers/src/stream_features.rs b/parsers/src/stream_features.rs index ba781991..b9a5bdb7 100644 --- a/parsers/src/stream_features.rs +++ b/parsers/src/stream_features.rs @@ -4,6 +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/. +use alloc::collections::BTreeSet; use minidom::Element; use xso::{AsXml, FromXml}; @@ -28,8 +29,10 @@ pub struct StreamFeatures { pub bind: Option, /// List of supported SASL mechanisms - #[xml(child(default))] - pub sasl_mechanisms: SaslMechanisms, + #[xml(extract(default, namespace = ns::SASL, name = "mechanisms", fields( + extract(n = .., name = "mechanism", fields(text(type_ = String))) + )))] + pub sasl_mechanisms: BTreeSet, /// Limits advertised by the server. #[xml(child(default))] @@ -59,15 +62,6 @@ pub struct StreamFeatures { pub others: Vec, } -/// List of supported SASL mechanisms -#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)] -#[xml(namespace = ns::SASL, name = "mechanisms")] -pub struct SaslMechanisms { - /// List of information elements describing this SASL mechanism. - #[xml(extract(n = .., name = "mechanism", fields(text(type_ = String))))] - pub mechanisms: Vec, -} - impl StreamFeatures { /// Can initiate TLS session with this server? pub fn can_starttls(&self) -> bool { @@ -88,14 +82,12 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(SaslMechanisms, 12); assert_size!(StreamFeatures, 92); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(SaslMechanisms, 24); assert_size!(StreamFeatures, 168); } @@ -112,10 +104,10 @@ mod tests { .unwrap(); let features = StreamFeatures::try_from(elem).unwrap(); - assert_eq!( - features.sasl_mechanisms.mechanisms, - ["PLAIN", "SCRAM-SHA-1", "SCRAM-SHA-1-PLUS"] - ); + assert!(features.sasl_mechanisms.contains("PLAIN")); + assert!(features.sasl_mechanisms.contains("SCRAM-SHA-1")); + assert!(features.sasl_mechanisms.contains("SCRAM-SHA-1-PLUS")); + assert!(!features.sasl_mechanisms.contains("CRAM-MD5")); } #[test] @@ -131,7 +123,7 @@ mod tests { let features = StreamFeatures::try_from(elem).unwrap(); assert_eq!(features.can_bind(), false); - assert_eq!(features.sasl_mechanisms.mechanisms.len(), 0); + assert_eq!(features.sasl_mechanisms.len(), 0); assert_eq!(features.can_starttls(), true); assert_eq!(features.starttls.unwrap().required, true); } @@ -151,7 +143,7 @@ mod tests { let features = StreamFeatures::try_from(elem).unwrap(); assert_eq!(features.can_bind(), true); - assert_eq!(features.sasl_mechanisms.mechanisms.len(), 0); + assert_eq!(features.sasl_mechanisms.len(), 0); assert_eq!(features.can_starttls(), false); assert_eq!(features.others.len(), 1); @@ -181,7 +173,7 @@ mod tests { let features = StreamFeatures::try_from(elem).unwrap(); assert_eq!(features.can_bind(), false); - assert_eq!(features.sasl_mechanisms.mechanisms.len(), 0); + assert_eq!(features.sasl_mechanisms.len(), 0); assert_eq!(features.can_starttls(), false); } } diff --git a/tokio-xmpp/src/client/login.rs b/tokio-xmpp/src/client/login.rs index 0ff67743..a13f0e49 100644 --- a/tokio-xmpp/src/client/login.rs +++ b/tokio-xmpp/src/client/login.rs @@ -5,14 +5,14 @@ use sasl::client::mechanisms::{Anonymous, Plain, Scram}; use sasl::client::Mechanism; use sasl::common::scram::{Sha1, Sha256}; use sasl::common::Credentials; -use std::collections::HashSet; +use std::collections::BTreeSet; use std::io; use tokio::io::{AsyncBufRead, AsyncWrite}; use xmpp_parsers::{ jid::Jid, ns, sasl::{Auth, Mechanism as XMPPMechanism, Nonza, Response}, - stream_features::{SaslMechanisms, StreamFeatures}, + stream_features::StreamFeatures, }; use crate::{ @@ -30,7 +30,7 @@ use crate::{ /// this returns the `stream` as [`InitiatingStream`] on success. pub async fn auth( mut stream: XmppStream, - sasl_mechanisms: &SaslMechanisms, + sasl_mechanisms: BTreeSet, creds: Credentials, ) -> Result, Error> { let local_mechs: Vec Box + Send>> = vec![ @@ -40,11 +40,9 @@ pub async fn auth( Box::new(|| Box::new(Anonymous::new())), ]; - let remote_mechs: HashSet = sasl_mechanisms.mechanisms.iter().cloned().collect(); - for local_mech in local_mechs { let mut mechanism = local_mech(); - if remote_mechs.contains(mechanism.name()) { + if sasl_mechanisms.contains(mechanism.name()) { let initial = mechanism.initial(); let mechanism_name = XMPPMechanism::from_str(mechanism.name()).map_err(ProtocolError::Parsers)?; @@ -124,7 +122,7 @@ pub async fn client_auth( .with_password(password) .with_channel_binding(channel_binding); // Authenticated (unspecified) stream - let stream = auth(xmpp_stream, &features.sasl_mechanisms, creds).await?; + let stream = auth(xmpp_stream, features.sasl_mechanisms, creds).await?; let stream = stream .send_header(StreamHeader { to: Some(Cow::Borrowed(jid.domain().as_str())),