From de2ba97f79ab30a8fef6cf2d8335675dcc9bc301 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 2 Jul 2024 18:40:28 +0200 Subject: [PATCH] xmpp-parsers: Implement XEP-0440: SASL Channel-Binding Type Capability --- parsers/ChangeLog | 1 + parsers/doap.xml | 8 ++++ parsers/src/lib.rs | 3 ++ parsers/src/ns.rs | 3 ++ parsers/src/sasl_cb.rs | 89 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 parsers/src/sasl_cb.rs diff --git a/parsers/ChangeLog b/parsers/ChangeLog index dc13ec3bcf71390eda954681e7e00ff9c602e02e..31d4c8a1b7050d63d7e2571d26a94576c6bfb2b9 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -17,6 +17,7 @@ XXXX-YY-ZZ RELEASER (!416) * New parsers/serialisers: - Stream Features (RFC 6120) (!400) + - SASL Channel-Binding Type Capability (XEP-0440) Version 0.21.0: 2024-07-25 Emmanuel Gil Peyrot diff --git a/parsers/doap.xml b/parsers/doap.xml index 13494a285caf6069c735811743aec1a6ba32bec2..f2876ff30c81c9335a955be2af4564174936137c 100644 --- a/parsers/doap.xml +++ b/parsers/doap.xml @@ -626,6 +626,14 @@ 0.16.0 + + + + complete + 0.4.2 + NEXT + + diff --git a/parsers/src/lib.rs b/parsers/src/lib.rs index 48e6c5dfe806c5b1a62cb5a849542dd41bb897ce..02428ed0305b917d46c4ecad43cfbe315a12f20e 100644 --- a/parsers/src/lib.rs +++ b/parsers/src/lib.rs @@ -272,6 +272,9 @@ pub mod occupant_id; /// XEP-0441: Message Archive Management Preferences pub mod mam_prefs; +/// XEP-0440: SASL Channel-Binding Type Capability +pub mod sasl_cb; + /// XEP-0444: Message Reactions pub mod reactions; diff --git a/parsers/src/ns.rs b/parsers/src/ns.rs index 1dd1211133eb5b4f13373b5e222dd39a050e5cfb..7191bf7fa4b0988e7ad89bbcbc190c3076cd13a8 100644 --- a/parsers/src/ns.rs +++ b/parsers/src/ns.rs @@ -293,6 +293,9 @@ pub const BOOKMARKS2_COMPAT_PEP: &str = "urn:xmpp:bookmarks:1#compat-pep"; /// XEP-0421: Anonymous unique occupant identifiers for MUCs pub const OID: &str = "urn:xmpp:occupant-id:0"; +/// XEP-0440: SASL Channel-Binding Type Capability +pub const SASL_CB: &str = "urn:xmpp:sasl-cb:0"; + /// XEP-0444: Message Reactions pub const REACTIONS: &str = "urn:xmpp:reactions:0"; diff --git a/parsers/src/sasl_cb.rs b/parsers/src/sasl_cb.rs new file mode 100644 index 0000000000000000000000000000000000000000..018fcc00cd7ac704004e6cedecff0812f34d051e --- /dev/null +++ b/parsers/src/sasl_cb.rs @@ -0,0 +1,89 @@ +// Copyright (c) 2024 Emmanuel Gil Peyrot +// +// 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/. + +use xso::{error::Error, AsXml, AsXmlText, FromXml, FromXmlText}; + +use crate::ns; +use std::borrow::Cow; + +/// One type of channel-binding, as defined by the IANA: +/// https://www.iana.org/assignments/channel-binding-types/channel-binding-types.xhtml +#[derive(Debug, Clone, PartialEq)] +pub enum Type { + /// The tls-unique channel binding. + TlsUnique, + + /// The tls-server-end-point channel binding. + TlsServerEndPoint, + + /// The tls-unique-for-telnet channel binding. + TlsUniqueForTelnet, + + /// The EKM value obtained from the current TLS connection. + /// + /// See RFC9266. + TlsExporter, +} + +impl FromXmlText for Type { + fn from_xml_text(s: String) -> Result { + Ok(match s.as_ref() { + "tls-unique" => Type::TlsUnique, + "tls-server-end-point" => Type::TlsServerEndPoint, + "tls-unique-for-telnet" => Type::TlsUniqueForTelnet, + "tls-exporter" => Type::TlsExporter, + + _ => return Err(Error::Other("Unknown value '{s}' for 'type' attribute.")), + }) + } +} + +impl AsXmlText for Type { + fn as_xml_text(&self) -> Result, Error> { + Ok(Cow::Borrowed(match self { + Type::TlsUnique => "tls-unique", + Type::TlsServerEndPoint => "tls-server-end-point", + Type::TlsUniqueForTelnet => "tls-unique-for-telnet", + Type::TlsExporter => "tls-exporter", + })) + } +} + +/// Stream feature listing the channel-binding types supported by the server. +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::SASL_CB, name = "sasl-channel-binding")] +pub struct SaslChannelBinding { + /// The list of channel-binding types supported by the server. + #[xml(extract(n = .., name = "channel-binding", fields(attribute(name = "type", type_ = Type))))] + pub types: Vec, +} + +#[cfg(test)] +mod tests { + use super::*; + use minidom::Element; + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_size() { + assert_size!(Type, 1); + assert_size!(SaslChannelBinding, 24); + } + + #[cfg(target_pointer_width = "32")] + #[test] + fn test_size() { + assert_size!(Type, 1); + assert_size!(SaslChannelBinding, 12); + } + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + let sasl_cb = SaslChannelBinding::try_from(elem).unwrap(); + assert_eq!(sasl_cb.types, [Type::TlsServerEndPoint, Type::TlsExporter]); + } +}