parsers: add stream error XSO
This commit is contained in:
parent
ce4b739026
commit
b39ad99ecd
3 changed files with 286 additions and 0 deletions
|
|
@ -29,6 +29,7 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
|
|||
- Extensible SASL Profile (XEP-0388)
|
||||
- SASL Channel-Binding Type Capability (XEP-0440)
|
||||
- Stream Limits Advertisement (XEP-0478)
|
||||
- RFC 6120 stream errors
|
||||
|
||||
Version 0.21.0:
|
||||
2024-07-25 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ pub mod starttls;
|
|||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||
pub mod stream;
|
||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||
pub mod stream_error;
|
||||
/// RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||
pub mod stream_features;
|
||||
|
||||
/// RFC 6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence
|
||||
|
|
|
|||
283
parsers/src/stream_error.rs
Normal file
283
parsers/src/stream_error.rs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
|
||||
//
|
||||
// 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 minidom::Element;
|
||||
use xso::{AsXml, FromXml};
|
||||
|
||||
use crate::ns;
|
||||
|
||||
/// Enumeration of all stream error conditions as defined in [RFC 6120].
|
||||
///
|
||||
/// All variant documentation is directly quoted from [RFC 6120].
|
||||
///
|
||||
/// [RFC 6120]: https://datatracker.ietf.org/doc/html/rfc6120#section-4.9.3
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::STREAM)]
|
||||
pub enum DefinedCondition {
|
||||
/// The entity has sent XML that cannot be processed.
|
||||
///
|
||||
/// This error can be used instead of the more specific XML-related
|
||||
/// errors, such as `<bad-namespace-prefix/>`, `<invalid-xml/>`,
|
||||
/// `<not-well-formed/>`, `<restricted-xml/>`, and
|
||||
/// `<unsupported-encoding/>`. However, the more specific errors are
|
||||
/// RECOMMENDED.
|
||||
#[xml(name = "bad-format")]
|
||||
BadFormat,
|
||||
|
||||
/// The entity has sent a namespace prefix that is unsupported, or has
|
||||
/// sent no namespace prefix on an element that needs such a prefix (see
|
||||
/// [Section 11.2](https://datatracker.ietf.org/doc/html/rfc6120#section-11.2)).
|
||||
#[xml(name = "bad-namespace-prefix")]
|
||||
BadNamespacePrefix,
|
||||
|
||||
/// The server either (1) is closing the existing stream for this entity
|
||||
/// because a new stream has been initiated that conflicts with the
|
||||
/// existing stream, or (2) is refusing a new stream for this entity
|
||||
/// because allowing the new stream would conflict with an existing
|
||||
/// stream (e.g., because the server allows only a certain number of
|
||||
/// connections from the same IP address or allows only one server-to-
|
||||
/// server stream for a given domain pair as a way of helping to ensure
|
||||
/// in-order processing as described under
|
||||
/// [Section 10.1](https://datatracker.ietf.org/doc/html/rfc6120#section-10.1)).
|
||||
///
|
||||
/// If a client receives a `<conflict/>` stream error, during the resource
|
||||
/// binding aspect of its reconnection attempt it MUST NOT blindly request
|
||||
/// the resourcepart it used during the former session but instead MUST
|
||||
/// choose a different resourcepart; details are provided under
|
||||
/// [Section 7](https://datatracker.ietf.org/doc/html/rfc6120#section-7).
|
||||
#[xml(name = "conflict")]
|
||||
Conflict,
|
||||
|
||||
/// One party is closing the stream because it has reason to believe that
|
||||
/// the other party has permanently lost the ability to communicate over
|
||||
/// the stream. The lack of ability to communicate can be discovered
|
||||
/// using various methods, such as whitespace keepalives as specified
|
||||
/// under
|
||||
/// [Section 4.4](https://datatracker.ietf.org/doc/html/rfc6120#section-4.4),
|
||||
/// XMPP-level pings as defined in
|
||||
/// [XEP-0199](https://xmpp.org/extensions/xep-0199.html), and
|
||||
/// XMPP Stream Management as defined in
|
||||
/// [XEP-0198](https://xmpp.org/extensions/xep-0198.html).
|
||||
///
|
||||
/// Interoperability Note: RFC 3920 specified that the
|
||||
/// `<connection-timeout/>` stream error is to be used if the peer has not
|
||||
/// generated any traffic over the stream for some period of time.
|
||||
/// That behavior is no longer recommended; instead, the error SHOULD be
|
||||
/// used only if the connected client or peer server has not responded to
|
||||
/// data sent over the stream.
|
||||
#[xml(name = "connection-timeout")]
|
||||
ConnectionTimeout,
|
||||
|
||||
/// The value of the 'to' attribute provided in the initial stream header
|
||||
/// corresponds to an FQDN that is no longer serviced by the receiving
|
||||
/// entity.
|
||||
#[xml(name = "host-gone")]
|
||||
HostGone,
|
||||
|
||||
/// The value of the 'to' attribute provided in the initial stream header
|
||||
/// does not correspond to an FQDN that is serviced by the receiving
|
||||
/// entity.
|
||||
#[xml(name = "host-unknown")]
|
||||
HostUnknown,
|
||||
|
||||
/// A stanza sent between two servers lacks a 'to' or 'from' attribute,
|
||||
/// the 'from' or 'to' attribute has no value, or the value violates the
|
||||
/// rules for XMPP addresses
|
||||
/// (see [RFC 6122](https://datatracker.ietf.org/doc/html/rfc6122)).
|
||||
#[xml(name = "improper-addressing")]
|
||||
ImproperAddressing,
|
||||
|
||||
/// The server has experienced a misconfiguration or other internal error
|
||||
/// that prevents it from servicing the stream.
|
||||
#[xml(name = "internal-server-error")]
|
||||
InternalServerError,
|
||||
|
||||
/// The data provided in a 'from' attribute does not match an authorized
|
||||
/// JID or validated domain as negotiated (1) between two servers using
|
||||
/// SASL or Server Dialback, or (2) between a client and a server via
|
||||
/// SASL authentication and resource binding.
|
||||
#[xml(name = "invalid-from")]
|
||||
InvalidFrom,
|
||||
|
||||
/// The stream namespace name is something other than
|
||||
/// `http://etherx.jabber.org/streams` (see
|
||||
/// [Section 11.2](https://datatracker.ietf.org/doc/html/rfc6120#section-11.2))
|
||||
/// or the content namespace declared as the default namespace is not
|
||||
/// supported (e.g., something other than `jabber:client` or
|
||||
/// `jabber:server`).
|
||||
#[xml(name = "invalid-namespace")]
|
||||
InvalidNamespace,
|
||||
|
||||
/// The entity has sent invalid XML over the stream to a server that
|
||||
/// performs validation (see
|
||||
/// [Section 11.4](https://datatracker.ietf.org/doc/html/rfc6120#section-11.4)).
|
||||
#[xml(name = "invalid-xml")]
|
||||
InvalidXml,
|
||||
|
||||
/// The entity has attempted to send XML stanzas or other outbound data
|
||||
/// before the stream has been authenticated, or otherwise is not
|
||||
/// authorized to perform an action related to stream negotiation; the
|
||||
/// receiving entity MUST NOT process the offending data before sending
|
||||
/// the stream error.
|
||||
#[xml(name = "not-authorized")]
|
||||
NotAuthorized,
|
||||
|
||||
/// The initiating entity has sent XML that violates the well-formedness
|
||||
/// rules of [XML](https://www.w3.org/TR/REC-xml/) or
|
||||
/// [XML-NAMES](https://www.w3.org/TR/REC-xml-names/).
|
||||
#[xml(name = "not-well-formed")]
|
||||
NotWellFormed,
|
||||
|
||||
/// The entity has violated some local service policy (e.g., a stanza
|
||||
/// exceeds a configured size limit); the server MAY choose to specify
|
||||
/// the policy in the `<text/>` element or in an application-specific
|
||||
/// condition element.
|
||||
#[xml(name = "policy-violation")]
|
||||
PolicyViolation,
|
||||
|
||||
/// The server is unable to properly connect to a remote entity that is
|
||||
/// needed for authentication or authorization (e.g., in certain
|
||||
/// scenarios related to Server Dialback
|
||||
/// [XEP-0220](https://xmpp.org/extensions/xep-0220.html)); this condition
|
||||
/// is not to be used when the cause of the error is within the
|
||||
/// administrative domain of the XMPP service provider, in which case the
|
||||
/// `<internal-server-error/>` condition is more appropriate.
|
||||
#[xml(name = "remote-connection-failed")]
|
||||
RemoteConnectionFailed,
|
||||
|
||||
/// The server is closing the stream because it has new (typically
|
||||
/// security-critical) features to offer, because the keys or
|
||||
/// certificates used to establish a secure context for the stream have
|
||||
/// expired or have been revoked during the life of the stream
|
||||
/// ([Section 13.7.2.3](https://datatracker.ietf.org/doc/html/rfc6120#section-13.7.2.3)),
|
||||
/// because the TLS sequence number has wrapped
|
||||
/// ([Section 5.3.5](https://datatracker.ietf.org/doc/html/rfc6120#section-5.3.5)),
|
||||
/// etc. The reset applies to the stream and to any security context
|
||||
/// established for that stream (e.g., via TLS and SASL), which means that
|
||||
/// encryption and authentication need to be negotiated again for the new
|
||||
/// stream (e.g., TLS session resumption cannot be used).
|
||||
#[xml(name = "reset")]
|
||||
Reset,
|
||||
|
||||
/// The server lacks the system resources necessary to service the stream.
|
||||
#[xml(name = "resource-constraint")]
|
||||
ResourceConstraint,
|
||||
|
||||
/// The entity has attempted to send restricted XML features such as a
|
||||
/// comment, processing instruction, DTD subset, or XML entity reference
|
||||
/// (see
|
||||
/// [Section 11.1](https://datatracker.ietf.org/doc/html/rfc6120#section-11.1)).
|
||||
#[xml(name = "restricted-xml")]
|
||||
RestrictedXml,
|
||||
|
||||
/// The server will not provide service to the initiating entity but is
|
||||
/// redirecting traffic to another host under the administrative control
|
||||
/// of the same service provider. The XML character data of the
|
||||
/// `<see-other-host/>` element returned by the server MUST specify the
|
||||
/// alternate FQDN or IP address at which to connect, which MUST be a
|
||||
/// valid domainpart or a domainpart plus port number (separated by the
|
||||
/// ':' character in the form "domainpart:port"). If the domainpart is
|
||||
/// the same as the source domain, derived domain, or resolved IPv4 or
|
||||
/// IPv6 address to which the initiating entity originally connected
|
||||
/// (differing only by the port number), then the initiating entity
|
||||
/// SHOULD simply attempt to reconnect at that address. (The format of
|
||||
/// an IPv6 address MUST follow
|
||||
/// [IPv6-ADDR](https://datatracker.ietf.org/doc/html/rfc6120#ref-IPv6-ADDR),
|
||||
/// which includes the enclosing the IPv6 address in square brackets
|
||||
/// '[' and ']' as originally defined by
|
||||
/// [URI](https://datatracker.ietf.org/doc/html/rfc6120#ref-URI).
|
||||
/// ) Otherwise, the initiating entity MUST resolve the FQDN
|
||||
/// specified in the `<see-other-host/>` element as described under
|
||||
/// [Section 3.2](https://datatracker.ietf.org/doc/html/rfc6120#section-3.2).
|
||||
///
|
||||
/// When negotiating a stream with the host to which it has been
|
||||
/// redirected, the initiating entity MUST apply the same policies it
|
||||
/// would have applied to the original connection attempt (e.g., a policy
|
||||
/// requiring TLS), MUST specify the same 'to' address on the initial
|
||||
/// stream header, and MUST verify the identity of the new host using the
|
||||
/// same reference identifier(s) it would have used for the original
|
||||
/// connection attempt (in accordance with
|
||||
/// [TLS-CERTS](https://datatracker.ietf.org/doc/html/rfc6120#ref-TLS-CERTS)).
|
||||
/// Even if the receiving entity returns a `<see-other-host/>` error
|
||||
/// before the confidentiality and integrity of the stream have been
|
||||
/// established (thus introducing the possibility of a denial-of-service
|
||||
/// attack), the fact that the initiating entity needs to verify the
|
||||
/// identity of the XMPP service based on the same reference identifiers
|
||||
/// implies that the initiating entity will not connect to a malicious
|
||||
/// entity. To reduce the possibility of a denial-of-service attack, (a)
|
||||
/// the receiving entity SHOULD NOT close the stream with a
|
||||
/// `<see-other-host/>` stream error until after the confidentiality and
|
||||
/// integrity of the stream have been protected via TLS or an equivalent
|
||||
/// security layer (such as the SASL GSSAPI mechanism), and (b) the
|
||||
/// receiving entity MAY have a policy of following redirects only if it
|
||||
/// has authenticated the receiving entity. In addition, the initiating
|
||||
/// entity SHOULD abort the connection attempt after a certain number of
|
||||
/// successive redirects (e.g., at least 2 but no more than 5).
|
||||
#[xml(name = "see-other-host")]
|
||||
SeeOtherHost(#[xml(text)] String),
|
||||
|
||||
/// The server is being shut down and all active streams are being closed.
|
||||
#[xml(name = "system-shutdown")]
|
||||
SystemShutdown,
|
||||
|
||||
/// The error condition is not one of those defined by the other
|
||||
/// conditions in this list; this error condition SHOULD NOT be used
|
||||
/// except in conjunction with an application-specific condition.
|
||||
#[xml(name = "undefined-condition")]
|
||||
UndefinedCondition,
|
||||
|
||||
/// The initiating entity has encoded the stream in an encoding that is
|
||||
/// not supported by the server (see
|
||||
/// [Section 11.6](https://datatracker.ietf.org/doc/html/rfc6120#section-11.6))
|
||||
/// or has otherwise improperly encoded the stream (e.g., by violating the
|
||||
/// rules of the
|
||||
/// [UTF-8](https://datatracker.ietf.org/doc/html/rfc6120#ref-UTF-8)
|
||||
/// encoding).
|
||||
#[xml(name = "unsupported-encoding")]
|
||||
UnsupportedEncoding,
|
||||
|
||||
/// The receiving entity has advertised a mandatory-to-negotiate stream
|
||||
/// feature that the initiating entity does not support, and has offered
|
||||
/// no other mandatory-to-negotiate feature alongside the unsupported
|
||||
/// feature.
|
||||
#[xml(name = "unsupported-feature")]
|
||||
UnsupportedFeature,
|
||||
|
||||
/// The initiating entity has sent a first-level child of the stream that
|
||||
/// is not supported by the server, either because the receiving entity
|
||||
/// does not understand the namespace or because the receiving entity
|
||||
/// does not understand the element name for the applicable namespace
|
||||
/// (which might be the content namespace declared as the default
|
||||
/// namespace).
|
||||
#[xml(name = "unsupported-stanza-type")]
|
||||
UnsupportedStanzaType,
|
||||
|
||||
/// The 'version' attribute provided by the initiating entity in the
|
||||
/// stream header specifies a version of XMPP that is not supported by
|
||||
/// the server.
|
||||
#[xml(name = "unsupported-version")]
|
||||
UnsupportedVersion,
|
||||
}
|
||||
|
||||
/// Stream error as specified in RFC 6120.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::STREAM, name = "error")]
|
||||
pub struct StreamError {
|
||||
/// The enumerated error condition which triggered this stream error.
|
||||
#[xml(child)]
|
||||
pub condition: DefinedCondition,
|
||||
|
||||
/// Optional error text. The first part is the optional `xml:lang`
|
||||
/// language tag, the second part is the actual text content.
|
||||
#[xml(extract(default, fields(attribute(name = "xml:lang", default, type_ = Option<String>), text(type_ = String))))]
|
||||
pub text: Option<(Option<String>, String)>,
|
||||
|
||||
/// Optional application-defined element which refines the specified
|
||||
/// [`Self::condition`].
|
||||
// TODO: use n = 1 once we have it.
|
||||
#[xml(element(n = ..))]
|
||||
pub application_specific: Vec<Element>,
|
||||
}
|
||||
Loading…
Reference in a new issue