RFC 3920
Extensible Messaging and Presence Protocol (XMPP): Core
RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core ๐
Network Working Group ๐ Editor: P. Saint-Andre, Ed. โจ Organization: Jabber Software Foundation ๐ฆ
Category: Standards Track ๐ธ Date: October 2004 ๐
Okay bestie, let's get the whole vibe set up first. This is RFC 3920, and its title is Extensible Messaging and Presence Protocol (XMPP): Core. It was written by P. Saint-Andre, Ed. from the Jabber Software Foundation. It's on the Standards Track ๐, which means it's a real protocol spec the Internet community is supposed to implement, and it dropped in October 2004 ๐ . The header doesn't list anything it obsoletes or updates, so there's no older RFC it's replacing or patching. Iconic start, no notes ๐
Status of this Memo ๐
So this part is basically the legal disclaimer, but make it cute. This document specifies an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements ๐ซถ If you want the current standardization state and status of this protocol, check the "Internet Official Protocol Standards" (STD 1) document. And distribution of this memo is unlimited, so share the tea freely โจ
Copyright Notice ๐
Copyright (C) The Internet Society (2004). Boring but important, periodt ๐
Abstract ๐ง
Okay the abstract is giving main character energy. This memo defines the core features of the Extensible Messaging and Presence Protocol (XMPP), which is a protocol for streaming Extensible Markup Language (XML) elements so structured info gets exchanged in close to real time between any two network endpoints ๐ XMPP is a generalized, extensible framework for exchanging XML data, but it's mainly used for building instant messaging and presence apps that meet the requirements of RFC 2779 ๐ฆ
Table of Contents ๐๏ธ
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Generalized Architecture . . . . . . . . . . . . . . . . . . 3
3. Addressing Scheme . . . . . . . . . . . . . . . . . . . . . 5
4. XML Streams . . . . . . . . . . . . . . . . . . . . . . . . 7
5. Use of TLS . . . . . . . . . . . . . . . . . . . . . . . . . 19
6. Use of SASL . . . . . . . . . . . . . . . . . . . . . . . . 27
7. Resource Binding . . . . . . . . . . . . . . . . . . . . . . 37
8. Server Dialback . . . . . . . . . . . . . . . . . . . . . . 41
9. XML Stanzas . . . . . . . . . . . . . . . . . . . . . . . . 48
10. Server Rules for Handling XML Stanzas . . . . . . . . . . . 58
11. XML Usage within XMPP . . . . . . . . . . . . . . . . . . . 60
12. Core Compliance Requirements . . . . . . . . . . . . . . . . 62
13. Internationalization Considerations . . . . . . . . . . . . 64
14. Security Considerations . . . . . . . . . . . . . . . . . . 64
15. IANA Considerations . . . . . . . . . . . . . . . . . . . . 69
16. References . . . . . . . . . . . . . . . . . . . . . . . . . 71
A. Nodeprep . . . . . . . . . . . . . . . . . . . . . . . . . . 75
B. Resourceprep . . . . . . . . . . . . . . . . . . . . . . . . 76
C. XML Schemas . . . . . . . . . . . . . . . . . . . . . . . . 78
D. Differences Between Core Jabber Protocols and XMPP . . . . . 87
Contributors. . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Acknowledgements. . . . . . . . . . . . . . . . . . . . . . . . . 89
Author's Address. . . . . . . . . . . . . . . . . . . . . . . . . 89
Full Copyright Statement. . . . . . . . . . . . . . . . . . . . . 90
Here's the map of the whole doc, bestie. It's 90 pages, so we're going to have a long journey ๐บ๏ธ๐
1. Introduction โจ
1.1. Overview
XMPP is an open Extensible Markup Language [XML] protocol for near-real-time messaging, presence, and request-response services ๐ธ The basics were built originally in the Jabber open-source community, mostly in 1999 ๐ฐ๏ธ In 2002, the XMPP WG got chartered to adapt Jabber into something that could work as an IETF instant messaging (IM) and presence technology, and that's the glow-up arc ๐ฆ So this memo defines the core features of XMPP 1.0. The extensions needed for the instant messaging and presence stuff in RFC 2779 [IMP-REQS] live in Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence [XMPP-IM] ๐
1.2. Terminology
Okay, the key words get their own moment ๐ The capitalized key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14, RFC 2119 [TERMS]. Those words are the rules, so they're always gonna be in caps ๐ฅ
2. Generalized Architecture ๐๏ธ
2.1. Overview
XMPP isn't married to any one network architecture ๐ But so far it's usually been done as client-server, where a client using XMPP talks to a server over a [TCP] connection, and servers also talk to each other over TCP connections ๐ซถ
Here's the high-level picture, where "-" means XMPP traffic and "=" means some other protocol ๐
C1----S1---S2---C3
|
C2----+--G1===FN1===FC1
The symbols, lowkey simple but important ๐ง
- C1, C2, C3 = XMPP clients
- S1, S2 = XMPP servers
- G1 = A gateway that translates between XMPP and the protocol(s) used on a foreign (non-XMPP) messaging network
- FN1 = A foreign messaging network
- FC1 = A client on a foreign messaging network
2.2. Server
A server is an intelligent abstraction layer for XMPP communications โจ Its main jobs are:
- to manage connections from or sessions for other entities, in the form of XML streams (Section 4) to and from authorized clients, servers, and other entities
- to route appropriately-addressed XML stanzas (Section 9) among such entities over XML streams
Most XMPP-compliant servers also take on storing data that clients use (like contact lists for IM and presence apps) ๐ In that case, the server processes the XML data itself on the client's behalf, and it doesn't get routed to another entity. Smart, right? ๐ง
2.3. Client
Most clients connect straight to a server over a [TCP] connection and use XMPP to get the full benefit of the server and any services attached to it ๐ Multiple resources (like devices or locations) MAY connect to a server at the same time on behalf of each authorized client ๐ฑ๐ป Each resource gets told apart by the resource identifier of an XMPP address, like <node@domain/ home> vs. <node@domain/work>, as defined under Addressing Scheme (Section 3) ๐ ๐ผ The RECOMMENDED port for client-to-server connections is 5222, as registered with the IANA (see Port Numbers (Section 15.9)) ๐
2.4. Gateway
A gateway is a special-purpose server-side service whose big job is to translate XMPP into the protocol used by a foreign (non-XMPP) messaging system, and then translate the replies back into XMPP ๐ Examples are gateways to email (see [SMTP]), Internet Relay Chat (see [IRC]), SIMPLE (see [SIMPLE]), Short Message Service (SMS), and legacy IM services like AIM, ICQ, MSN Messenger, and Yahoo! Instant Messenger ๐ How gateways talk to servers, and how they talk to the foreign messaging system, is not defined in this document ๐
2.5. Network
Each server has its own network address, and server-to-server communication is a straightforward extension of the client-to-server protocol ๐ So in practice, the system is a network of servers that talk to each other ๐ค For example, <juliet@example.com> can exchange messages, presence, and other info with <romeo@example.net> ๐ This pattern is familiar from messaging protocols (like [SMTP]) that use network addressing standards ๐ฌ Communications between any two servers are OPTIONAL. If you turn them on, they SHOULD happen over XML streams bound to [TCP] connections. The RECOMMENDED port for server-to-server connections is 5269, as registered with the IANA (see Port Numbers (Section 15.9)) ๐โจ
3. Addressing Scheme ๐ฎ
3.1. Overview
An entity is anything that can be considered a network endpoint (basically, an ID on the network) and that can communicate using XMPP ๐ชช All of them are uniquely addressable in a form that's consistent with RFC 2396 [URI]. Historically, the address of an XMPP entity is called a Jabber Identifier or JID ๐ A valid JID is an ordered set of elements made of a domain identifier, a node identifier, and a resource identifier ๐งฉ
The JID syntax is defined below in Augmented Backus-Naur Form, as defined in [ABNF] ๐ค The IPv4address and IPv6address rules are defined in Appendix B of [IPv6]. The allowed character sequences that match the node rule are defined by the Nodeprep profile of [STRINGPREP], as documented in Appendix A of this memo. The allowed character sequences that match the resource rule are defined by the Resourceprep profile of [STRINGPREP], as documented in Appendix B of this memo. And the sub-domain rule refers to an internationalized domain label as described in [IDNA] ๐
jid = [ node "@" ] domain [ "/" resource ]
domain = fqdn / address-literal
fqdn = (sub-domain 1*("." sub-domain))
sub-domain = (internationalized domain label)
address-literal = IPv4address / IPv6address
All JIDs follow that structure โจ The most common use is to identify an IM user, the server they connect to, and their connected resource (like a specific client), in the form <user@host/resource> ๐ But other node types are possible too. For example, a specific chat room on a multi-user chat service could be addressed as <room@service>, where "room" is the chat room's name and "service" is the hostname of the multi-user chat service ๐ And a specific occupant of that room could be <room@service/nick>, where "nick" is their room nickname ๐ Lots of other JID types are possible too. Like, <domain/resource> could be a server-side script or service ๐ค
Each allowed portion of a JID (node identifier, domain identifier, and resource identifier) MUST NOT be more than 1023 bytes long, which makes the max total size, including the '@' and '/' separators, 3071 bytes ๐ That's a hard limit, bestie, no exceptions ๐ โโ๏ธ
Quick reminder: that MUST NOT limit applies to each portion of the JID on its own, and the 3071-byte total includes the separators.
3.2. Domain Identifier
The domain identifier is the primary identifier, and it's the only REQUIRED element of a JID, since a bare domain identifier is already a valid JID ๐ธ It usually stands for the network gateway or "primary" server that other entities connect to for XML routing and data management ๐ฃ๏ธ But the entity behind a domain identifier isn't always a server. It can be a service addressed as a subdomain of a server, one that does more than a server does, like a multi-user chat service, a user directory, or a gateway to a foreign messaging system ๐ง
The domain identifier for every server or service that talks over a network MAY be an IP address, but it SHOULD be a fully qualified domain name (see [DNS]) ๐ A domain identifier MUST be an "internationalized domain name" as defined in [IDNA], and the Nameprep [NAMEPREP] profile of stringprep [STRINGPREP] has to be applicable to it without failing ๐ Before comparing two domain identifiers, a server MUST (and a client SHOULD) first apply the Nameprep profile to the labels (as defined in [IDNA]) that make up each identifier ๐
That's the end of part 1, bestie! ๐ฆ More of the RFC is coming in the next parts, so stay tuned ๐
3.3. Node Identifier ๐
okay so the node identifier is an optional secondary identifier ๐ฆ that goes before the domain identifier, separated from it by the @ character. it usually represents the entity requesting and using network access provided by the server or gateway (aka a client) ๐
, but it can also represent other kinds of entities, like a chat room associated with a multi-user chat service ๐ธ. the entity represented by a node identifier is addressed within the context of a specific domain. within instant messaging and presence apps of XMPP, this address is called a "bare JID" and it looks like <node@domain> โจ
A node identifier MUST be formatted so that the Nodeprep profile of [STRINGPREP] can be applied to it without failing ๐. before comparing two node identifiers, a server MUST (and a client SHOULD) first apply the Nodeprep profile to each identifier ๐.
3.4. Resource Identifier ๐
the resource identifier is an optional tertiary identifier ๐ง that goes after the domain identifier, separated from it by the / character. a resource identifier can modify either a <node@domain> or a plain <domain> address. it usually represents a specific session, connection (like a device or location), or object (like a participant in a multi-user chat room) belonging to the entity associated with a node identifier ๐. a resource identifier is opaque to both servers and other clients, and it's typically defined by a client implementation when it provides the info needed to complete Resource Binding (Section 7). it can also be generated by a server on behalf of a client. once that's done, it's called a "connected resource" ๐. an entity MAY maintain multiple connected resources at the same time, and each one is told apart by a distinct resource identifier ๐.
A resource identifier MUST be formatted so that the Resourceprep profile of [STRINGPREP] can be applied without failing. before comparing two resource identifiers, a server MUST (and a client SHOULD) first apply the Resourceprep profile to each identifier ๐ซถ.
3.5. Determination of Addresses ๐ฅ
after SASL negotiation (Section 6) and, if appropriate, Resource Binding (Section 7), the receiving entity for a stream MUST determine the initiating entity's JID. this part is the main character moment ๐.
for server-to-server communications, the initiating entity's JID SHOULD be the authorization identity, derived from the authentication identity as defined by the Simple Authentication and Security Layer (SASL) specification [SASL], if no authorization identity was specified during SASL negotiation (Section 6) ๐ธ.
for client-to-server communications, the "bare JID" (<node@domain>) SHOULD be the authorization identity, derived from the authentication identity as defined in [SASL], if no authorization identity was specified during SASL negotiation (Section 6). the resource identifier portion of the "full JID" (<node@domain/resource>) SHOULD be the resource identifier negotiated by the client and server during Resource Binding (Section 7) ๐ฆ.
the receiving entity MUST ensure that the resulting JID (including node identifier, domain identifier, resource identifier, and separator characters) conforms to the rules and formats defined earlier in this section ๐ญ. to meet this restriction, the receiving entity may need to replace the JID sent by the initiating entity with the canonicalized JID as determined by the receiving entity ๐ .
4. XML Streams โจ
4.1. Overview ๐
okay bestie, two fundamental concepts make possible the rapid, asynchronous exchange of relatively small payloads of structured information between presence-aware entities: XML streams and XML stanzas ๐ง. here's how they're defined:
Definition of XML Stream: An XML stream is a container for the exchange of XML elements between any two entities over a network ๐. the start of an XML stream is denoted unambiguously by an opening XML <stream> tag (with appropriate attributes and namespace declarations), and the end is denoted unambiguously by a closing XML </stream> tag ๐. during the life of the stream, the entity that initiated it can send an unbounded number of XML elements over the stream. these can be elements used to negotiate the stream (e.g., to negotiate Use of TLS (Section 5) or use of SASL (Section 6)), or XML stanzas (as defined herein: <message/>, <presence/>, or <iq/> elements qualified by the default namespace) ๐
. the "initial stream" is negotiated from the initiating entity (usually a client or server) to the receiving entity (usually a server), and it can be seen as corresponding to the initiating entity's "session" with the receiving entity ๐ฆ. the initial stream enables unidirectional communication from the initiating entity to the receiving entity. so, to enable information exchange the other way, the receiving entity MUST negotiate a stream in the opposite direction (the "response stream") ๐ธ.
Definition of XML Stanza: An XML stanza is a discrete semantic unit of structured information that gets sent from one entity to another over an XML stream ๐. an XML stanza exists at the direct child level of the root <stream/> element, and it's said to be well-balanced if it matches the production [43] content of [XML] ๐. the start of any XML stanza is denoted unambiguously by the element start tag at depth=1 of the XML stream (e.g., <presence>), and the end is denoted unambiguously by the corresponding close tag at depth=1 (e.g., </presence>) โจ. an XML stanza MAY contain child elements (with accompanying attributes, elements, and XML character data) as needed to convey the desired information ๐. the only XML stanzas defined herein are the <message/>, <presence/>, and <iq/> elements qualified by the default namespace for the stream, as described under XML Stanzas (Section 9). an XML element sent for the purpose of Transport Layer Security (TLS) negotiation (Section 5), Simple Authentication and Security Layer (SASL) negotiation (Section 6), or server dialback (Section 8) is NOT considered to be an XML stanza ๐ซถ.
okay so let's look at a client's session with a server ๐. to connect to a server, a client MUST initiate an XML stream by sending an opening <stream> tag to the server. this can optionally be preceded by a text declaration specifying the XML version and the character encoding supported (see Inclusion of Text Declaration (Section 11.4); see also Character Encoding (Section 11.5)) ๐. subject to local policies and service provisioning, the server SHOULD then reply with a second XML stream back to the client, again optionally preceded by a text declaration ๐. once the client has completed SASL negotiation (Section 6), the client MAY send an unbounded number of XML stanzas over the stream to any recipient on the network ๐ฅ. when the client wants to close the stream, it simply sends a closing </stream> tag to the server (or the server can close it instead). after that, both the client and server SHOULD terminate the underlying connection (usually a TCP connection) as well ๐ญ.
if you're used to thinking of XML in a document-centric way, you might like to picture a client's session with a server as two open-ended XML documents ๐ฆ: one from the client to the server and one from the server to the client. from this view, the root <stream/> element is the document entity for each "document", and the two "documents" get built up as XML stanzas are sent over the two XML streams ๐ธ. but that's just a convenience, and XMPP doesn't deal in documents. it deals in XML streams and XML stanzas ๐
.
so, in essence, an XML stream acts as an envelope for all the XML stanzas sent during a session ๐. here's a simplified way to picture it:
|--------------------|
| <stream> |
|--------------------|
| <presence> |
| <show/> |
| </presence> |
|--------------------|
| <message to='foo'> |
| <body/> |
| </message> |
|--------------------|
| <iq to='bar'> |
| <query/> |
| </iq> |
|--------------------|
| ... |
|--------------------|
| </stream> |
|--------------------|
4.2. Binding to TCP ๐ง
okay, so there's no required link between an XML stream and a [TCP] connection. two entities could connect to each other another way, like polling over [HTTP] ๐. still, this specification defines a binding of XMPP to TCP only ๐. in the context of client-to-server communications, a server MUST allow a client to share a single TCP connection for XML stanzas sent from client to server and from server to client ๐. in the context of server-to-server communications, a server MUST use one TCP connection for XML stanzas sent from the server to the peer, and another TCP connection (initiated by the peer) for stanzas going from the peer to the server, for a total of two TCP connections ๐ซถ.
4.3. Stream Security ๐
no cap, this one's serious ๐ญ. when negotiating XML streams in XMPP 1.0, TLS SHOULD be used as defined under Use of TLS (Section 5), and SASL MUST be used as defined under Use of SASL (Section 6) ๐ . the "initial stream" (the stream from the initiating entity to the receiving entity) and the "response stream" (the stream from the receiving entity to the initiating entity) MUST be secured separately ๐ฅ. security in both directions MAY be established via mechanisms that provide mutual authentication, though ๐.
an entity SHOULD NOT attempt to send XML Stanzas (Section 9) over the stream before the stream has been authenticated. but if it does anyway, then the other entity MUST NOT accept those stanzas, and SHOULD return a <not-authorized/> stream error and then terminate both the XML stream and the underlying TCP connection ๐. note well: this applies to XML stanzas only (i.e., <message/>, <presence/>, and <iq/> elements scoped by the default namespace). it does NOT apply to XML elements used for stream negotiation (e.g., elements used to negotiate Use of TLS (Section 5) or Use of SASL (Section 6)) ๐ธ.
4.4. Stream Attributes โจ
okay so the stream element has a bunch of attributes and each one has its own job, so let's go through them bestie ๐ซถ
- to ๐: The
toattribute SHOULD be used only in the XML stream header going from the initiating entity to the receiving entity, and it MUST be set to a hostname that the receiving entity serves. There SHOULD NOT be atoattribute in the header the receiving entity sends back to the initiating entity. But if one does show up, it SHOULD be silently ignored by the initiating entity. - from ๐: The
fromattribute SHOULD be used only in the XML stream header going from the receiving entity to the initiating entity. It MUST be set to a hostname that the receiving entity serves and that is granting access to the initiating entity. There SHOULD NOT be afromattribute on the header the initiating entity sends to the receiving entity. If one is included anyway, it SHOULD be silently ignored by the receiving entity. - id ๐ฆ: The
idattribute SHOULD be used only in the XML stream header going from the receiving entity to the initiating entity. It's a unique identifier the receiving entity makes up to act as a session key for the initiating entity's streams with it, and it MUST be unique within the receiving application (normally a server). Note well, because this one's a big deal: the stream ID may be security-critical, so it MUST be both unpredictable and nonrepeating. (For recommendations on randomness for security purposes, check [RANDOM].) There SHOULD NOT be anidattribute on the header the initiating entity sends to the receiving entity. If one shows up anyway, it SHOULD be silently ignored by the receiving entity. - xml:lang ๐ธ: An
xml:langattribute (as defined in Section 2.12 of [XML]) SHOULD be included by the initiating entity on the header for the initial stream, to say what the default language is for any human-readable XML character data it sends over that stream. If the attribute is included, the receiving entity SHOULD remember that value as the default for both the initial stream and the response stream. If it's not included, the receiving entity SHOULD use a configurable default value for both streams, and it MUST communicate that value in the header for the response stream. For all stanzas sent over the initial stream, if the initiating entity doesn't include anxml:langattribute, the receiving entity SHOULD apply the default value. If the initiating entity does include one, the receiving entity MUST NOT modify or delete it (see also xml:lang (Section 9.1.5)). The value of thexml:langattribute MUST be an NMTOKEN (as defined in Section 2.3 of [XML]) and MUST conform to the format defined in RFC 3066 [LANGTAGS]. - version ๐ง: Having the
versionattribute set to a value of at least "1.0" signals support for the stream-related protocols (including stream features) defined in this specification. The detailed rules for generating and handling this attribute are below.
Here's the cheat sheet, because I know you're going to want it ๐
| initiating to receiving | receiving to initiating
---------+---------------------------+-----------------------
to | hostname of receiver | silently ignored
from | silently ignored | hostname of receiver
id | silently ignored | session key
xml:lang | default language | default language
version | signals XMPP 1.0 support | signals XMPP 1.0 support
4.4.1. Version Support ๐
The version of XMPP in this spec is "1.0". It covers the stream-related protocols (Use of TLS (Section 5), Use of SASL (Section 6), and Stream Errors (Section 4.7)), plus the semantics of the three defined XML stanza types (<message/>, <presence/>, and <iq/>). The numbering scheme is "<major>.<minor>". The major and minor numbers MUST be treated as separate integers, and each one MAY be incremented past a single digit. So "XMPP 2.4" is a lower version than "XMPP 2.13", which is lower than "XMPP 12.3" ๐ฅ. Leading zeros (for example, "XMPP 6.01") MUST be ignored by recipients and MUST NOT be sent.
The major version number should be incremented only if the stream and stanza formats or required actions have changed so dramatically that an older version entity couldn't interoperate with a newer one by just ignoring the elements and attributes it doesn't understand and taking the actions in the older specification. The minor version number is for new capabilities. An entity with a smaller minor version number MUST ignore it, while the entity with the larger minor version number uses it for informational purposes. For example, a minor version number might signal the ability to process a newly defined value of the 'type' attribute for message, presence, or IQ stanzas. The entity with the larger minor version number would just note that its correspondent can't understand that value of 'type', so it wouldn't send it. Iykyk ๐
The following rules apply to how implementations generate and handle the 'version' attribute within stream headers:
- The initiating entity MUST set the value of the 'version' attribute on the initial stream header to the highest version number it supports. (So if the highest it supports is the one defined in this specification, it MUST set the value to "1.0".)
- The receiving entity MUST set the value of the 'version' attribute on the response stream header to either the value the initiating entity supplied or the highest version number the receiving entity supports, whichever is lower. The receiving entity MUST perform a numeric comparison on the major and minor version numbers, not a string match on "
<major>.<minor>". - If the version number in the response stream header is at least one major version lower than the version number in the initial stream header, and newer version entities can't interoperate with older ones as described above, the initiating entity SHOULD generate an
<unsupported-version/>stream error and terminate the XML stream and underlying TCP connection. ๐ - If either entity receives a stream header with no 'version' attribute, the entity MUST consider the other entity's supported version to be "0.0", and it SHOULD NOT include a 'version' attribute in the stream header it sends in reply.
4.5. Namespace Declarations ๐
The stream element MUST possess both a streams namespace declaration and a default namespace declaration (as "namespace declaration" is defined in the XML namespaces specification [XML-NAMES]). For all the details on the streams namespace and the default namespace, see Namespace Names and Prefixes (Section 11.2).
4.6. Stream Features ๐
If the initiating entity includes a 'version' attribute set to at least "1.0" in the initial stream header, the receiving entity MUST send a <features/> child element (prefixed by the streams namespace prefix) to the initiating entity. That's how it announces any stream-level features that can be negotiated (or capabilities that otherwise need advertising). Right now this is only used to advertise Use of TLS (Section 5), Use of SASL (Section 6), and Resource Binding (Section 7) as defined here, plus Session Establishment as defined in [XMPP-IM]. But the stream features functionality could be used for other negotiable features down the line. If an entity doesn't understand or support some features, it SHOULD silently ignore them. And if one or more security features (like TLS and SASL) need to be successfully negotiated before a non-security feature (like Resource Binding) can be offered, that non-security feature SHOULD NOT be included in the stream features advertised before the relevant security features have been negotiated. Security first, bestie ๐
4.7. Stream Errors ๐
The root stream element MAY contain an <error/> child element prefixed by the streams namespace prefix. The error child MUST be sent by a compliant entity (usually a server rather than a client) if it perceives that a stream-level error has occurred.
4.7.1. Rules ๐
Here are the rules for stream-level errors:
- Stream-level errors are assumed to be unrecoverable. So if an error happens at the level of the stream, the entity that detects it MUST send a stream error to the other entity, send a closing
</stream>tag, and terminate the underlying TCP connection. ๐ญ - If the error happens while the stream is being set up, the receiving entity MUST still send the opening
<stream>tag, include the<error/>element as a child of the stream element, send the closing</stream>tag, and terminate the underlying TCP connection. In this case, if the initiating entity gives an unknown host in the 'to' attribute (or doesn't provide a 'to' attribute at all), the server SHOULD provide the server's authoritative hostname in the 'from' attribute of the stream header sent before termination. ๐
4.7.2. Syntax ๐ฆ
The syntax for stream errors looks like this:
<stream:error>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'
xml:lang='langcode'>
OPTIONAL descriptive text
</text>
[OPTIONAL application-specific condition element]
</stream:error>
The <error/> element:
- MUST contain a child element corresponding to one of the defined stanza error conditions defined below. That element MUST be qualified by the 'urn:ietf:params:xml:ns:xmpp-streams' namespace.
- MAY contain a
<text/>child containing XML character data that describes the error in more detail. This element MUST be qualified by the 'urn:ietf:params:xml:ns:xmpp-streams' namespace, and it SHOULD possess an 'xml:lang' attribute specifying the natural language of the XML character data. - MAY contain a child element for an application-specific error condition. That element MUST be qualified by an application-defined namespace, and its structure is defined by that namespace.
The <text/> element is OPTIONAL. If you include it, it SHOULD be used only to give descriptive or diagnostic info that supplements the meaning of a defined condition or application-specific condition. It SHOULD NOT be interpreted programmatically by an application. It SHOULD NOT be used as the error message shown to a user, but it MAY be shown in addition to the error message associated with the included condition element (or elements). โจ
4.7.3. Defined Conditions โจ
okay so here are all the stream-level error conditions that are officially defined, bestie ๐
<bad-format/>: the entity sent XML the server can't process ๐. This one MAY be used instead of the more specific XML errors like<bad-namespace-prefix/>,<invalid-xml/>,<restricted-xml/>,<unsupported-encoding/>, and<xml-not-well-formed/>, but the more specific ones are preferred ๐ .<bad-namespace-prefix/>: the entity used a namespace prefix the server doesn't support, or it left the prefix off an element that needs one (see XML Namespace Names and Prefixes (Section 11.2)) ๐.<conflict/>: the server is closing the active stream for this entity because a new stream came in that clashes with it ๐ฅ.<connection-timeout/>: the entity hasn't sent any traffic over the stream for a while. How long that is depends on the local service policy ๐ฐ๏ธ.<host-gone/>: thetoattribute in the stream header points at a hostname the server doesn't host anymore ๐๏ธ.<host-unknown/>: thetoattribute in the stream header doesn't match any hostname the server hosts ๐คทโโ๏ธ.<improper-addressing/>: a stanza between two servers is missing itstoorfromattribute, or that attribute has no value ๐ญ.<internal-server-error/>: the server has a misconfiguration or some undefined internal error that stops it from servicing the stream ๐ง.<invalid-from/>: the JID or hostname in afromaddress doesn't match an authorized JID or validated domain. That can come from SASL or dialback between servers, or from authentication and resource binding between a client and a server ๐ต๏ธโโ๏ธ.<invalid-id/>: the stream ID or dialback ID is invalid, or it doesn't match one that was given earlier ๐ชช.<invalid-namespace/>: the streams namespace name is anything other than "http://etherx.jabber.org/streams", or the dialback namespace name is anything other than "jabber:server:dialback" (see XML Namespace Names and Prefixes (Section 11.2)) ๐ซ.<invalid-xml/>: the entity sent invalid XML over the stream to a server that does validation (see Validation (Section 11.3)) ๐งพ.<not-authorized/>: the entity tried to send data before the stream was authenticated, or it isn't allowed to do something related to stream negotiation. The receiving entity MUST NOT process the offending stanza before sending the stream error ๐จ. No peeking at the bad stanza, periodt!<policy-violation/>: the entity broke some local service policy. The server MAY choose to spell out the policy in the<text/>element or in an application-specific condition element ๐.<remote-connection-failed/>: the server can't properly connect to a remote entity it needs for authentication or authorization ๐.<resource-constraint/>: the server doesn't have the system resources it needs to service the stream ๐ชซ.<restricted-xml/>: the entity sent restricted XML features, like a comment, processing instruction, DTD, entity reference, or unescaped character (see Restrictions (Section 11.1)) ๐ โโ๏ธ.<see-other-host/>: the server won't serve the initiating entity but is redirecting it to another host. The server SHOULD name the alternate hostname or IP address as the XML character data of the<see-other-host/>element, and that MUST be a valid domain identifier ๐บ๏ธโจ.<system-shutdown/>: the server is shutting down, so all the active streams are closing ๐.<undefined-condition/>: the error isn't one of the other conditions on this list. This error SHOULD only be used together with an application-specific condition ๐ค.<unsupported-encoding/>: the initiating entity encoded the stream in an encoding the server doesn't support (see Character Encoding (Section 11.5)) ๐ค.<unsupported-stanza-type/>: the initiating entity sent a first-level child of the stream that the server doesn't support ๐งฉ.<unsupported-version/>: theversionattribute in the stream header asks for an XMPP version the server doesn't support. The server MAY list the version(s) it does support in the<text/>element ๐ข.<xml-not-well-formed/>: the initiating entity sent XML that isn't well-formed, as defined by [XML] ๐งต.
4.7.4. Application-Specific Conditions ๐
As mentioned before, an application MAY send its own stream error info by adding a child element with its own namespace to the error element. That application-specific element SHOULD add to or further qualify a defined element. So the <error/> element ends up with two or three child elements, like this:
<stream:error>
<xml-not-well-formed
xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
<text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
Some special application diagnostic information!
</text>
<escape-your-data xmlns='application-ns'/>
</stream:error>
</stream:stream>
4.8. Simplified Stream Examples ๐
Okay, this part has two simple examples of a stream-based "session" between a client and a server ๐ง. In them, the "C" lines are what the client sends to the server, and the "S" lines are what the server sends back to the client. They're here to help the concepts we've covered so far click ๐.
Here's a basic "session" ๐ฌ:
C: <?xml version='1.0'?>
<stream:stream
to='example.com'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
S: <?xml version='1.0'?>
<stream:stream
from='example.com'
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
... encryption, authentication, and resource binding ...
C: <message from='juliet@example.com'
to='romeo@example.net'
xml:lang='en'>
C: <body>Art thou not Romeo, and a Montague?</body>
C: </message>
S: <message from='romeo@example.net'
to='juliet@example.com'
xml:lang='en'>
S: <body>Neither, fair saint, if either thee dislike.</body>
S: </message>
C: </stream:stream>
S: </stream:stream>
And here's a "session" that goes totally wrong ๐ญ:
C: <?xml version='1.0'?>
<stream:stream
to='example.com'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
S: <?xml version='1.0'?>
<stream:stream
from='example.com'
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
... encryption, authentication, and resource binding ...
C: <message xml:lang='en'>
<body>Bad XML, no closing body tag!
</message>
S: <stream:error>
<xml-not-well-formed
xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</stream:error>
S: </stream:stream>
5. Use of TLS ๐
5.1. Overview ๐
okay so XMPP has a whole move for keeping the stream safe from tampering and eavesdropping ๐ It's called channel encryption, and it runs on Transport Layer Security (TLS) [TLS] plus a "STARTTLS" extension. That extension is modelled after similar ones in the IMAP [IMAP], POP3 [POP3], and ACAP [ACAP] protocols, as described in RFC 2595 [USINGTLS]. The namespace name for STARTTLS is urn:ietf:params:xml:ns:xmpp-tls โจ
An administrator of a given domain MAY require TLS for client-to-server communications, server-to-server communications, or both ๐ Clients SHOULD use TLS to secure the streams before they try to finish SASL negotiation (Section 6), and servers SHOULD use TLS between two domains to keep server-to-server chats private ๐ซถ
The following rules apply ๐
- An initiating entity that complies with this specification MUST include the
versionattribute set to a value of "1.0" in the initial stream header. - If the TLS negotiation occurs between two servers, communications MUST NOT proceed until the Domain Name System (DNS) hostnames asserted by the servers have been resolved (see Server-to-Server Communications (Section 14.4)).
- When a receiving entity that complies with this specification receives an initial stream header that includes the
versionattribute set to a value of at least "1.0", it MUST, after sending a stream header in reply (including the version flag), include a<starttls/>element (qualified by theurn:ietf:params:xml:ns:xmpp-tlsnamespace) along with the list of other stream features it supports ๐ง - If the initiating entity chooses to use TLS, TLS negotiation MUST be completed before proceeding to SASL negotiation. This order is required to help safeguard authentication information sent during SASL negotiation, and to make it possible to base the use of the SASL EXTERNAL mechanism on a certificate provided during prior TLS negotiation ๐
- During TLS negotiation, an entity MUST NOT send any white space characters (matching production [3] content of [XML]) within the root stream element as separators between elements. Any white space in the TLS examples below is only there for readability. This prohibition helps ensure proper security layer byte precision ๐
- The receiving entity MUST consider the TLS negotiation to have begun immediately after sending the closing
>character of the<proceed/>element. The initiating entity MUST consider the TLS negotiation to have begun immediately after receiving the closing>character of the<proceed/>element from the receiving entity ๐ฆ - The initiating entity MUST validate the certificate presented by the receiving entity. See Certificate Validation (Section 14.2) for the certificate validation procedures ๐ฅ
- Certificates MUST be checked against the hostname as provided by the initiating entity (e.g., a user), not the hostname as resolved via the Domain Name System. For example, if the user specifies a hostname of "example.com" but a DNS SRV [SRV] lookup returned "im.example.com", the certificate MUST be checked as "example.com". If a JID for any kind of XMPP entity (e.g., client or server) is represented in a certificate, it MUST be represented as a UTF8String within an otherName entity inside the subjectAltName, using the [ASN.1] Object Identifier "id-on-xmppAddr" specified in Section 5.1.1 of this document ๐
- If the TLS negotiation is successful, the receiving entity MUST discard any knowledge obtained in an insecure manner from the initiating entity before TLS takes effect ๐
- If the TLS negotiation is successful, the initiating entity MUST discard any knowledge obtained in an insecure manner from the receiving entity before TLS takes effect ๐
- If the TLS negotiation is successful, the receiving entity MUST NOT offer the STARTTLS extension to the initiating entity along with the other stream features that are offered when the stream is restarted ๐
- If the TLS negotiation is successful, the initiating entity MUST continue with SASL negotiation โจ
- If the TLS negotiation results in failure, the receiving entity MUST terminate both the XML stream and the underlying TCP connection ๐ญ
- See Mandatory-to-Implement Technologies (Section 14.7) regarding mechanisms that MUST be supported ๐
5.1.1. ASN.1 Object Identifier for XMPP Address ๐ง
The [ASN.1] Object Identifier "id-on-xmppAddr" from above is defined like this:
id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
id-on OBJECT IDENTIFIER ::= { id-pkix 8 } -- other name forms
id-on-xmppAddr OBJECT IDENTIFIER ::= { id-on 5 }
XmppAddr ::= UTF8String
This Object Identifier MAY also be represented in the dotted display format as "1.3.6.1.5.5.7.8.5" ๐
5.2. Narrative ๐ธ
Okay so here's the play-by-play when an initiating entity secures a stream with a receiving entity using TLS ๐
- The initiating entity opens a TCP connection and starts the stream by sending the opening XML stream header to the receiving entity, including the
versionattribute set to a value of at least "1.0". - The receiving entity responds by opening a TCP connection and sending an XML stream header to the initiating entity, including the
versionattribute set to a value of at least "1.0". - The receiving entity offers the STARTTLS extension to the initiating entity by including it with the list of other supported stream features. If TLS is required for interaction with the receiving entity, it SHOULD signal that by including a
<required/>element as a child of the<starttls/>element ๐ซถ - The initiating entity issues the STARTTLS command (i.e., a
<starttls/>element qualified by theurn:ietf:params:xml:ns:xmpp-tlsnamespace) to tell the receiving entity it wants to start a TLS negotiation to secure the stream ๐ - The receiving entity MUST reply with either a
<proceed/>element or a<failure/>element qualified by theurn:ietf:params:xml:ns:xmpp-tlsnamespace. If the failure case happens, the receiving entity MUST terminate both the XML stream and the underlying TCP connection. If the proceed case happens, the entities MUST attempt to complete the TLS negotiation over the TCP connection, and MUST NOT send any further XML data until the TLS negotiation is complete ๐ฅ - The initiating entity and receiving entity attempt to complete a TLS negotiation in accordance with [TLS] ๐
- If the TLS negotiation is unsuccessful, the receiving entity MUST terminate the TCP connection. If the TLS negotiation is successful, the initiating entity MUST initiate a new stream by sending an opening XML stream header to the receiving entity. It is not necessary to send a closing
</stream>tag first, since the receiving entity and initiating entity MUST consider the original stream to be closed upon successful TLS negotiation โจ - When the receiving entity gets the new stream header from the initiating entity, it MUST respond by sending a new XML stream header to the initiating entity along with the available features (but not including the STARTTLS feature) ๐
5.3. Client-to-Server Example ๐ฆ
Here's the data flow for a client securing a stream using STARTTLS. Note: the alternate steps shown below are there to illustrate the protocol for failure cases. They are not exhaustive, and they would not necessarily be triggered by the data sent in the example ๐
Step 1: Client initiates stream to server:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: Server responds by sending a stream tag to client:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123'
from='example.com'
version='1.0'>
Step 3: Server sends the STARTTLS extension to client along with authentication mechanisms and any other stream features:
<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Step 4: Client sends the STARTTLS command to server:
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5: Server informs client that it is allowed to proceed:
<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5 (alt): Server informs client that TLS negotiation has failed and closes both stream and TCP connection:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
Step 6: Client and server attempt to complete TLS negotiation over the existing TCP connection.
Step 7: If TLS negotiation is successful, client initiates a new stream to server:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 7 (alt): If TLS negotiation is unsuccessful, server closes TCP connection.
Step 8: Server responds by sending a stream header to client along with any available stream features:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='c2s_234'
version='1.0'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
Step 9: Client continues with SASL negotiation (Section 6).
5.4. Server-to-Server Example โจ
okay so this one shows two servers, Server1 and Server2, locking down their stream with STARTTLS ๐ heads up: the alt steps are there to show what happens when stuff goes sideways ๐ญ they aren't a full list of every failure, and the example data won't always trigger them, so don't treat this as the whole story ๐
Step 1: Server1 opens a stream to Server2 ๐
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: Server2 replies with its own stream tag ๐
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_123'
version='1.0'>
Step 3: Server2 sends the STARTTLS extension to Server1, alongside its auth mechanisms and any other stream features โจ
<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>KERBEROS_V4</mechanism>
</mechanisms>
</stream:features>
Step 4: Server1 sends the STARTTLS command to Server2 ๐
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5: Server2 tells Server1 that it's cleared to proceed ๐ฅน
<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Step 5 (alt): Server2 tells Server1 that TLS negotiation has failed, and then closes the stream ๐
<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
Step 6: Server1 and Server2 try to finish TLS negotiation over TCP ๐ค
Step 7: If TLS negotiation works out, Server1 opens a brand new stream to Server2 ๐ฆ
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 7 (alt): If TLS negotiation doesn't work out, Server2 closes the TCP connection ๐
Step 8: Server2 replies with a stream header and any stream features it has available ๐ธ
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_234'
version='1.0'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>KERBEROS_V4</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
Step 9: Server1 keeps going with SASL negotiation (Section 6) ๐
6. Use of SASL โจ
6.1. Overview ๐ฆ
okay so XMPP has its own way of authenticating a stream, and it's built on a profile of the Simple Authentication and Security Layer (SASL) protocol [SASL] ๐ SASL is the general-purpose way of adding auth to connection-based protocols, and XMPP uses a generic XML namespace profile for it that follows the profiling rules in [SASL] ๐
here are the rules that apply ๐
- If the SASL negotiation happens between two servers, communications MUST NOT proceed until the Domain Name System (DNS) hostnames the servers are asserting have been resolved (see Server-to-Server Communications (Section 14.4)) ๐
- If the initiating entity can do SASL negotiation, it MUST include the
'version'attribute, set to a value of at least"1.0", in the initial stream header ๐ - If the receiving entity can do SASL negotiation, it MUST advertise one or more authentication mechanisms inside a
<mechanisms/>element qualified by the'urn:ietf:params:xml:ns:xmpp-sasl'namespace, replying to the opening stream tag it got from the initiating entity (if that opening stream tag had the'version'attribute set to a value of at least"1.0") ๐ฃ - During SASL negotiation, an entity MUST NOT send any white space characters (matching production [3] content of [XML]) inside the root stream element as separators between elements. The white space shown in the SASL examples below is only there so it's easier to read ๐ This rule helps keep the security layer's byte precision intact ๐
- Any XML character data inside the elements used during SASL negotiation MUST be encoded with base64, and the encoding has to follow the definition in Section 3 of RFC 3548 [BASE64] ๐ง
- If the selected SASL mechanism supports a "simple username" (for example, DIGEST-MD5 and CRAM-MD5 do, but EXTERNAL and GSSAPI don't), the initiating entity SHOULD give its sending domain as the simple username during auth (an IP address or fully qualified domain name, as found in a domain identifier) for server-to-server communications. For client-to-server communications, it SHOULD give its registered account name (the user or node name, as found in an XMPP node identifier) instead ๐ซถ
- If the initiating entity wants to act on behalf of another entity, and the selected SASL mechanism can transmit an authorization identity, the initiating entity MUST provide an authorization identity during SASL negotiation. If it doesn't want to act on behalf of anyone else, it MUST NOT provide one. As [SASL] specifies, the initiating entity MUST NOT provide an authorization identity unless it's different from the default one derived from the authentication identity, as described in [SASL]. If one is provided, its value MUST be of the form
<domain>(a domain identifier only) for servers, and of the form<node@domain>(a node identifier plus a domain identifier) for clients ๐ง - After a successful SASL negotiation that includes negotiating a security layer, the receiving entity MUST discard any knowledge it got from the initiating entity that didn't come from the SASL negotiation itself ๐๏ธ
- After a successful SASL negotiation that includes negotiating a security layer, the initiating entity MUST discard any knowledge it got from the receiving entity that didn't come from the SASL negotiation itself ๐งน
- See Mandatory-to-Implement Technologies (Section 14.7) for the mechanisms that MUST be supported ๐
6.2. Narrative ๐ธ
okay so here's the play-by-play ๐ when an initiating entity wants to log in to a receiving entity using SASL, these are the steps:
- The initiating entity asks for SASL by putting the
'version'attribute in its opening XML stream header, set to"1.0"โจ - After the receiving entity sends its own stream header back, it lists the SASL mechanisms it's offering. Each one is a
<mechanism/>element inside a<mechanisms/>container (qualified by theurn:ietf:params:xml:ns:xmpp-saslnamespace), and that container is a child of a<features/>element in the streams namespace. ๐ฆ If Use of TLS (Section 5) has to be set up before a certain mechanism can be used, the receiving entity MUST NOT list that mechanism before TLS negotiation. If the initiating entity showed a valid certificate during that earlier TLS negotiation, the receiving entity SHOULD offer the SASL EXTERNAL mechanism during SASL negotiation (refer to [SASL]), though the EXTERNAL mechanism MAY be offered in other situations too ๐ - The initiating entity picks a mechanism by sending an
<auth/>element (qualified by theurn:ietf:params:xml:ns:xmpp-saslnamespace) to the receiving entity, with a suitable value in the'mechanism'attribute. This element MAY contain XML character data (what SASL calls the "initial response") if the mechanism supports or requires it. If the initiating entity needs to send a zero-length initial response, it MUST send it as a single equals sign"=", which tells the receiver the response is there but has no data ๐ - If it's needed, the receiving entity challenges the initiating entity by sending a
<challenge/>element (qualified by the same namespace). This element MAY contain XML character data, and that data MUST be computed according to the definition of the SASL mechanism the initiating entity chose ๐ฅ - The initiating entity answers the challenge with a
<response/>element (qualified by the same namespace). This element MAY contain XML character data, which MUST also be computed according to the definition of the chosen SASL mechanism ๐ - If it's needed, the receiving entity sends more challenges and the initiating entity sends more responses ๐ง
This challenge/response back-and-forth keeps going until one of three things happens:
- The initiating entity aborts the handshake by sending an
<abort/>element (qualified by theurn:ietf:params:xml:ns:xmpp-saslnamespace). When the receiving entity gets an<abort/>element, it SHOULD allow a configurable but reasonable number of retries (at least 2), and after that it MUST terminate the TCP connection. This lets the initiating entity (e.g., an end-user client) handle incorrectly-provided credentials (e.g., a mistyped password) without being forced to reconnect ๐ - The receiving entity reports failure of the handshake by sending a
<failure/>element (qualified by the same namespace) to the initiating entity. The particular cause of the failure SHOULD be communicated in an appropriate child element of the<failure/>element, as defined under SASL Errors (Section 6.4). If the failure case happens, the receiving entity SHOULD allow a configurable but reasonable number of retries (at least 2), and after that it MUST terminate the TCP connection. Again, this is so the initiating entity (e.g., an end-user client) can tolerate incorrectly-provided credentials (e.g., a mistyped password) without being forced to reconnect ๐ญ - The receiving entity reports success of the handshake by sending a
<success/>element (qualified by the same namespace) to the initiating entity. This element MAY contain XML character data (what SASL calls "additional data with success") if the chosen SASL mechanism requires it. Once the initiating entity receives the<success/>element, it MUST initiate a new stream by sending an opening XML stream header to the receiving entity. It isn't necessary to send a closing</stream>tag first, because the receiving entity and the initiating entity MUST consider the original stream to be closed as soon as either one sends or receives the<success/>element ๐ When the receiving entity gets the new stream header, it MUST respond by sending a new XML stream header to the initiating entity, along with any available features (but not including the STARTTLS and SASL features), or an empty<features/>element (to signify that no additional features are available). Any such additional features that are not defined herein MUST be defined by the relevant extension to XMPP โจ
6.3. SASL Definition ๐
The profiling requirements of [SASL] require that a protocol definition supply the following information:
- service name:
"xmpp" - initiation sequence: After the initiating entity provides an opening XML stream header and the receiving entity replies in kind, the receiving entity provides a list of acceptable authentication methods. The initiating entity chooses one method from that list and sends it to the receiving entity as the value of the
'mechanism'attribute on an<auth/>element, optionally including an initial response to avoid a round trip. ๐ฆ - exchange sequence: Challenges and responses are carried through the exchange of
<challenge/>elements from the receiving entity to the initiating entity, and<response/>elements from the initiating entity to the receiving entity. The receiving entity reports failure by sending a<failure/>element and success by sending a<success/>element. The initiating entity aborts the exchange by sending an<abort/>element. Upon successful negotiation, both sides consider the original XML stream to be closed, and both entities send new stream headers ๐ธ - security layer negotiation: The security layer takes effect immediately after the receiving entity sends the closing
">"character of the<success/>element, and immediately after the initiating entity receives the closing">"character of the<success/>element. The order of layers is first [TCP], then [TLS], then [SASL], then XMPP. ๐ - use of the authorization identity: The authorization identity may be used by xmpp to denote the non-default
<node@domain>of a client, or the sending<domain>of a server. ๐
6.4. SASL Errors ๐
The following SASL-related error conditions are defined:
<aborted/>-- The receiving entity acknowledges an<abort/>element sent by the initiating entity. It is sent in reply to the<abort/>element. ๐<incorrect-encoding/>-- The data provided by the initiating entity could not be processed because the [BASE64] encoding is incorrect (e.g., because the encoding does not adhere to the definition in Section 3 of [BASE64]). It is sent in reply to a<response/>element, or to an<auth/>element with initial response data. ๐<invalid-authzid/>-- The authzid provided by the initiating entity is invalid, either because it is incorrectly formatted, or because the initiating entity does not have permission to authorize that ID. It is sent in reply to a<response/>element, or to an<auth/>element with initial response data. ๐ง<invalid-mechanism/>-- The initiating entity did not provide a mechanism, or requested a mechanism that is not supported by the receiving entity. It is sent in reply to an<auth/>element. ๐ฅ<mechanism-too-weak/>-- The mechanism requested by the initiating entity is weaker than server policy permits for that initiating entity. It is sent in reply to a<response/>element, or to an<auth/>element with initial response data. ๐<not-authorized/>-- The authentication failed because the initiating entity did not provide valid credentials (this includes, but is not limited to, the case of an unknown username). It is sent in reply to a<response/>element, or to an<auth/>element with initial response data. ๐ญ<temporary-auth-failure/>-- The authentication failed because of a temporary error condition within the receiving entity. It is sent in reply to an<auth/>element or a<response/>element. ๐
6.5. Client-to-Server Example โจ
okay bestie, this one shows the whole data flow when a client logs in to a server with SASL, usually right after TLS is set up ๐ heads up: the (alt) steps are there to show what failure looks like ๐ they aren't a full list, and the example data won't always trigger them ๐
Step 1: Client initiates stream to server:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: Server responds with a stream tag sent to client:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_234'
from='example.com'
version='1.0'>
Step 3: Server informs client of available authentication mechanisms:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Step 4: Client selects an authentication mechanism:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: Server sends a [BASE64] encoded challenge to client:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>
The decoded challenge is:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): Server returns error to client:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: Client sends a [BASE64] encoded response to the challenge:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>
The decoded response is:
username="somenode",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.com",\
response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
Step 7: Server sends another [BASE64] encoded challenge to client:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
The decoded challenge is:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): Server returns error to client:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 8: Client responds to the challenge:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: Server informs client of successful authentication:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): Server informs client of failed authentication:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 10: Client initiates a new stream to server:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: Server responds by sending a stream header to client along with any additional features (or an empty features element):
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>
6.6. Server-to-Server Example ๐ฆ
this one is the same vibe but server to server ๐ฅ๏ธ๐ฅ๏ธ one server logs in to another using SASL, again usually after TLS is up ๐ same deal with the (alt) steps: they show failure cases, they aren't exhaustive, and the example data won't necessarily set them off ๐
Step 1: Server1 initiates stream to Server2:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: Server2 responds with a stream tag sent to Server1:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_234'
version='1.0'>
Step 3: Server2 informs Server1 of available authentication mechanisms:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>KERBEROS_V4</mechanism>
</mechanisms>
</stream:features>
Step 4: Server1 selects an authentication mechanism:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: Server2 sends a [BASE64] encoded challenge to Server1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz
</challenge>
The decoded challenge is:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): Server2 returns error to Server1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: Server1 sends a [BASE64] encoded response to the challenge:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j
ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j
PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5v
cmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3
LGNoYXJzZXQ9dXRmLTgK
</response>
The decoded response is:
username="example.org",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.org",\
response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
Step 7: Server2 sends another [BASE64] encoded challenge to Server1:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
The decoded challenge is:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): Server2 returns error to Server1:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<invalid-authzid/>
</failure>
</stream:stream>
Step 8: Server1 responds to the challenge:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 8 (alt): Server1 aborts negotiation:
<abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: Server2 informs Server1 of successful authentication:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): Server2 informs Server1 of failed authentication:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<aborted/>
</failure>
</stream:stream>
Step 10: Server1 initiates a new stream to Server2:
<stream:stream
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: Server2 responds by sending a stream header to Server1 along with any additional features (or an empty features element):
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='s2s_345'
version='1.0'>
<stream:features/>
7. Resource Binding โจ
okay so bestie, after SASL is done (see Section 6) and the receiving entity is happy, the initiating entity MAY want or need to bind a specific resource to that stream ๐ this is mostly a client thing. the addressing format (Section 3) and stanza delivery rules (Section 10) say every client MUST have a resource identifier attached to its <node@domain> ๐ which is either generated by the server or handed over by the client app. that way the address for that stream is a "full JID" that looks like <node@domain/resource> ๐ฆ main character energy, literally.
Once the SASL negotiation reports success, the client MUST send a new stream header to the server ๐ธ and the server MUST answer with its own stream header plus a list of stream features. if the server needs the client to bind a resource after SASL, it MUST include an empty <bind/> element in the urn:ietf:params:xml:ns:xmpp-bind namespace in that features list. it only goes in the header for the response stream sent after successful SASL (and not before) ๐
Server advertises resource binding feature to client:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
So once the client is told binding is required, it MUST bind a resource by sending an IQ stanza of type "set" (see IQ Semantics (Section 9.2.3)) that carries data in the urn:ietf:params:xml:ns:xmpp-bind namespace ๐
If the client wants the server to make up the resource identifier, it sends an IQ "set" with an empty <bind/> element ๐ง
Client asks server to bind a resource:
<iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</iq>
A server that supports resource binding MUST be able to generate a resource identifier for a client ๐ and any resource identifier the server generates MUST be unique for that <node@domain> ๐ซถ
If the client wants to pick its own, it sends an IQ "set" with the resource identifier as the XML character data of a <resource/> child element inside <bind/> ๐
Client binds a resource:
<iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
</iq>
Once the server has either generated a resource identifier or accepted the client's one, it MUST send back an IQ stanza of type "result" ๐ and that result MUST include a <jid/> child element with the full JID for the connected resource, as the server decided it:
Server informs client of successful resource binding:
<iq type='result' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<jid>somenode@example.com/someresource</jid>
</bind>
</iq>
A server SHOULD accept the resource identifier the client gave it ๐ but it MAY override that with one it generates itself. if it does, the server SHOULD NOT send back a stanza error (like <forbidden/>) and instead SHOULD tell the client the generated identifier in the IQ result, just like above โจ
When a client supplies a resource identifier, these stanza error conditions are possible (see Stanza Errors (Section 9.3)) ๐ญ
- The provided resource identifier cannot be processed by the server in accordance with Resourceprep (Appendix B).
- The client is not allowed to bind a resource to the stream (e.g., because the node or user has reached a limit on the number of connected resources allowed).
- The provided resource identifier is already in use but the server does not allow binding of multiple connected resources with the same identifier.
Here's what those error protocols look like ๐
Resource identifier cannot be processed:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
Client is not allowed to bind a resource:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
Resource identifier is in use:
<iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
Last one! If, before resource binding is finished, the client tries to send any XML stanza that isn't an IQ with a <bind/> child in the urn:ietf:params:xml:ns:xmpp-bind namespace, the server MUST NOT process that stanza ๐ซ and SHOULD send back a <not-authorized/> stanza error to the client ๐
8. Server Dialback
8.1. Overview
okay so the Jabber protocols that XMPP grew out of have a "server dialback" method ๐ฆ for guarding against domain spoofing, which makes it harder to fake XML stanzas. but ngl it is NOT a security mechanism ๐ it only gives weak verification of server identities (check Server-to-Server Communications (Section 14.4) for its security vibes). domains that need real security SHOULD use TLS and SASL (again, see Section 14.4) ๐ and if SASL is already doing server-to-server auth, dialback SHOULD NOT be used since it's unnecessary. it's only documented for backward compatibility with existing implementations and deployments ๐ธ
Dialback works because of the Domain Name System (DNS), since one server can (usually) find the authoritative server for a given domain โจ and because dialback depends on DNS, inter-domain communications MUST NOT go ahead until the DNS hostnames asserted by the servers have been resolved (see Section 14.4) ๐ซถ
It's uni-directional ๐ so it gives (weak) verification of identities for one stream in one direction. dialback isn't an authentication mechanism, so mutual authentication isn't possible through it ๐ญ which means server dialback MUST be completed in each direction before two domains can do bi-directional communications ๐
The method for generating and verifying the keys used in dialback MUST take into account the hostnames being used, the stream ID generated by the receiving server, and a secret known by the authoritative server's network ๐ฅ the stream ID is security-critical here, so it MUST be both unpredictable and non-repeating (see [RANDOM] for recommendations on randomness for security purposes) ๐
Any error during dialback negotiation MUST be treated as a stream error, which terminates the stream and the underlying TCP connection ๐ the possible error conditions are in the protocol description below.
Terminology bestie ๐ง
- Originating Server -- the server trying to set up a connection between two domains.
- Receiving Server -- the server trying to verify that the Originating Server really represents the domain it claims to be.
- Authoritative Server -- the server that answers to the DNS hostname asserted by the Originating Server. for basic setups this is the Originating Server itself, but it could be a separate machine in the Originating Server's network ๐
8.2. Order of Events
here's the quick rundown of how dialback goes down ๐
- The Originating Server establishes a connection to the Receiving Server.
- The Originating Server sends a 'key' value over the connection to the Receiving Server.
- The Receiving Server establishes a connection to the Authoritative Server.
- The Receiving Server sends the same 'key' value to the Authoritative Server.
- The Authoritative Server replies that key is valid or invalid.
- The Receiving Server informs the Originating Server whether it is authenticated or not.
and here's the picture of that flow ๐ฆ
Originating Receiving
Server Server
----------- ---------
| |
| establish connection |
| ----------------------> |
| |
| send stream header |
| ----------------------> |
| |
| send stream header |
| <---------------------- |
| | Authoritative
| send dialback key | Server
| ----------------------> | -------------
| | |
| establish connection |
| ----------------------> |
| |
| send stream header |
| ----------------------> |
| |
| send stream header |
| <---------------------- |
| |
| send verify request |
| ----------------------> |
| |
| send verify response |
| <---------------------- |
|
| report dialback result |
| <---------------------- |
| |
8.3. Protocol
okay bestie, this is the full choreography of how the two servers actually talk to each other ๐ it's like a dance, and every step matters ๐ฆ
- The Originating Server establishes a TCP connection to the Receiving Server.
- The Originating Server sends a stream header to the Receiving Server:
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:server'
xmlns:db='jabber:server:dialback'>
Note: the 'to' and 'from' attributes are OPTIONAL on the root stream element ๐ The xmlns:db namespace declaration with exactly that name is how the Receiving Server knows the Originating Server supports dialback โจ If the namespace name is wrong, the Receiving Server MUST generate an <invalid-namespace/> stream error condition and terminate both the XML stream and the underlying TCP connection. ๐
- The Receiving Server SHOULD send a stream header back to the Originating Server, including a unique ID for this interaction ๐ธ
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:server'
xmlns:db='jabber:server:dialback'
id='457F9224A0...'>
Note: the 'to' and 'from' attributes are OPTIONAL on the root stream element. If the namespace name is incorrect, the Originating Server MUST generate an <invalid-namespace/> stream error condition and terminate both the XML stream and the underlying TCP connection. Note well that the Receiving Server SHOULD reply, but it MAY silently terminate the XML stream and underlying TCP connection depending on the security policies it has in place ๐ If it does want to proceed, though, it MUST send a stream header back to the Originating Server.
- The Originating Server sends a dialback key to the Receiving Server:
<db:result
to='Receiving Server'
from='Originating Server'>
98AF014EDC0...
</db:result>
Note: the Receiving Server does not examine this key, because it doesn't keep any info about the Originating Server between sessions ๐ง The key the Originating Server generates MUST be based partly on the ID the Receiving Server gave in the previous step, and partly on a secret shared by the Originating Server and the Authoritative Server ๐ If the 'to' address doesn't match a hostname the Receiving Server recognizes, the Receiving Server MUST generate a <host-unknown/> stream error condition and terminate both the XML stream and the underlying TCP connection. If the 'from' address matches a domain the Receiving Server already has an established connection with, the Receiving Server MUST maintain the existing connection until it validates whether the new one is legit ๐ Also, the Receiving Server MAY choose to generate a <not-authorized/> stream error condition for the new connection, then terminate both the XML stream and the underlying TCP connection tied to that new request. not me giving the old connection the benefit of the doubt ๐ญ
- The Receiving Server establishes a TCP connection back to the domain name the Originating Server asserted. As a result, it connects to the Authoritative Server. (Note: as an optimization, an implementation MAY reuse an existing connection here โป๏ธ)
- The Receiving Server sends the Authoritative Server a stream header:
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:server'
xmlns:db='jabber:server:dialback'>
Note: the 'to' and 'from' attributes are OPTIONAL on the root stream element. If the namespace name is incorrect, the Authoritative Server MUST generate an <invalid-namespace/> stream error condition and terminate both the XML stream and the underlying TCP connection.
- The Authoritative Server sends the Receiving Server a stream header:
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:server'
xmlns:db='jabber:server:dialback'
id='1251A342B...'>
Note: if the namespace name is incorrect, the Receiving Server MUST generate an <invalid-namespace/> stream error condition and terminate both the XML stream and the underlying TCP connection between it and the Authoritative Server. If a stream error happens between the Receiving Server and the Authoritative Server, the Receiving Server MUST generate a <remote-connection-failed/> stream error condition and terminate both the XML stream and the underlying TCP connection between it and the Originating Server ๐๐
- The Receiving Server sends the Authoritative Server a request to verify a key:
<db:verify
from='Receiving Server'
to='Originating Server'
id='457F9224A0...'>
98AF014EDC0...
</db:verify>
Note: the hostnames get passed here, along with the original ID the Receiving Server gave the Originating Server in Step 3, and the key the Originating Server sent in Step 4 ๐๏ธ Based on that info, plus the shared secret inside the Authoritative Server's network, the key gets verified. Any verifiable method MAY be used to generate the key. If the 'to' address doesn't match a hostname the Authoritative Server recognizes, the Authoritative Server MUST generate a <host-unknown/> stream error condition and terminate both the XML stream and the underlying TCP connection. If the 'from' address doesn't match the hostname the Receiving Server used when it opened the TCP connection (or any validated domain under it, like a validated subdomain of the Receiving Server's hostname or another validated domain the Receiving Server hosts), the Authoritative Server MUST generate an <invalid-from/> stream error condition and terminate both the XML stream and the underlying TCP connection ๐ซ
- The Authoritative Server checks whether the key was valid or invalid:
<db:verify
from='Originating Server'
to='Receiving Server'
type='valid'
id='457F9224A0...'/>
or
<db:verify
from='Originating Server'
to='Receiving Server'
type='invalid'
id='457F9224A0...'/>
Note: if the ID doesn't match the one the Receiving Server gave in Step 3, the Receiving Server MUST generate an <invalid-id/> stream error condition and terminate both the XML stream and the underlying TCP connection. If the 'to' address doesn't match a hostname the Receiving Server recognizes, the Receiving Server MUST generate a <host-unknown/> stream error condition and terminate both the XML stream and the underlying TCP connection. If the 'from' address doesn't match the hostname the Originating Server used when it opened the TCP connection (or any validated domain under it, like a validated subdomain of the Originating Server's hostname or another validated domain the Originating Server hosts), the Receiving Server MUST generate an <invalid-from/> stream error condition and terminate both the XML stream and the underlying TCP connection. After sending the verification back to the Receiving Server, the Authoritative Server SHOULD terminate the stream between them ๐
- The Receiving Server tells the Originating Server how it went:
<db:result
from='Receiving Server'
to='Originating Server'
type='valid'/>
Note: at this point the connection has either been validated with a type='valid', or reported as invalid. If it's invalid, the Receiving Server MUST terminate both the XML stream and the underlying TCP connection. If it's validated, data can be sent by the Originating Server and read by the Receiving Server. Before that, though, all XML stanzas sent to the Receiving Server SHOULD be silently dropped ๐ซฅ
The result of all that is that the Receiving Server has verified the identity of the Originating Server. That means the Originating Server can send, and the Receiving Server can accept, XML stanzas over the "initial stream" (the stream from the Originating Server to the Receiving Server) โจ To verify the identities of the entities using the "response stream" (the stream from the Receiving Server back to the Originating Server), dialback MUST be completed in the opposite direction as well ๐
After a successful dialback negotiation, the Receiving Server SHOULD accept later <db:result/> packets (like validation requests sent for a subdomain or another hostname the Receiving Server serves) from the Originating Server over the existing validated connection. This is what "piggybacking" the original validated connection in one direction is all about ๐
Even if dialback negotiation succeeds, a server MUST verify that all XML stanzas received from the other server include a 'from' attribute and a 'to' attribute. If a stanza doesn't meet this, the receiving server MUST generate an <improper-addressing/> stream error condition and terminate both the XML stream and the underlying TCP connection. Furthermore, a server MUST verify that the 'from' attribute of stanzas received from the other server includes a validated domain for the stream. If a stanza doesn't meet this, the receiving server MUST generate an <invalid-from/> stream error condition and terminate both the XML stream and the underlying TCP connection. Both of these checks help prevent spoofing of particular stanzas ๐ก๏ธ๐
9. XML Stanzas โจ
After TLS negotiation (Section 5) if you want it, SASL negotiation (Section 6), and Resource Binding (Section 7) if it's needed, XML stanzas can finally be sent over the streams ๐ Three kinds of XML stanza are defined for the 'jabber:client' and 'jabber:server' namespaces: <message/>, <presence/>, and <iq/>. There are also five common attributes for these kinds of stanza. The common attributes, plus the basic semantics of the three stanza kinds, are defined right here. For more detailed syntax of XML stanzas for instant messaging and presence apps, check out [XMPP-IM] ๐
9.1. Common Attributes
The following five attributes are common to message, presence, and IQ stanzas ๐
9.1.1. to
The 'to' attribute specifies the JID of the intended recipient for the stanza ๐
In the 'jabber:client' namespace, a stanza SHOULD possess a 'to' attribute. However, a stanza a client sends to its server for that server to handle (like presence sent so it can be broadcast to other entities) SHOULD NOT possess a 'to' attribute ๐
In the 'jabber:server' namespace, a stanza MUST possess a 'to' attribute. If a server receives a stanza that doesn't meet this restriction, it MUST generate an <improper-addressing/> stream error condition and terminate both the XML stream and the underlying TCP connection with the offending server ๐
If the 'to' attribute's value is invalid or can't be reached, the entity that discovers this (usually the sender's or recipient's server) MUST return an appropriate error to the sender. It sets the 'from' attribute of the error stanza to the value that was provided in the 'to' attribute of the offending stanza ๐
9.1.2. from ๐
okay bestie, the from attribute tells everyone who sent the stanza. It's the JID of the sender, so it's basically the return address ๐ฎ
When a server gets an XML stanza on an authenticated stream in the jabber:client namespace, it MUST do one of the following:
- validate that the value of the
fromattribute the client gave is that of a connected resource for the associated entity - add a
fromaddress to the stanza. The value is the bare JID (<node@domain>) or the full JID (<node@domain/resource>) that the server figured out for the connected resource that made the stanza (see Determination of Addresses (Section 3.5))
If a client tries to send a stanza whose from doesn't match one of that entity's connected resources, the server SHOULD send back an <invalid-from/> stream error. If a client tries to send a stanza over a stream that isn't authenticated yet, the server SHOULD send back a <not-authorized/> stream error. If either of these happens, the stream MUST be closed and the underlying TCP connection MUST be terminated. This is what keeps a rogue client from launching a denial of service attack ๐
โโ๏ธ
When a server makes a stanza itself to send to a connected client (like when it's running data storage services for the client), that stanza MUST either (1) leave out the from attribute or (2) include a from whose value is the account's bare JID (<node@domain>) or the client's full JID (<node@domain/resource>). A server MUST NOT send a client a stanza without a from attribute if the server didn't generate that stanza itself. When a client gets a stanza with no from, it MUST assume the stanza came from the server it's connected to ๐ซถ
On the jabber:server side, a stanza MUST have a from attribute. If a server gets a stanza without one, it MUST generate an <improper-addressing/> stream error condition. The domain part of the JID in from also MUST match the hostname of the sending server (or any validated domain of it, like a validated subdomain of the sending server's hostname or another validated domain hosted by the sending server), as communicated during SASL negotiation or dialback negotiation. If a server gets a stanza that doesn't meet this, it MUST generate an <invalid-from/> stream error condition. Both of these conditions MUST result in the stream being closed and the underlying TCP connection being terminated. This is how we stop a rogue server from launching a denial of service attack, and it's honestly so important ๐ญ
9.1.3. id ๐ชช
The optional id attribute MAY be used by a sending entity to keep track of stanzas it sends and receives internally. This is especially useful for tracking the request-response interaction that's built into IQ stanzas. It is OPTIONAL for the value of the id attribute to be unique globally, within a domain, or within a stream. IQ semantics add some extra restrictions, so check out IQ Semantics (Section 9.2.3) for those.
9.1.4. type ๐
The type attribute gives the detailed purpose or context of a message, presence, or IQ stanza. Which values are allowed depends on whether the stanza is a message, presence, or IQ. The message and presence values are about instant messaging and presence apps, so they're defined in [XMPP-IM]. The IQ values describe the role of an IQ stanza in a structured request-response "conversation," so those are defined down in IQ Semantics (Section 9.2.3). The only type value that all three stanza kinds share is "error". See Stanza Errors (Section 9.3) ๐จ
9.1.5. xml:lang ๐
A stanza SHOULD have an xml:lang attribute (as defined in Section 2.12 of [XML]) if it contains XML character data that's meant to be shown to a human. This comes from RFC 2277 [CHARSET], which says "internationalization is for humans" ๐ฅน The xml:lang value sets the default language for any of that human-readable character data, and a specific child element MAY override it with its own xml:lang. If a stanza doesn't have an xml:lang attribute, an implementation MUST assume the default language is whatever was set for the stream under Stream Attributes (Section 4.4) above. The value of xml:lang MUST be an NMTOKEN and MUST follow the format defined in RFC 3066 [LANGTAGS]. Yes, the spec is that picky, and I love that for us ๐
9.2. Basic Semantics ๐ง
9.2.1. Message Semantics ๐ฌ
The <message/> stanza is basically a "push" mechanism, where one entity pushes info to another, kind of like email ๐ง All message stanzas SHOULD have a to attribute that says who the intended recipient is. When a server gets one of these, it SHOULD route or deliver it to that recipient (see Server Rules for Handling XML Stanzas (Section 10) for the general routing and delivery rules for XML stanzas).
9.2.2. Presence Semantics ๐ธ
The <presence/> element works like a broadcast or "publish-subscribe" mechanism. Several entities get info about an entity they've subscribed to (here, network availability info) โจ In general, a publishing entity SHOULD send a presence stanza with no to attribute. In that case, the server it's connected to SHOULD broadcast or multiplex the stanza to all the subscribing entities. A publishing entity MAY also send a presence stanza with a to attribute, and then the server SHOULD route or deliver it to that intended recipient. Check out Server Rules for Handling XML Stanzas (Section 10) for the general routing and delivery rules, and [XMPP-IM] for the presence-specific rules in an instant messaging and presence app ๐
9.2.3. IQ Semantics ๐
Info/Query, or IQ, is a request-response mechanism. It's kinda similar to [HTTP] ๐ IQ lets one entity make a request of another entity and get a response back. The data in the request and response is defined by the namespace declaration on a direct child element of the IQ element, and the requesting entity keeps track of the interaction using the id attribute. So IQ interactions follow a common pattern of structured data exchange, like get/result or set/result (though an error can come back in reply to a request if that makes sense):
Requesting Responding
Entity Entity
---------- ----------
| |
| <iq type='get' id='1'> |
| ------------------------> |
| |
| <iq type='result' id='1'> |
| <------------------------ |
| |
| <iq type='set' id='2'> |
| ------------------------> |
| |
| <iq type='error' id='2'> |
| <------------------------ |
| |
To enforce these semantics, the following rules apply:
- The
idattribute is REQUIRED for IQ stanzas. - The
typeattribute is REQUIRED for IQ stanzas. Its value MUST be one of the following:get-- The stanza is a request for information or requirements.set-- The stanza provides required data, sets new values, or replaces existing values.result-- The stanza is a response to a successful get or set request.error-- An error has occurred regarding processing or delivery of a previously-sent get or set (see Stanza Errors (Section 9.3)).
- An entity that receives an IQ request of type
"get"or"set"MUST reply with an IQ response of type"result"or"error"(the response MUST preserve theidattribute of the request). - An entity that receives a stanza of type
"result"or"error"MUST NOT respond to that stanza by sending a further IQ response of type"result"or"error". However, as shown above, the requesting entity MAY send another request (for example, an IQ of type"set"to provide required information it found out through a get/result pair). - An IQ stanza of type
"get"or"set"MUST contain one and only one child element that specifies the semantics of the particular request or response. - An IQ stanza of type
"result"MUST include zero or one child elements. - An IQ stanza of type
"error"SHOULD include the child element from the associated"get"or"set", and MUST include an<error/>child. For details, see Stanza Errors (Section 9.3).
9.3. Stanza Errors ๐ซ
Stanza errors are handled a lot like stream errors (Section 4.7). The big difference is that stanza errors are recoverable, so error stanzas include hints about what the original sender can do to fix the problem ๐ ๏ธ
9.3.1. Rules ๐
The following rules apply to stanza-related errors:
- The receiving or processing entity that detects an error condition related to a stanza MUST return to the sending entity a stanza of the same kind (message, presence, or IQ) whose
typeattribute is set to"error"(such a stanza is called an "error stanza" herein). - The entity that generates an error stanza SHOULD include the original XML that was sent, so the sender can check it out and, if needed, fix the XML before trying again.
- An error stanza MUST contain an
<error/>child element. - An
<error/>child MUST NOT be included if thetypeattribute has a value other than"error"(or if there's notypeattribute at all). - An entity that receives an error stanza MUST NOT respond to it with a further error stanza. This helps prevent looping, and honestly, nobody needs an error loop in their life ๐
9.3.2. Syntax ๐
okay so here's the shape of a stanza error, bestie ๐ it's literally a little envelope with a sticky note inside:
<stanza-kind to='sender' type='error'>
[RECOMMENDED to include sender XML here]
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'
xml:lang='langcode'>
OPTIONAL descriptive text
</text>
[OPTIONAL application-specific condition element]
</error>
</stanza-kind>
The stanza-kind is one of message, presence, or iq. Pick your fighter ๐ฅ
The value of the <error/> element's type attribute MUST be one of the following:
cancel-- do not retry (the error is unrecoverable) ๐continue-- proceed (the condition was only a warning) ๐ธmodify-- retry after changing the data sent โ๏ธauth-- retry after providing credentials ๐wait-- retry after waiting (the error is temporary) โณ
The <error/> element:
- MUST contain a child element corresponding to one of the defined stanza error conditions specified below; this element MUST be qualified by the
urn:ietf:params:xml:ns:xmpp-stanzasnamespace. ๐ - MAY contain a
<text/>child containing XML character data that describes the error in more detail; this element MUST be qualified by theurn:ietf:params:xml:ns:xmpp-stanzasnamespace and SHOULD possess anxml:langattribute. ๐ - MAY contain a child element for an application-specific error condition; this element MUST be qualified by an application-defined namespace, and its structure is defined by that namespace. ๐งฉ
The <text/> element is OPTIONAL. If included, it SHOULD be used only to provide descriptive or diagnostic information that supplements the meaning of a defined condition or application-specific condition. It SHOULD NOT be interpreted programmatically by an application. It SHOULD NOT be used as the error message presented to a user, but MAY be shown in addition to the error message associated with the included condition element (or elements). so it's like the footnote, not the headline ๐
Finally, to maintain backward compatibility, the schema (specified in [XMPP-IM]) allows the optional inclusion of a code attribute on the <error/> element. โจ
9.3.3. Defined Conditions ๐
okay the menu of official error conditions is here, and I'm obsessed with how specific these are ๐ญ the associated error type column is basically the hint for what to do next:
<bad-request/>-- the sender has sent XML that is malformed or that cannot be processed (e.g., an IQ stanza that includes an unrecognized value of thetypeattribute); the associated error type SHOULD be "modify". ๐<conflict/>-- access cannot be granted because an existing resource or session exists with the same name or address; the associated error type SHOULD be "cancel". ๐ซ<feature-not-implemented/>-- the feature requested is not implemented by the recipient or server and therefore cannot be processed; the associated error type SHOULD be "cancel". ๐งฑ<forbidden/>-- the requesting entity does not possess the required permissions to perform the action; the associated error type SHOULD be "auth". ๐<gone/>-- the recipient or server can no longer be contacted at this address (the error stanza MAY contain a new address in the XML character data of the<gone/>element); the associated error type SHOULD be "modify". ๐<internal-server-error/>-- the server could not process the stanza because of a misconfiguration or an otherwise-undefined internal server error; the associated error type SHOULD be "wait". ๐ง<item-not-found/>-- the addressed JID or item requested cannot be found; the associated error type SHOULD be "cancel". ๐<jid-malformed/>-- the sending entity has provided or communicated an XMPP address (e.g., a value of thetoattribute) or aspect thereof (e.g., a resource identifier) that does not adhere to the syntax defined in Addressing Scheme (Section 3); the associated error type SHOULD be "modify". ๐ชช<not-acceptable/>-- the recipient or server understands the request but is refusing to process it because it does not meet criteria defined by the recipient or server (e.g., a local policy regarding acceptable words in messages); the associated error type SHOULD be "modify". ๐<not-allowed/>-- the recipient or server does not allow any entity to perform the action; the associated error type SHOULD be "cancel". โ<not-authorized/>-- the sender must provide proper credentials before being allowed to perform the action, or has provided improper credentials; the associated error type SHOULD be "auth". ๐๏ธ<payment-required/>-- the requesting entity is not authorized to access the requested service because payment is required; the associated error type SHOULD be "auth". ๐ธ<recipient-unavailable/>-- the intended recipient is temporarily unavailable; the associated error type SHOULD be "wait" (note: an application MUST NOT return this error if doing so would provide information about the intended recipient's network availability to an entity that is not authorized to know such information). ๐ this one is a privacy thing, so don't leak anyone's network status ๐ซฃ<redirect/>-- the recipient or server is redirecting requests for this information to another entity, usually temporarily (the error stanza SHOULD contain the alternate address, which MUST be a valid JID, in the XML character data of the<redirect/>element); the associated error type SHOULD be "modify". โช๏ธ<registration-required/>-- the requesting entity is not authorized to access the requested service because registration is required; the associated error type SHOULD be "auth". ๐<remote-server-not-found/>-- a remote server or service specified as part or all of the JID of the intended recipient does not exist; the associated error type SHOULD be "cancel". ๐<remote-server-timeout/>-- a remote server or service specified as part or all of the JID of the intended recipient (or required to fulfill a request) could not be contacted within a reasonable amount of time; the associated error type SHOULD be "wait". ๐ฐ๏ธ<resource-constraint/>-- the server or recipient lacks the system resources necessary to service the request; the associated error type SHOULD be "wait". ๐ง<service-unavailable/>-- the server or recipient does not currently provide the requested service; the associated error type SHOULD be "cancel". ๐ ๏ธ<subscription-required/>-- the requesting entity is not authorized to access the requested service because a subscription is required; the associated error type SHOULD be "auth". ๐๏ธ<undefined-condition/>-- the error condition is not one of those defined by the other conditions in this list; any error type may be associated with this condition, and it SHOULD be used only in conjunction with an application-specific condition. ๐ซฅ<unexpected-request/>-- the recipient or server understood the request but was not expecting it at this time (e.g., the request was out of order); the associated error type SHOULD be "wait". ๐
9.3.4. Application-Specific Conditions ๐ฆ
so an application MAY bring its own error info too, as long as it's properly namespaced and tucked inside the error element. the application-specific element SHOULD supplement or further qualify a defined element, so the <error/> element ends up with two or three child elements. here's what that looks like:
<iq type='error' id='some-id'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<too-many-parameters xmlns='application-ns'/>
</error>
</iq>
<message type='error' id='another-id'>
<error type='modify'>
<undefined-condition
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xml:lang='en'
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
Some special application diagnostic information...
</text>
<special-application-condition xmlns='application-ns'/>
</error>
</message>
10. Server Rules for Handling XML Stanzas ๐
Compliant server implementations MUST ensure in-order processing of XML stanzas between any two entities. in-order, always, no shuffling the queue ๐
Beyond the requirement for in-order processing, each server implementation will contain its own "delivery tree" for handling stanzas it receives. Such a tree determines whether a stanza needs to be routed to another domain, processed internally, or delivered to a resource associated with a connected node. The following rules apply: ๐ณ
10.1. No 'to' Address ๐
If the stanza possesses no to attribute, the server SHOULD process it on behalf of the entity that sent it. Because all stanzas received from other servers MUST possess a to attribute, this rule applies only to stanzas received from a registered entity (such as a client) that is connected to the server. If the server receives a presence stanza with no to attribute, the server SHOULD broadcast it to the entities that are subscribed to the sending entity's presence, if applicable (the semantics of presence broadcast for instant messaging and presence applications are defined in [XMPP-IM]). If the server receives an IQ stanza of type "get" or "set" with no to attribute and it understands the namespace that qualifies the content of the stanza, it MUST either process the stanza on behalf of the sending entity (where the meaning of "process" is determined by the semantics of the qualifying namespace) or return an error to the sending entity. ๐ฎ no to means "it's for me, the sender," and the server handles the rest ๐ซถ
10.2. Foreign Domain ๐
If the hostname of the domain identifier portion of the JID contained in the to attribute does not match one of the configured hostnames of the server itself or a subdomain thereof, the server SHOULD route the stanza to the foreign domain (subject to local service provisioning and security policies regarding inter-domain communication). There are two possible cases: โ๏ธ
- A server-to-server stream already exists between the two domains: The sender's server routes the stanza to the authoritative server for the foreign domain over the existing stream. ๐ค๏ธ
- There exists no server-to-server stream between the two domains: The sender's server (1) resolves the hostname of the foreign domain (as defined under Server-to-Server Communications (Section 14.4)), (2) negotiates a server-to-server stream between the two domains (as defined under Use of TLS (Section 5) and Use of SASL (Section 6)), and (3) routes the stanza to the authoritative server for the foreign domain over the newly-established stream. ๐ค
If routing to the recipient's server is unsuccessful, the sender's server MUST return an error to the sender; if the recipient's server can be contacted but delivery by the recipient's server to the recipient is unsuccessful, the recipient's server MUST return an error to the sender by way of the sender's server. so errors always make the trip back home ๐ฌ
10.3. Subdomain ๐ง
If the hostname of the domain identifier portion of the JID contained in the to attribute matches a subdomain of one of the configured hostnames of the server itself, the server MUST either process the stanza itself or route the stanza to a specialized service that is responsible for that subdomain (if the subdomain is configured), or return an error to the sender (if the subdomain is not configured). ๐
10.4. Mere Domain or Specific Resource ๐ธ
okay so this one's about JIDs that are just a domain (<domain>) or a domain plus a resource (<domain/resource>), no node ๐
. If the hostname part of the to JID matches one of the server's own configured hostnames, then the server (or one of its defined resources) MUST either process the stanza like it normally would for that stanza kind, or send an error stanza back to the sender. no in-between, bestie ๐
10.5. Node in Same Domain ๐ฆ
this is the one for <node@domain> and <node@domain/resource> addresses, where the domain matches one of the server's own hostnames ๐ the server SHOULD deliver the stanza to the person it's meant for, the one the to JID represents. there are three rules for how that goes:
- if the JID has a resource (so it's
<node@domain/resource>) and a connected resource matches that full JID, the recipient's server SHOULD deliver the stanza to the stream or session that matches the resource exactly โจ - if the JID has a resource but NO connected resource matches the full JID, the recipient's server SHOULD send back a
<service-unavailable/>stanza error to the sender ๐ - if the JID is just
<node@domain>and the node has at least one connected resource, the recipient's server SHOULD deliver the stanza to at least one of those resources, following whatever application-specific rules apply (there's a set of delivery rules for instant messaging and presence defined in [XMPP-IM], so go peek at that ๐ง)
11. XML Usage within XMPP ๐
11.1. Restrictions ๐
XMPP is a simplified, specialized protocol for streaming XML elements so people can swap structured info in close to real time โฑ๏ธ it doesn't need to parse every arbitrary XML document out there, so it doesn't have to support the full feature set of [XML]. the following restrictions apply:
When it comes to generating XML, an XMPP implementation MUST NOT inject any of these into an XML stream:
- comments (as defined in Section 2.5 of [XML])
- processing instructions (Section 2.6 therein)
- internal or external DTD subsets (Section 2.8 therein)
- internal or external entity references (Section 4.2 therein) with the exception of predefined entities (Section 4.6 therein)
- character data or attribute values containing unescaped characters that map to the predefined entities (Section 4.6 therein); such characters MUST be escaped
And when it comes to processing XML, if an XMPP implementation receives this kind of restricted XML data, it MUST ignore the data ๐ โโ๏ธ
11.2. XML Namespace Names and Prefixes ๐
[XML-NAMES] namespaces are used all over XMPP-compliant XML to draw strict lines around who owns which data ๐ซถ their whole job is to keep different vocabularies of XML elements separate when they get mixed together in one document. being namespace-aware is what lets any allowable XML get mixed in with any data element inside XMPP. the rules for namespace names and prefixes are in the subsections below โจ
11.2.1. Streams Namespace ๐
a streams namespace declaration is REQUIRED in every XML stream header. the name of the streams namespace MUST be http://etherx.jabber.org/streams. the element names of the <stream/> element and its <features/> and <error/> children MUST be qualified by the streams namespace prefix every single time. an implementation SHOULD only generate the stream: prefix for these elements, and for historical reasons it MAY accept only the stream: prefix ๐
11.2.2. Default Namespace ๐
a default namespace declaration is REQUIRED and gets used in all XML streams to define which first-level children the root stream element is allowed to have ๐ this declaration MUST be the same for the initial stream and the response stream, so both streams are qualified consistently. the default namespace applies to the stream and to all stanzas sent within it, unless something explicitly qualifies them with a different namespace, or with the prefix of the streams namespace or the dialback namespace.
A server implementation MUST support the following two default namespaces (for historical reasons, some implementations MAY support only these two default namespaces):
jabber:client-- this default namespace is declared when the stream is used for communications between a client and a serverjabber:server-- this default namespace is declared when the stream is used for communications between two servers
A client implementation MUST support the jabber:client default namespace, and for historical reasons it MAY support only that one ๐ธ
An implementation MUST NOT generate namespace prefixes for elements in the default namespace if that default namespace is jabber:client or jabber:server. an implementation SHOULD NOT generate namespace prefixes for elements qualified by content namespaces (as opposed to stream namespaces) other than jabber:client and jabber:server ๐
Note: Thejabber:clientandjabber:servernamespaces are nearly identical, but they get used in different contexts (jabber:clientfor client-to-server communications,jabber:serverfor server-to-server communications). the only difference between the two is that thetoandfromattributes are OPTIONAL on stanzas sent withinjabber:client, whereas they are REQUIRED on stanzas sent withinjabber:server. if a compliant implementation accepts a stream qualified by thejabber:clientorjabber:servernamespace, it MUST support the common attributes (Section 9.1) and basic semantics (Section 9.2) of all three core stanza kinds (message, presence, and IQ) ๐ฅ
11.2.3. Dialback Namespace ๐ง
a dialback namespace declaration is REQUIRED for every element used in server dialback (Section 8) ๐ the name of the dialback namespace MUST be jabber:server:dialback. all elements qualified by this namespace MUST be prefixed. an implementation SHOULD only generate the db: prefix for these elements, and it MAY accept only the db: prefix โจ
11.3. Validation ๐ฆ
except for the way 'to' and 'from' addresses get handled for stanzas in the jabber:server namespace, a server isn't responsible for validating the XML elements it forwards to a client or another server ๐
an implementation MAY choose to provide only validated data elements, but that's OPTIONAL (although an implementation MUST NOT accept XML that isn't well-formed, so no sneaking that one through ๐
โโ๏ธ). clients SHOULD NOT count on being able to send data that doesn't conform to the schemas, and they SHOULD ignore any non-conformant elements or attributes on the incoming XML stream. validating XML streams and stanzas is OPTIONAL, and the schemas are only included here for descriptive purposes ๐
11.4. Inclusion of Text Declaration ๐
implementations SHOULD send a text declaration before sending a stream header ๐ซถ applications MUST follow the rules in [XML] about when a text declaration gets included.
11.5. Character Encoding ๐
implementations MUST support the UTF-8 (RFC 3629 [UTF-8]) transformation of Universal Character Set (ISO/IEC 10646-1 [UCS2]) characters, as required by RFC 2277 [CHARSET]. implementations MUST NOT attempt to use any other encoding. no other encodings, periodt ๐
12. Core Compliance Requirements ๐
this section sums up the specific bits of XMPP that servers and clients MUST support to count as compliant implementations, plus the extra protocol aspects they SHOULD support ๐ธ for compliance purposes, there's a split between core protocols (which MUST be supported by any server or client, no matter the application) and instant messaging protocols (which MUST be supported only by instant messaging and presence apps built on the core protocols). the requirements for all servers and clients live right here, and the requirements for instant messaging servers and clients live in the matching section of [XMPP-IM] โจ
12.1. Servers ๐
on top of all the defined requirements for security, XML usage, and internationalization, a server MUST support the following core protocols to be considered compliant:
- Application of the [NAMEPREP], Nodeprep (Appendix A), and Resourceprep (Appendix B) profiles of [STRINGPREP] to addresses (including ensuring that domain identifiers are internationalized domain names as defined in [IDNA])
- XML streams (Section 4), including Use of TLS (Section 5), Use of SASL (Section 6), and Resource Binding (Section 7)
- The basic semantics of the three defined stanza kinds (i.e.,
<message/>,<presence/>, and<iq/>) as specified in stanza semantics (Section 9.2) - Generation (and, where appropriate, handling) of error syntax and semantics related to streams, TLS, SASL, and XML stanzas
In addition, a server MAY support the following core protocol:
- Server dialback (Section 8)
12.2. Clients ๐
a client MUST support the following core protocols to be considered compliant:
- XML streams (Section 4), including Use of TLS (Section 5), Use of SASL (Section 6), and Resource Binding (Section 7)
- The basic semantics of the three defined stanza kinds (i.e.,
<message/>,<presence/>, and<iq/>) as specified in stanza semantics (Section 9.2) - Handling (and, where appropriate, generation) of error syntax and semantics related to streams, TLS, SASL, and XML stanzas
In addition, a client SHOULD support the following core protocols:
- Generation of addresses to which the [NAMEPREP], Nodeprep (Appendix A), and Resourceprep (Appendix B) profiles of [STRINGPREP] can be applied without failing
13. Internationalization Considerations ๐
XML streams MUST be encoded in UTF-8, as specified under Character Encoding (Section 11.5) ๐ซถ as specified under Stream Attributes (Section 4.4), an XML stream SHOULD include an xml:lang attribute, which is treated as the default language for any XML character data sent over the stream that's meant to be shown to a human user ๐ธ as specified under xml:lang (Section 9.1.5), an XML stanza SHOULD include an xml:lang attribute if the stanza has XML character data meant for a human user to see โจ a server SHOULD apply the default xml:lang attribute to stanzas it routes or delivers on behalf of connected entities, and it MUST NOT modify or delete xml:lang attributes on stanzas it receives from other entities. the language tags stay put, bestie ๐ณ๏ธโ๐
14. Security Considerations ๐ฅ
14.1. High Security ๐
Okay so for XMPP chats (client-to-server AND server-to-server), "high security" means using security tech that gives you BOTH mutual authentication AND integrity-checking โจ. When you're doing certificate-based auth for high security, a chain-of-trust SHOULD be established out-of-band ๐. A shared certificate authority signing certs could let a previously unknown cert build trust in-band though, which is so clever ๐ง . See Section 14.2 below for the cert validation stuff ๐
Implementations MUST support high security. Service provisioning SHOULD use high security, subject to local security policies ๐ซถ
14.2. Certificate Validation ๐ชช
Bestie, this is the big one ๐ญ. When an XMPP peer talks to another peer securely, it MUST validate the peer's certificate. There are three possible cases:
- Case #1: The peer contains an End Entity certificate which appears to be certified by a chain of certificates terminating in a trust anchor (as described in Section 6.1 of [X509]).
- Case #2: The peer certificate is certified by a Certificate Authority not known to the validating peer.
- Case #3: The peer certificate is self-signed.
In Case #1, the validating peer MUST do one of two things ๐:
- Verify the peer certificate according to the rules of [X509]. The certificate SHOULD then be checked against the expected identity of the peer following the rules described in [HTTP-TLS], except that a
subjectAltNameextension of type"xmpp"MUST be used as the identity if present. If one of these checks fails, user-oriented clients MUST either notify the user (clients MAY give the user the opportunity to continue with the connection in any case) or terminate the connection with a bad certificate error. Automated clients SHOULD terminate the connection (with a bad certificate error) and log the error to an appropriate audit log. Automated clients MAY provide a configuration setting that disables this check, but MUST provide a setting that enables it. ๐ - The peer SHOULD show the certificate to a user for approval, including the entire certificate chain. The peer MUST cache the certificate (or some non-forgeable representation such as a hash). In future connections, the peer MUST verify that the same certificate was presented and MUST notify the user if it has changed. ๐ธ
In Case #2 and Case #3, implementations SHOULD act as in (2) above ๐ฆ
14.3. Client-to-Server Communications ๐ฑ
A compliant client implementation MUST support both TLS and SASL for connections to a server. Slay ๐
The TLS protocol for encrypting XML streams (defined under Use of TLS (Section 5)) provides a reliable mechanism for helping to ensure the confidentiality and data integrity of data exchanged between two entities ๐
The SASL protocol for authenticating XML streams (defined under Use of SASL (Section 6)) provides a reliable mechanism for validating that a client connecting to a server is who it claims to be ๐ชช
Client-to-server communications MUST NOT proceed until the DNS hostname asserted by the server has been resolved. Such resolutions SHOULD first attempt to resolve the hostname using an [SRV] Service of "xmpp-client" and Proto of "tcp", resulting in resource records such as _xmpp-client._tcp.example.com. (the use of the string "xmpp-client" for the service identifier is consistent with the IANA registration). If the SRV lookup fails, the fallback is a normal IPv4/IPv6 address record resolution to determine the IP address, using the "xmpp-client" port of 5222, registered with the IANA ๐ง
The IP address and method of access of clients MUST NOT be made public by a server, nor are any connections other than the original server connection required. This helps to protect the client's server from direct attack or identification by third parties. Main character protection energy ๐ก๏ธ
14.4. Server-to-Server Communications ๐
A compliant server implementation MUST support both TLS and SASL for inter-domain communications. For historical reasons, a compliant implementation SHOULD also support Server Dialback (Section 8) ๐ฐ๏ธ
Because service provisioning is a matter of policy, it is OPTIONAL for any given domain to communicate with other domains, and server-to-server communications MAY be disabled by the administrator of any given deployment. If a particular domain enables inter-domain communications, it SHOULD enable high security ๐
Administrators may want to require use of SASL for server-to-server communications in order to ensure both authentication and confidentiality (e.g., on an organization's private network). Compliant implementations SHOULD support SASL for this purpose ๐
Inter-domain connections MUST NOT proceed until the DNS hostnames asserted by the servers have been resolved. Such resolutions MUST first attempt to resolve the hostname using an [SRV] Service of "xmpp-server" and Proto of "tcp", resulting in resource records such as _xmpp-server._tcp.example.com. (the use of the string "xmpp-server" for the service identifier is consistent with the IANA registration; note well that the "xmpp-server" service identifier supersedes the earlier use of a "jabber" service identifier, since the earlier usage did not conform to [SRV]; implementations desiring to be backward compatible should continue to look for or answer to the "jabber" service identifier as well). If the SRV lookup fails, the fallback is a normal IPv4/IPv6 address record resolution to determine the IP address, using the "xmpp-server" port 5269, registered with the IANA ๐ฎ
Server dialback helps protect against domain spoofing, thus making it more difficult to spoof XML stanzas. It is not a mechanism for authenticating, securing, or encrypting streams between servers as is done via SASL and TLS, and results in weak verification of server identities only. Furthermore, it is susceptible to DNS poisoning attacks unless DNSSec [DNSSEC] is used, and even if the DNS information is accurate, dialback cannot protect from attacks where the attacker is capable of hijacking the IP address of the remote domain. Domains requiring robust security SHOULD use TLS and SASL. If SASL is used for server-to-server authentication, dialback SHOULD NOT be used since it is unnecessary. ๐จ
14.5. Order of Layers ๐ฅ
The order of layers in which protocols MUST be stacked is as follows:
- TCP
- TLS
- SASL
- XMPP
The rationale for this order is that [TCP] is the base connection layer used by all of the protocols stacked on top of TCP, [TLS] is often provided at the operating system layer, [SASL] is often provided at the application layer, and XMPP is the application itself โจ
14.6. Lack of SASL Channel Binding to TLS ๐
The SASL framework does not provide a mechanism to bind SASL authentication to a security layer providing confidentiality and integrity protection that was negotiated at a lower layer. This lack of a "channel binding" prevents SASL from being able to verify that the source and destination end points to which the lower layer's security is bound are equivalent to the end points that SASL is authenticating. If the end points are not identical, the lower layer's security cannot be trusted to protect data transmitted between the SASL authenticated entities. In such a situation, a SASL security layer should be negotiated that effectively ignores the presence of the lower layer security. Okay this one is a lot, but it's giving important ๐
14.7. Mandatory-to-Implement Technologies ๐
At a minimum, all implementations MUST support the following mechanisms:
- for authentication: the SASL [DIGEST-MD5] mechanism
- for confidentiality: TLS (using the
TLS_RSA_WITH_3DES_EDE_CBC_SHAcipher) - for both: TLS plus SASL EXTERNAL(using the
TLS_RSA_WITH_3DES_EDE_CBC_SHAcipher supporting client-side certificates)
14.8. Firewalls ๐งฑ
Communications using XMPP normally occur over [TCP] connections on port 5222 (client-to-server) or port 5269 (server-to-server), as registered with the IANA (see IANA Considerations (Section 15)). Use of these well-known ports allows administrators to easily enable or disable XMPP activity through existing and commonly-deployed firewalls. Very organized, very iconic ๐
14.9. Use of base64 in SASL ๐ง
Both the client and the server MUST verify any [BASE64] data received during SASL negotiation. An implementation MUST reject (not ignore) any characters that are not explicitly allowed by the base64 alphabet; this helps to guard against creation of a covert channel that could be used to "leak" information. An implementation MUST NOT break on invalid input and MUST reject any sequence of base64 characters containing the pad ('=') character if that character is included as something other than the last character of the data (e.g., "=AAA" or "BBBB=CCC"); this helps to guard against buffer overflow attacks and other attacks on the implementation. Base 64 encoding visually hides otherwise easily recognized information, such as passwords, but does not provide any computational confidentiality. Base 64 encoding MUST follow the definition in Section 3 of RFC 3548 [BASE64]. Hiding is not the same as locking, babe ๐๐
14.10. Stringprep Profiles ๐งต
XMPP makes use of the [NAMEPREP] profile of [STRINGPREP] for the processing of domain identifiers; for security considerations related to Nameprep, refer to the appropriate section of [NAMEPREP].
In addition, XMPP defines two profiles of [STRINGPREP]: Nodeprep (Appendix A) for node identifiers and Resourceprep (Appendix B) for resource identifiers.
The Unicode and ISO/IEC 10646 repertoires have many characters that look similar. In many cases, users of security protocols might do visual matching, such as when comparing the names of trusted third parties. Because it is impossible to map similar-looking characters without a great deal of context, such as knowing the fonts used, stringprep does nothing to map similar-looking characters together, nor to prohibit some characters because they look like others. Lookalike characters are a whole mood ๐
A node identifier can be employed as one part of an entity's address in XMPP. One common usage is as the username of an instant messaging user; another is as the name of a multi-user chat room; many other kinds of entities could use node identifiers as part of their addresses. The security of such services could be compromised based on different interpretations of the internationalized node identifier; for example, a user entering a single internationalized node identifier could access another user's account information, or a user could gain access to an otherwise restricted chat room or service. ๐ซ
A resource identifier can be employed as one part of an entity's address in XMPP. One common usage is as the name for an instant messaging user's connected resource (active session); another is as the nickname of a user in a multi-user chat room; many other kinds of entities could use resource identifiers as part of their addresses. The security of such services could be compromised based on different interpretations of the internationalized resource identifier; for example, a user could attempt to initiate multiple sessions with the same name, or a user could send a message to someone other than the intended recipient in a multi-user chat room. Not me misreading a chat room nickname ๐
15. IANA Considerations ๐
15.1. XML Namespace Name for TLS Data ๐
okay so the IANA gets a URN sub-namespace for the TLS stuff in XMPP ๐ it's the namespace for TLS-related data, and it follows the format from The IETF XML Registry [XML-REG]. the whole thing is basically a little ID card for the TLS bits โจ
URI: urn:ietf:params:xml:ns:xmpp-tls
Specification: RFC 3920
Description: This is the XML namespace name for TLS-related data in
the Extensible Messaging and Presence Protocol (XMPP) as defined
by RFC 3920.
Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>
15.2. XML Namespace Name for SASL Data ๐ธ
same energy but for SASL ๐ซถ this sub-namespace is for the SASL-related data in XMPP, and it also follows the format in [XML-REG] (no cap, the registry is doing a lot of work here ๐ )
URI: urn:ietf:params:xml:ns:xmpp-sasl
Specification: RFC 3920
Description: This is the XML namespace name for SASL-related data in
the Extensible Messaging and Presence Protocol (XMPP) as defined
by RFC 3920.
Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>
15.3. XML Namespace Name for Stream Errors ๐ฆ
this one is for the stream-related error data ๐ญ when a stream goes sideways, this is the namespace that tells you what went wrong. it also adheres to the format in [XML-REG] ๐ซ
URI: urn:ietf:params:xml:ns:xmpp-streams
Specification: RFC 3920
Description: This is the XML namespace name for stream-related error
data in the Extensible Messaging and Presence Protocol (XMPP) as
defined by RFC 3920.
Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>
15.4. XML Namespace Name for Resource Binding ๐ง
resource binding gets its own namespace too โจ it's the URN sub-namespace for it in XMPP, again following the format from [XML-REG]. the group is literally thorough about everything ๐
URI: urn:ietf:params:xml:ns:xmpp-bind
Specification: RFC 3920
Description: This is the XML namespace name for resource binding in
the Extensible Messaging and Presence Protocol (XMPP) as defined
by RFC 3920.
Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>
15.5. XML Namespace Name for Stanza Errors ๐
last one in this batch: stanza-related error data gets its namespace here ๐ it sticks to the format in [XML-REG], so every namespace is consistent (iconic behaviour, honestly ๐)
URI: urn:ietf:params:xml:ns:xmpp-stanzas
Specification: RFC 3920
Description: This is the XML namespace name for stanza-related error
data in the Extensible Messaging and Presence Protocol (XMPP) as
defined by RFC 3920.
Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>
15.6. Nodeprep Profile of Stringprep ๐
the Nodeprep profile of stringprep is spelled out under Nodeprep (Appendix A) ๐ฅ and IANA has registered it in the stringprep profile registry. so yeah, it's officially on the list โจ
Name of this profile:
Nodeprep
RFC in which the profile is defined:
RFC 3920
Indicator whether or not this is the newest version of the profile:
This is the first version of Nodeprep
15.7. Resourceprep Profile of Stringprep โญ
same deal for Resourceprep ๐ the profile is defined under Resourceprep (Appendix B), and IANA registered it in the stringprep profile registry. the sibling profile gets the spotlight too ๐ซถ
Name of this profile:
Resourceprep
RFC in which the profile is defined:
RFC 3920
Indicator whether or not this is the newest version of the profile:
This is the first version of Resourceprep
15.8. GSSAPI Service Name ๐
IANA registered "xmpp" as a GSSAPI [GSS-API] service name ๐ the definition lives under SASL Definition (Section 6.3), so that's where you go if you want the details ๐ญ
15.9. Port Numbers ๐ช
IANA registered "xmpp-client" and "xmpp-server" as keywords for [TCP] ports 5222 and 5269 respectively ๐
these ports SHOULD be used for client-to-server and server-to-server communications respectively, but their use is OPTIONAL. so it's a strong suggestion, not a hard rule ๐
16. References ๐
16.1. Normative References ๐งพ
[ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 2234, November 1997.
[BASE64] Josefsson, S., "The Base16, Base32, and Base64 Data
Encodings", RFC 3548, July 2003.
[CHARSET] Alvestrand, H., "IETF Policy on Character Sets and
Languages", BCP 18, RFC 2277, January 1998.
[DIGEST-MD5] Leach, P. and C. Newman, "Using Digest Authentication as
a SASL Mechanism", RFC 2831, May 2000.
[DNS] Mockapetris, P., "Domain names - implementation and
specification", STD 13, RFC 1035, November 1987.
[GSS-API] Linn, J., "Generic Security Service Application Program
Interface Version 2, Update 1", RFC 2743, January 2000.
[HTTP-TLS] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
[IDNA] Faltstrom, P., Hoffman, P., and A. Costello,
"Internationalizing Domain Names in Applications
(IDNA)", RFC 3490, March 2003.
[IPv6] Hinden, R. and S. Deering, "Internet Protocol Version 6
(IPv6) Addressing Architecture", RFC 3513, April 2003.
[LANGTAGS] Alvestrand, H., "Tags for the Identification of
Languages", BCP 47, RFC 3066, January 2001.
[NAMEPREP] Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep
Profile for Internationalized Domain Names (IDN)", RFC
3491, March 2003.
[RANDOM] Eastlake 3rd, D., Crocker, S., and J. Schiller,
"Randomness Recommendations for Security", RFC 1750,
December 1994.
[SASL] Myers, J., "Simple Authentication and Security Layer
(SASL)", RFC 2222, October 1997.
[SRV] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
specifying the location of services (DNS SRV)", RFC
2782, February 2000.
[STRINGPREP] Hoffman, P. and M. Blanchet, "Preparation of
Internationalized Strings ("stringprep")", RFC 3454,
December 2002.
[TCP] Postel, J., "Transmission Control Protocol", STD 7, RFC
793, September 1981.
[TERMS] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
RFC 2246, January 1999.
[UCS2] International Organization for Standardization,
"Information Technology - Universal Multiple-octet coded
Character Set (UCS) - Amendment 2: UCS Transformation
Format 8 (UTF-8)", ISO Standard 10646-1 Addendum 2,
October 1996.
[UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO
10646", STD 63, RFC 3629, November 2003.
[X509] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet
X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile", RFC 3280,
April 2002.
[XML] Bray, T., Paoli, J., Sperberg-McQueen, C., and E. Maler,
"Extensible Markup Language (XML) 1.0 (2nd ed)", W3C
REC-xml, October 2000, <http://www.w3.org/TR/REC-xml>.
[XML-NAMES] Bray, T., Hollander, D., and A. Layman, "Namespaces in
XML", W3C REC-xml-names, January 1999,
<http://www.w3.org/TR/REC-xml-names>.
16.2. Informative References ๐ซ
[ACAP] Newman, C. and J. Myers, "ACAP -- Application
Configuration Access Protocol", RFC 2244, November 1997.
[ASN.1] CCITT, "Recommendation X.208: Specification of Abstract
Syntax Notation One (ASN.1)", 1988.
[DNSSEC] Eastlake 3rd, D., "Domain Name System Security
Extensions", RFC 2535, March 1999.
[HTTP] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[IMAP] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION
4rev1", RFC 3501, March 2003.
[IMP-REQS] Day, M., Aggarwal, S., Mohr, G., and J. Vincent,
"Instant Messaging / Presence Protocol Requirements",
RFC 2779, February 2000.
[IRC] Oikarinen, J. and D. Reed, "Internet Relay Chat
Protocol", RFC 1459, May 1993.
[JEP-0029] Kaes, C., "Definition of Jabber Identifiers (JIDs)", JSF
JEP 0029, October 2003.
[JEP-0078] Saint-Andre, P., "Non-SASL Authentication", JSF JEP
0078, July 2004.
[JEP-0086] Norris, R. and P. Saint-Andre, "Error Condition
Mappings", JSF JEP 0086, February 2004.
[JSF] Jabber Software Foundation, "Jabber Software
Foundation", <http://www.jabber.org/>.
[POP3] Myers, J. and M. Rose, "Post Office Protocol - Version
3", STD 53, RFC 1939, May 1996.
[SIMPLE] SIMPLE Working Group, "SIMPLE WG",
<http://www.ietf.org/html.charters/simple-charter.html>.
[SMTP] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
April 2001.
[URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifiers (URI): Generic Syntax", RFC 2396,
August 1998.
[USINGTLS] Newman, C., "Using TLS with IMAP, POP3 and ACAP", RFC
2595, June 1999.
[XML-REG] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688,
January 2004.
[XMPP-IM] Saint-Andre, P., Ed., "Extensible Messaging and Presence
Protocol (XMPP): Instant Messaging and Presence", RFC
3921, October 2004.
Appendix A. Nodeprep ๐ท
A.1. Introduction ๐ฌ
this appendix defines the "Nodeprep" profile of [STRINGPREP] โจ basically it's a set of processing rules that helps users type internationalized node identifiers in XMPP and gives them the best shot at getting the string right ๐ (a node identifier is the optional part of an XMPP address that comes before the domain and the '@'. it's often, but not always, tied to an IM username ๐ซถ)
these rules are only for XMPP node identifiers. they aren't meant for arbitrary text or any other part of an XMPP address, so don't go applying them everywhere ๐ โโ๏ธ
this profile defines the following, as required by [STRINGPREP]:
- The intended applicability of the profile: internationalized node identifiers within XMPP
- The character repertoire that is the input and output to stringprep: Unicode 3.2, specified in Section 2 of this Appendix
- The mappings used: specified in Section 3
- The Unicode normalization used: specified in Section 4
- The characters that are prohibited as output: specified in Section 5
- Bidirectional character handling: specified in Section 6
A.2. Character Repertoire ๐ค
this profile uses Unicode 3.2, and the list of unassigned code points is Table A.1. both are defined in Appendix A of [STRINGPREP] ๐
A.3. Mapping ๐บ๏ธ
this profile specifies mapping using the following tables from [STRINGPREP]:
Table B.1
Table B.2
A.4. Normalization โจ
this profile specifies the use of Unicode normalization form KC, as described in [STRINGPREP] ๐
A.5. Prohibited Output ๐ซ
Okay so this profile straight up bans using the following tables from [STRINGPREP]. No exceptions, bestie ๐
Table C.1.1
Table C.1.2
Table C.2.1
Table C.2.2
Table C.3
Table C.4
Table C.5
Table C.6
Table C.7
Table C.8
Table C.9
And on top of that, these Unicode characters are also off the menu ๐ โโ๏ธ
#x22 (")
#x26 (&)
#x27 (')
#x2F (/)
#x3A (:)
#x3C (<)
#x3E (>)
#x40 (@)
A.6. Bidirectional Characters ๐
This profile says we check bidirectional strings, the way Section 6 of [STRINGPREP] describes. It's giving careful and organised ๐ง
Appendix B. Resourceprep ๐
B.1. Introduction ๐ธ
Okay so this appendix defines the "Resourceprep" profile of [STRINGPREP]. Basically it's a set of processing rules that help users type internationalized resource identifiers in the Extensible Messaging and Presence Protocol (XMPP), and gives them the best shot at getting the string's content right โจ (Quick reminder: an XMPP resource identifier is the optional bit of an XMPP address that comes after a domain identifier and the '/' separator. It's often, but not always, linked to an instant messaging session name ๐ฌ) These rules are only meant for XMPP resource identifiers. They are NOT meant for random text or any other part of an XMPP address, so don't go applying them there ๐ โโ๏ธ
This profile defines the following, as [STRINGPREP] requires:
- The intended applicability of the profile: internationalized resource identifiers within XMPP ๐
- The character repertoire that is the input and output to stringprep: Unicode 3.2, specified in Section 2 of this Appendix ๐
- The mappings used: specified in Section 3 ๐บ๏ธ
- The Unicode normalization used: specified in Section 4 ๐ซถ
- The characters that are prohibited as output: specified in Section 5 ๐ซ
- Bidirectional character handling: specified in Section 6 ๐
B.2. Character Repertoire ๐
This profile uses Unicode 3.2, with the list of unassigned code points being Table A.1. Both of these are defined in Appendix A of [STRINGPREP] ๐
B.3. Mapping ๐บ๏ธ
This profile specifies mapping using the following tables from [STRINGPREP]:
Table B.1
B.4. Normalization ๐ง
This profile uses Unicode normalization form KC, as described in [STRINGPREP]. Main character energy ๐
B.5. Prohibited Output ๐ซ
This profile prohibits the use of the following tables from [STRINGPREP]. Note that Table B.1 is not on this list, because it's the mapping table ๐
Table C.1.2
Table C.2.1
Table C.2.2
Table C.3
Table C.4
Table C.5
Table C.6
Table C.7
Table C.8
Table C.9
B.6. Bidirectional Characters ๐
This profile checks bidirectional strings as described in Section 6 of [STRINGPREP]. Iykyk ๐ฆ
Appendix C. XML Schemas ๐
Heads up, bestie: these XML schemas are descriptive, not normative ๐ค If you need the schemas for the 'jabber:client' and 'jabber:server' namespaces, go check [XMPP-IM] ๐
C.1. Streams namespace ๐
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://etherx.jabber.org/streams'
xmlns='http://etherx.jabber.org/streams'
elementFormDefault='unqualified'>
<xs:element name='stream'>
<xs:complexType>
<xs:sequence xmlns:client='jabber:client'
xmlns:server='jabber:server'
xmlns:db='jabber:server:dialback'>
<xs:element ref='features' minOccurs='0' maxOccurs='1'/>
<xs:any namespace='urn:ietf:params:xml:ns:xmpp-tls'
minOccurs='0'
maxOccurs='unbounded'/>
<xs:any namespace='urn:ietf:params:xml:ns:xmpp-sasl'
minOccurs='0'
maxOccurs='unbounded'/>
<xs:choice minOccurs='0' maxOccurs='1'>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='client:message'/>
<xs:element ref='client:presence'/>
<xs:element ref='client:iq'/>
</xs:choice>
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element ref='server:message'/>
<xs:element ref='server:presence'/>
<xs:element ref='server:iq'/>
<xs:element ref='db:result'/>
<xs:element ref='db:verify'/>
</xs:choice>
</xs:choice>
<xs:element ref='error' minOccurs='0' maxOccurs='1'/>
</xs:sequence>
<xs:attribute name='from' type='xs:string' use='optional'/>
<xs:attribute name='id' type='xs:NMTOKEN' use='optional'/>
<xs:attribute name='to' type='xs:string' use='optional'/>
<xs:attribute name='version' type='xs:decimal' use='optional'/>
<xs:attribute ref='xml:lang' use='optional'/>
</xs:complexType>
</xs:element>
<xs:element name='features'>
<xs:complexType>
<xs:all xmlns:tls='urn:ietf:params:xml:ns:xmpp-tls'
xmlns:sasl='urn:ietf:params:xml:ns:xmpp-sasl'
xmlns:bind='urn:ietf:params:xml:ns:xmpp-bind'
xmlns:sess='urn:ietf:params:xml:ns:xmpp-session'>
<xs:element ref='tls:starttls' minOccurs='0'/>
<xs:element ref='sasl:mechanisms' minOccurs='0'/>
<xs:element ref='bind:bind' minOccurs='0'/>
<xs:element ref='sess:session' minOccurs='0'/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name='error'>
<xs:complexType>
<xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'>
<xs:group ref='err:streamErrorGroup'/>
<xs:element ref='err:text'
minOccurs='0'
maxOccurs='1'/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
C.2. Stream error namespace ๐จ
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:ietf:params:xml:ns:xmpp-streams'
xmlns='urn:ietf:params:xml:ns:xmpp-streams'
elementFormDefault='qualified'>
<xs:element name='bad-format' type='empty'/>
<xs:element name='bad-namespace-prefix' type='empty'/>
<xs:element name='conflict' type='empty'/>
<xs:element name='connection-timeout' type='empty'/>
<xs:element name='host-gone' type='empty'/>
<xs:element name='host-unknown' type='empty'/>
<xs:element name='improper-addressing' type='empty'/>
<xs:element name='internal-server-error' type='empty'/>
<xs:element name='invalid-from' type='empty'/>
<xs:element name='invalid-id' type='empty'/>
<xs:element name='invalid-namespace' type='empty'/>
<xs:element name='invalid-xml' type='empty'/>
<xs:element name='not-authorized' type='empty'/>
<xs:element name='policy-violation' type='empty'/>
<xs:element name='remote-connection-failed' type='empty'/>
<xs:element name='resource-constraint' type='empty'/>
<xs:element name='restricted-xml' type='empty'/>
<xs:element name='see-other-host' type='xs:string'/>
<xs:element name='system-shutdown' type='empty'/>
<xs:element name='undefined-condition' type='empty'/>
<xs:element name='unsupported-encoding' type='empty'/>
<xs:element name='unsupported-stanza-type' type='empty'/>
<xs:element name='unsupported-version' type='empty'/>
<xs:element name='xml-not-well-formed' type='empty'/>
<xs:group name='streamErrorGroup'>
<xs:choice>
<xs:element ref='bad-format'/>
<xs:element ref='bad-namespace-prefix'/>
<xs:element ref='conflict'/>
<xs:element ref='connection-timeout'/>
<xs:element ref='host-gone'/>
<xs:element ref='host-unknown'/>
<xs:element ref='improper-addressing'/>
<xs:element ref='internal-server-error'/>
<xs:element ref='invalid-from'/>
<xs:element ref='invalid-id'/>
<xs:element ref='invalid-namespace'/>
<xs:element ref='invalid-xml'/>
<xs:element ref='not-authorized'/>
<xs:element ref='policy-violation'/>
<xs:element ref='remote-connection-failed'/>
<xs:element ref='resource-constraint'/>
<xs:element ref='restricted-xml'/>
<xs:element ref='see-other-host'/>
<xs:element ref='system-shutdown'/>
<xs:element ref='undefined-condition'/>
<xs:element ref='unsupported-encoding'/>
<xs:element ref='unsupported-stanza-type'/>
<xs:element ref='unsupported-version'/>
<xs:element ref='xml-not-well-formed'/>
</xs:choice>
</xs:group>
<xs:element name='text'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='xs:string'>
<xs:attribute ref='xml:lang' use='optional'/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
C.3. TLS namespace ๐
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:ietf:params:xml:ns:xmpp-tls'
xmlns='urn:ietf:params:xml:ns:xmpp-tls'
elementFormDefault='qualified'>
<xs:element name='starttls'>
<xs:complexType>
<xs:sequence>
<xs:element
name='required'
minOccurs='0'
maxOccurs='1'
type='empty'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='proceed' type='empty'/>
<xs:element name='failure' type='empty'/>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
C.4. SASL namespace ๐
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:ietf:params:xml:ns:xmpp-sasl'
xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
elementFormDefault='qualified'>
<xs:element name='mechanisms'>
<xs:complexType>
<xs:sequence>
<xs:element name='mechanism'
maxOccurs='unbounded'
type='xs:string'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='auth'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='empty'>
<xs:attribute name='mechanism'
type='xs:string'
use='optional'/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name='challenge' type='xs:string'/>
<xs:element name='response' type='xs:string'/>
<xs:element name='abort' type='empty'/>
<xs:element name='success' type='empty'/>
<xs:element name='failure'>
<xs:complexType>
<xs:choice minOccurs='0'>
<xs:element name='aborted' type='empty'/>
<xs:element name='incorrect-encoding' type='empty'/>
<xs:element name='invalid-authzid' type='empty'/>
<xs:element name='invalid-mechanism' type='empty'/>
<xs:element name='mechanism-too-weak' type='empty'/>
<xs:element name='not-authorized' type='empty'/>
<xs:element name='temporary-auth-failure' type='empty'/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
C.5. Resource binding namespace ๐
Okay, bestie, this is the schema for resource binding, and it's giving minimalist. The bind element gets at most one child, either a resource or a jid, and both are plain strings. Iconic. ๐
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:ietf:params:xml:ns:xmpp-bind'
xmlns='urn:ietf:params:xml:ns:xmpp-bind'
elementFormDefault='qualified'>
<xs:element name='bind'>
<xs:complexType>
<xs:choice minOccurs='0' maxOccurs='1'>
<xs:element name='resource' type='xs:string'/>
<xs:element name='jid' type='xs:string'/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
C.6. Dialback namespace ๐ฆ
Now we're in Server Dialback land ๐ธ There are two elements here, result and verify. Both hold a token as their text, and both need from and to attributes. The optional type attribute only accepts invalid or valid. The one difference is that verify also needs an id attribute, and that one is an xs:NMTOKEN. Very precise, very cute. ๐ง
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='jabber:server:dialback'
xmlns='jabber:server:dialback'
elementFormDefault='qualified'>
<xs:element name='result'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='xs:token'>
<xs:attribute name='from' type='xs:string' use='required'/>
<xs:attribute name='to' type='xs:string' use='required'/>
<xs:attribute name='type' use='optional'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='invalid'/>
<xs:enumeration value='valid'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name='verify'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='xs:token'>
<xs:attribute name='from' type='xs:string' use='required'/>
<xs:attribute name='id' type='xs:NMTOKEN' use='required'/>
<xs:attribute name='to' type='xs:string' use='required'/>
<xs:attribute name='type' use='optional'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='invalid'/>
<xs:enumeration value='valid'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
C.7. Stanza error namespace โจ
This is the stanza error buffet ๐ There are twenty-one error conditions in total. Most of them are empty, which just means they show up as a bare element with no text. gone and redirect are the exceptions, since they carry a string. Then there's a text element for human-readable explanations, and it can take an optional xml:lang attribute. All of them get grouped into stanzaErrorGroup, so the whole set can be referenced in one go. Organised, and honestly kind of iconic. ๐
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='urn:ietf:params:xml:ns:xmpp-stanzas'
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'
elementFormDefault='qualified'>
<xs:element name='bad-request' type='empty'/>
<xs:element name='conflict' type='empty'/>
<xs:element name='feature-not-implemented' type='empty'/>
<xs:element name='forbidden' type='empty'/>
<xs:element name='gone' type='xs:string'/>
<xs:element name='internal-server-error' type='empty'/>
<xs:element name='item-not-found' type='empty'/>
<xs:element name='jid-malformed' type='empty'/>
<xs:element name='not-acceptable' type='empty'/>
<xs:element name='not-allowed' type='empty'/>
<xs:element name='payment-required' type='empty'/>
<xs:element name='recipient-unavailable' type='empty'/>
<xs:element name='redirect' type='xs:string'/>
<xs:element name='registration-required' type='empty'/>
<xs:element name='remote-server-not-found' type='empty'/>
<xs:element name='remote-server-timeout' type='empty'/>
<xs:element name='resource-constraint' type='empty'/>
<xs:element name='service-unavailable' type='empty'/>
<xs:element name='subscription-required' type='empty'/>
<xs:element name='undefined-condition' type='empty'/>
<xs:element name='unexpected-request' type='empty'/>
<xs:group name='stanzaErrorGroup'>
<xs:choice>
<xs:element ref='bad-request'/>
<xs:element ref='conflict'/>
<xs:element ref='feature-not-implemented'/>
<xs:element ref='forbidden'/>
<xs:element ref='gone'/>
<xs:element ref='internal-server-error'/>
<xs:element ref='item-not-found'/>
<xs:element ref='jid-malformed'/>
<xs:element ref='not-acceptable'/>
<xs:element ref='not-allowed'/>
<xs:element ref='payment-required'/>
<xs:element ref='recipient-unavailable'/>
<xs:element ref='redirect'/>
<xs:element ref='registration-required'/>
<xs:element ref='remote-server-not-found'/>
<xs:element ref='remote-server-timeout'/>
<xs:element ref='resource-constraint'/>
<xs:element ref='service-unavailable'/>
<xs:element ref='subscription-required'/>
<xs:element ref='undefined-condition'/>
<xs:element ref='unexpected-request'/>
</xs:choice>
</xs:group>
<xs:element name='text'>
<xs:complexType>
<xs:simpleContent>
<xs:extension base='xs:string'>
<xs:attribute ref='xml:lang' use='optional'/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=''/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Appendix D. Differences Between Core Jabber Protocols and XMPP ๐
This section is non-normative, so think of it as a friendly catch-up. โจ
XMPP grew out of the protocols built by the Jabber open-source community, which you can think of as "XMPP 0.9" ๐ฆ There's a huge installed base of Jabber implementations and deployments out there, so it's helpful to spell out the key differences. That way, upgrading to XMPP is way easier for everyone. This appendix covers the core differences. The matching section of [XMPP-IM] covers the differences that matter specifically for instant messaging and presence apps. ๐
D.1. Channel Encryption ๐
The Jabber community commonly used SSL for channel encryption on ports other than 5222 and 5269, with the convention being ports 5223 and 5270. XMPP uses TLS over the IANA-registered ports for channel encryption instead, as defined under Use of TLS (Section 5) herein. ๐
D.2. Authentication ๐๏ธ
The Jabber community's client-server authentication protocol used a basic IQ interaction qualified by the jabber:iq:auth namespace. You can find the documentation for it in [JEP-0078], which the Jabber Software Foundation [JSF] published. XMPP uses SASL for authentication, as defined under Use of SASL (Section 6) herein. ๐
The Jabber community didn't develop an authentication protocol for server-to-server communications. It only had the Server Dialback (Section 8) protocol, which was there to prevent server spoofing. XMPP replaces Server Dialback with a true server-to-server authentication protocol, as defined under Use of SASL (Section 6) herein. ๐
D.3. Resource Binding ๐
In the Jabber community, resource binding was handled through the jabber:iq:auth namespace, which was also used for client authentication with a server. XMPP gives resource binding its own dedicated namespace. It also lets a server generate a resource identifier on behalf of a client, as defined under Resource Binding (Section 7). ๐ง
D.4. JID Processing ๐ชช
The Jabber community's JID processing was kind of loosely defined. You can find the documentation for forbidden characters and case handling in [JEP-0029], which the Jabber Software Foundation [JSF] published. XMPP specifies the use of [NAMEPREP] for domain identifiers. It also adds two [STRINGPREP] profiles on top of Nameprep for JID processing: Nodeprep (Appendix A) for node identifiers and Resourceprep (Appendix B) for resource identifiers. Much more precise now. ๐ธ
D.5. Error Handling ๐จ
In the Jabber community, stream-related errors were handled through XML character data text inside a <stream:error/> element. In XMPP, stream-related errors use an extensible mechanism defined under Stream Errors (Section 4.7) herein. ๐
Stanza-related errors were handled in the Jabber community with HTTP-style error codes. In XMPP, stanza-related errors use an extensible mechanism defined under Stanza Errors (Section 9.3) herein. You can find a mapping between the Jabber and XMPP error handling mechanisms in [JEP-0086], which the Jabber Software Foundation [JSF] published. ๐
D.6. Internationalization ๐
UTF-8 has always been standard practice in the Jabber community. But the community never defined a way to specify the language of human-readable text in XML character data. XMPP specifies the use of the xml:lang attribute in those contexts, as defined under Stream Attributes (Section 4.4) and xml:lang (Section 9.1.5) herein. Language tags, finally. ๐ณ๏ธโ๐
D.7. Stream Version Attribute ๐ข
The Jabber community didn't include a version attribute in stream headers. XMPP specifies including that attribute as a way to signal support for stream features like authentication and encryption, as defined under Version Support (Section 4.4.1) herein. Basically, the version attribute is the hint that tells everyone what's on the menu. ๐
Contributors โจ
Most of the core aspects of the Extensible Messaging and Presence Protocol were originally developed within the Jabber open-source community in 1999. The community was founded by Jeremie Miller, who released the source code for the initial version of the jabber server in January 1999. Major early contributors to the base protocol also included Ryan Eatmon, Peter Millard, Thomas Muldowney, and Dave Smith. ๐ซถ
The XMPP Working Group's work concentrated especially on security and internationalization. In those areas, the protocols for using TLS and SASL were originally contributed by Rob Norris, and the stringprep profiles were originally contributed by Joe Hildebrand. The error code syntax was suggested by Lisa Dusseault. ๐ฅ
Acknowledgements ๐ท
Thanks to a whole bunch of people beyond the contributors listed above! It's hard to give a complete list, but these folks were especially helpful in defining the protocols or commenting on the specifications in this memo: Thomas Charron, Richard Dobson, Sam Hartman, Schuyler Heath, Jonathan Hogg, Cullen Jennings, Craig Kaes, Jacek Konieczny, Alexey Melnikov, Keith Minkler, Julian Missig, Pete Resnick, Marshall Rose, Alexey Shchepin, Jean-Louis Seguineau, Iain Shigeoka, Greg Troxel, and David Waite. ๐
Thanks also to the members of the XMPP Working Group and the IETF community for their comments and feedback throughout the life of this memo. You all are literally the best. ๐ฅน
Author's Address ๐ฎ
Peter Saint-Andre (editor) Jabber Software Foundation
EMail: stpeter@jabber.org
Full Copyright Statement โ๏ธ
Copyright (C) The Internet Society (2004).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/S HE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property โจ
Okay bestie, so this part is all about the legal stuff, which is lowkey not my favourite but it's important ๐ The IETF doesn't take a position on whether any Intellectual Property Rights or other rights might apply to the tech in this document ๐ It also doesn't say whether licences are available, and it hasn't gone looking for any rights either. If you want the IETF's rules on rights in IETF Documents, you'll find them in BCP 78 and BCP 79 ๐
Copies of IPR disclosures that were sent to the IETF Secretariat are on the IETF's online IPR repository at http://www.ietf.org/ipr. You can also find any licence assurances there, plus results from attempts to get a general licence or permission for implementers or users to use those proprietary rights ๐ฆ
The IETF also invites anyone who's interested to flag any copyrights, patents, patent applications, or other proprietary rights that might cover technology needed to implement this standard. Send that info to the IETF at ietf-ipr@ietf.org ๐
Acknowledgement โจ
Funding for the RFC Editor function is currently provided by the Internet Society ๐ธ๐ซถ
๐ฆ where this page comes from
- ietf: rfc3920 2004-10
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms