1
0
mirror of https://github.com/moparisthebest/xeps synced 2024-11-24 10:12:19 -05:00

1.16 RC1 complete rewrite

git-svn-id: file:///home/ksmith/gitmigration/svn/xmpp/trunk@574 4b5297f7-1745-476d-ba37-a9c6900126ab
This commit is contained in:
Ian Paterson 2007-02-15 04:17:04 +00:00
parent 80724e4f4a
commit 6919490ad7

View File

@ -2,32 +2,47 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [ <!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'> <!ENTITY % ents SYSTEM 'xep.ent'>
%ents; %ents;
<!ENTITY server "server">
<!ENTITY xep0206 "<span class='ref'>XMPP Over BOSH</span> <note>XEP-0206: XMPP Over BOSH &lt;<link url='http://www.xmpp.org/extensions/xep-0206.html'>http://www.xmpp.org/extensions/xep-0206.html</link>&gt;.</note>" >
<!ENTITY xep0214 "<span class='ref'>BOAH</span> <note>XEP-0214: Bidirectional-streams Over Asynchronous HTTP (BOAH) &lt;<link url='http://www.xmpp.org/extensions/xep-0214.html'>http://www.xmpp.org/extensions/xep-0214.html</link>&gt;.</note>" >
<!ENTITY ECMAScript "<span class='ref'>ECMAScript (JavaScript)</span> <note>Standard ECMA-262: ECMAScript Language Specification 3rd edition &lt;<link url='http://www.ecma-international.org/publications/standards/Ecma-262.htm'>http://www.ecma-international.org/publications/standards/Ecma-262.htm</link>&gt;.</note>" >
<!ENTITY rfc4627 "<span class='ref'>RFC 4627</span> <note>RFC 4627: The application/json Media Type for JavaScript Object Notation (JSON) &lt;<link url='http://tools.ietf.org/html/rfc4627'>http://tools.ietf.org/html/rfc4627</link>&gt;.</note>" >
]> ]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?> <?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep> <xep>
<header> <header>
<title>HTTP Binding</title> <title>Bidirectional-streams Over Synchronous HTTP (BOSH)</title>
<abstract>This document defines a binding of XMPP communications to a transport layer of HTTP rather than TCP.</abstract> <abstract>This document defines a transport protocol (formerly known as HTTP Binding) that emulates bi-directional connections efficiently using multiple synchronous HTTP request/response pairs (i.e. without polling or asynchronous chunking).</abstract>
&LEGALNOTICE; &LEGALNOTICE;
<number>0124</number> <number>0124</number>
<status>Draft</status> <status>Draft</status>
<type>Standards Track</type> <type>Standards Track</type>
<sig>Standards</sig> <jig>Standards</jig>
<dependencies> <dependencies>
<spec>XMPP Core</spec> <spec>XMPP Core</spec>
<spec>RFC 1945</spec> <spec>RFC 1945</spec>
<spec>RFC 2068</spec> <spec>RFC 2616</spec>
<spec>RFC 3174</spec> <spec>RFC 3174</spec>
</dependencies> </dependencies>
<supersedes/> <supersedes/>
<supersededby/> <supersededby/>
<shortname>httpbind</shortname> <shortname>bosh</shortname>
<schemaloc> <schemaloc>
<url>http://www.xmpp.org/schemas/httpbind.xsd</url> <url>http://www.xmpp.org/schemas/httpbind.xsd</url>
</schemaloc> </schemaloc>
&ianpaterson; &ianpaterson;
&dizzyd; &dizzyd;
&stpeter; &stpeter;
<revision>
<version>1.6</version>
<date>2007-02-15</date>
<initials>ip</initials>
<remark>Multiple clarifications and restructuring without changes to protocol itself; changed title to BOSH; added section that fully explores the technique underlying the protocol; separated XMPP-specific features into new XEP-0206; added optional new Script Syntax and session pauses; added from and ver attributes; added hold attribute to session creation response; clarified polling too-frequently error; recommended clients use HTTP Pipelining.</remark>
</revision>
<revision> <revision>
<version>1.5</version> <version>1.5</version>
<date>2006-04-28</date> <date>2006-04-28</date>
@ -126,43 +141,41 @@
</revision> </revision>
</header> </header>
<section1 topic="Introduction" anchor='intro'> <section1 topic="Introduction" anchor='intro'>
<p>&xmppcore; defines XML streams bound to TCP (see &rfc0793;) as the standard transport layer for Jabber/XMPP communications. However, the binding of XMPP to TCP is not always feasible because of client runtime environment and/or network constraints. This document describes the usage of the Hypertext Transfer Protocol (HTTP, see &rfc2068; and &rfc1945;) as an alternative transport binding that supports such constrained environments, normally via deployment of a specialized server-side connection manager that communicates with clients via HTTP rather than TCP.</p> <p>Applications, restricted either by their runtime environments or by firewalls that permit only Web browsing, often find that arbitrary TCP connections (see &rfc0793;) cannot be established. BOSH, the protocol described in this document, may be used as a "drop-in" alternative to a bi-directional TCP connection. It is a mature fully-featured protocol that has been in use for many years with many open source and commercial implementations. It overcomes common communication constraints by employing fully-compliant "cookie-free" <note>Enabling communications via &rfc2965; is sub-optimal since several significant computing platforms provide only limited access to underlying HTTP requests/responses; worse, some platforms hide or remove cookie-related headers.</note> HTTP 1.0 or HTTP 1.1 as a transport (see &rfc1945; and &rfc2616;).</p>
<p>Before the authors pursued publication of this document, other approaches were explored. One possible approach might have been to apply state to a series of HTTP transactions via HTTP "cookies" as specified in &rfc2965;. However, there are several significant computing platforms which provide only limited access to underlying HTTP requests/responses; worse, some platforms hide or remove cookie-related headers. Therefore the cookie approach was rejected.</p> <p>BOSH can transport any data efficiently and with minimal latency in both directions. For applications that require both "push" and "pull" communications, BOSH is significantly more bandwidth-efficient and responsive than most other bi-directional HTTP-based transport protocols (e.g. &xep0025;) and techniques now commonly known as AJAX.</p>
<p>Another approach might have been to modify or extend &xep0025;. This informational protocol has been used by Jabber clients without runtime constraints to access XMPP servers from behind firewalls. Unfortunately, the method defined in XEP-0025 also depends on cookies, does not meet most of the requirements described below, and cannot be extended without breaking all existing implementations.</p> <p>BOSH achieves this efficiency and low-latency by avoiding polling without resorting to chunked HTTP responses (i.e. without using the technique which is now commonly known as "Comet"). The protocol employs multiple synchronous HTTP request/response pairs. This technique allows it to pass through even those proxies that buffer partial HTTP responses before forwarding the full responses only once they are available.</p>
<p>Therefore, this document specifies a new way of transporting XMPP via HTTP. All information is encoded in the body of standard HTTP POST requests and responses. Each HTTP body contains a single &lt;body/&gt; XML wrapper element (not to be confused with the &lt;body/&gt; child of the &lt;message/&gt; stanza as defined in &xmppim;), which encapsulates zero or more XML stanzas.</p> <p>Note: Although the XML being transported in the examples herein is XMPP, this transport is not part of XMPP. In fact, from its conception the intention of the primary author was that it could be used to implement any bidirectional XML stream transporting a mixture of elements qualified by namespaces defined by different protocols (e.g., both XMPP and JSON). This mix is necessary since some connection managers may not support <link url="#multi">Multiple Streams</link> and constrained clients often have no access to HTTP Pipelining (which limits them to one BOSH session at a time). BOSH connection managers are generally not required to understand anything about the XML content that they transport beyond perhaps ensuring that each XML stanza is qualified by the correct namespace. &xep0206; documents some XMPP-specific extensions of this protocol that were formerly included in this document.</p>
<p>Although this specification documents some XMPP-specific features, the binding is not part of XMPP. In fact, the protocol is extensible and could be used to implement any bidirectional stream of XML stanzas.</p> <p>Note: This document inherits terminology regarding the Hypertext Transport Protocol from <cite>RFC 1945</cite> and <cite>RFC 2616</cite>.</p>
</section1>
<section1 topic="Terminology" anchor='terms'>
<section2 topic="HTTP Terms" anchor='terms-http'>
<p>This document inherits terminology regarding the Hypertext Transport Protocol from RFCs 1945 and 2068.</p>
</section2>
</section1> </section1>
<section1 topic='Requirements' anchor='reqs'> <section1 topic='Requirements' anchor='reqs'>
<p>Platform limitiations, security restrictions, and other constraints imply that many clients can connect to Internet resources (e.g., Jabber servers) only via HTTP. The following design requirements reflect the need to offer performance as close as possible to a standard TCP connection.</p> <p>The following design requirements reflect the need to offer performance as close as possible to a standard TCP connection.</p>
<ol> <ol>
<li>Compatible with constrained runtime environments (e.g., mobile and browser-based clients).</li> <li>Compatible with constrained runtime environments* (e.g., mobile and browser-based clients).</li>
<li>Compatible with restricted network connections (e.g., firewalls, proxies, and gateways).</li> <li>Compatible with restricted network connections (e.g., firewalls, proxies, and gateways).</li>
<li>Fault tolerant (e.g., session recovers after an underlying TCP connection breaks during an HTTP request).</li> <li>Compatible with proxies that buffer partial HTTP responses.</li>
<li>Extensible (based on XML).</li> <li>Fault tolerant (e.g., session recovers after an underlying TCP connection breaks at any stage during an HTTP request).</li>
<li>Consume significantly less bandwidth than polling-based solutions.</li> <li>Extensible.</li>
<li>Significantly more responsive than polling-based solutions.</li> <li>Consume significantly less bandwidth than polling-based protocols.</li>
<li>Support for polling (for clients that are limited to one HTTP connection at a time).</li> <li>Significantly more responsive (lower latency) than polling-based protocols.</li>
<li>XML stanzas should arrive at the server in the order they were sent by the client.</li> <li>Support for polling (for clients that are limited to a single HTTP connection at a time).</li>
<li>Protect against unauthorized users interjecting HTTP requests into a session.</li> <li>In-order delivery of data.</li>
<li>Guard against unauthorized users interjecting HTTP requests into a session.</li>
<li>Protect against denial of service attacks.</li>
<li>Multiplexing of data streams</li>
</ol> </ol>
<p>Compatibility with constrained runtime environments implies the following restrictions:</p> <p>*Compatibility with constrained runtime environments implies the following restrictions:</p>
<ul> <ol>
<li>Clients should not be required to have programmatic access to the headers of each HTTP request and response (e.g., cookies or status codes).</li> <li>Clients should not be required to have programmatic access to the headers of each HTTP request and response (e.g., cookies or status codes).</li>
<li>The body of each HTTP request and response should be parsable XML with a single root element.</li> <li>The body of each HTTP request and response may be parsable XML with a single root element.</li>
<li>Clients should be able to specify the Content-Type of the HTTP responses they receive.</li> <li>Clients should be able to specify the Content-Type of the HTTP responses they receive.</li>
</ul> </ol>
</section1> </section1>
<section1 topic="Architectural Assumptions" anchor='arch'> <section1 topic="Architectural Assumptions" anchor='arch'>
<p>The binding of XMPP to HTTP assumes a different architecture from that described for the binding of XMPP to TCP as defined in <cite>RFC 3920</cite>. In particular, because HTTP is not the native binding for XMPP, we assume that most XMPP implementations will utilize a specialized "connection manager" to handle HTTP connections rather than the usual TCP connections. Effectively, such a connection manager will be a specialized HTTP server that translates between the HTTP requests and responses defined herein and the XML streams (or a server API) implemented by the XMPP server or servers with which it communicates, thus enabling an HTTP client to connect to an XMPP server. We can illustrate this graphically as follows:</p> <p>This document assumes that most implementations will utilize a specialized "connection manager" to handle HTTP connections rather than the usual TCP connections. Effectively, such a connection manager will be a specialized HTTP server that translates between the HTTP requests and responses defined herein and the data streams (or API) implemented by the &server; or &server;s with which it communicates, thus enabling an HTTP client to connect to a &server;. We can illustrate this graphically as follows:</p>
<code><![CDATA[ <code><![CDATA[
XMPP Server Server
| |
| [XML streams or server API] | [unwrapped data streams]
| |
Connection Manager Connection Manager
| |
@ -170,45 +183,55 @@ Connection Manager
| |
HTTP Client HTTP Client
]]></code> ]]></code>
<p>This document addresses communications between an HTTP client and the connection manager only. It does not address communications between the connection manager and the XMPP server, since such communications are implementation-specific (e.g., the connection manager and the XMPP server may use &xep0114; or an API defined by the XMPP server implementation in order to communicate; alternatively, the XMPP server may natively support the HTTP binding, in which case the connection manager will be a logical entity rather than a physical entity).</p> <p>BOSH addresses communications between an HTTP client and the connection manager only. It does not address communications between the connection manager and the &server;, since such communications are implementation-specific (e.g., the &server; may natively support this HTTP binding, in which case the connection manager will be a logical entity rather than a physical entity; alternatively the connection manager may be an independant translating proxy such that the &server; may believe it is talking directly to the client over TCP; or the connection manager and the &server; may use a component protocol or an API defined by the &server; implementation).</p>
<p>Furthermore, no aspect of the HTTP binding limits its use to client-to-server communications; i.e., it could be used for server-to-server or component-to-server communications as well (probably through a slight change to the XML schema). However, this document focuses exclusively on use of the HTTP binding by clients that cannot maintain persistent TCP connections to a server and that therefore cannot use the TCP binding defined in <cite>RFC 3920</cite>. We assume that servers and components are under no such restrictions and thus would use the TCP binding.</p> <p>Furthermore, no aspect of this protocol limits its use to client-to-server communications. It could be used for server-to-server or component-to-server communications as well. However, this document focuses exclusively on use of the transport by clients that cannot maintain arbitrary persistent TCP connections with a server. We assume that servers and components are under no such restrictions and thus would use TCP.</p>
</section1> </section1>
<section1 topic="HTTP Version and HTTP Headers" anchor='http'> <section1 topic="The BOSH Technique" anchor='technique'>
<p>Clients SHOULD send HTTP requests over persistent HTTP/1.1 connections. However, a constrained client MAY open a new HTTP/1.0 connection (as defined in RFC 1945) to send each request.</p> <p>Since HTTP is a synchronous request/response protocol, the traditional solution to emulating a bidirectional-stream over HTTP involved the client intermittently polling the connection manager to discover if it has any data queued for delivery to the client. This naive approach wastes a lot of network bandwidth by polling when no data is available. It also reduces the responsiveness of the application since the data spends time queued waiting until the connection manager receives the next poll (HTTP request) from the client. This results in an inevitable trade-off between responsiveness and bandwidth, since increasing the polling frequency will decrease latency but simultaneously increase bandwidth consumption (or vice versa if polling frequency is decreased).</p>
<p>Requests and responses MAY include HTTP headers not specified herein. The receiver SHOULD ignore any such headers.</p> <p>The technique employed by this protocol achieves both low latency and low bandwidth consumption by encouraging the connection manager not to respond to a request until it actually has data to send to the client. As soon as the client receives a response from the connection manager it sends another request, thereby ensuring that the connection manager is (almost) always holding a request that it can use to "push" data to the client.</p>
<p>If the client needs to send some data to the connection manager then it simply sends a second request containing the data. Unfortunately most constrained clients do not support HTTP Pipelining (concurrent requests over a single connection), so the client typically needs to send the data over a second HTTP connection. The connection manager always responds to the request it has been holding on the first connection as soon as it receives a new request from the client - even if it has no data to send the client. It does that to make sure the client can send more data immediately if necessary. (The client cannot open more than two HTTP connections at the same time, <note>In order to reduce network congestion, <cite>RFC 2616</cite> recommends that clients SHOULD NOT keep more than two HTTP connections to the same HTTP server open at the same time. Clients running in constrained enviroments typically have no choice but to abide by that recommendation.</note> so it would otherwise have to wait until the connection manager responds to one of the requests.)</p>
<p>BOSH works reliably even if network conditions force every HTTP request to be made over a different TCP connection. However, if as is usually the case, the client is able to use HTTP/1.1, then (assuming reliable network conditions) all requests during a session will pass over the same two persistent connections. Almost all of the time (see below) the client is able to push data on one of the connections, while the connection manager is able to "push" data on the other (so latency is as low as a standard TCP connection). It's interesting to note that the roles of the two connections typically switch whenever the client sends data to the connection manager.</p>
<p>If there is no traffic in either direction for an agreed amount of time (typically a couple of minutes), then the connection manager responds to the client with no data, and that response immediately triggers a fresh client request. The connection manager does that to ensure that if a network connection is broken then both parties will realise within a reasonable amount of time. This exchange is similar to the "keep-alive" or "ping" that is common practice over most persistent TCP connections. Since the BOSH technique involves no polling, bandwidth consumption is not significantly greater than a standard TCP connection. <note>If there is no traffic other than the "pings" then bandwidth consumption will be double that of a TCP connection (although double nothing is still nothing). If data is sent in large packets then bandwidth consumption will be almost identical.</note></p>
<p>Most of the time data can be pushed immediately. However, if one of the endpoints has just pushed some data then it will usually have to wait for a network round trip until it is able to push again. If HTTP Pipelining is available to the client then multiple concurrent requests are possible. So the client can always push data immediately. It can also ensure the connection manager is always holding enough requests such that even during bursts of activity it will never have to wait before pushing data. Furthermore, if the pool of requests being held by the connection manager is large enough, then the client will not be under pressure to send a new empty request immediately after receiving data from the connection manager. It can instead wait until it needs to send data. So, if over time the traffic to and from the client is balanced, bandwidth consumption will be about the same as if a standard TCP connection was being used.</p>
<p>Each block of data pushed by the connection manager is a complete HTTP response. So, unlike the Comet technique, the BOSH technique works through intermediate proxies that buffer partial HTTP responses. It is also fully compliant with HTTP/1.0 - which does not provide for chunked transfer encoding. Also unlike Comet, Web clients can use BOSH to make cross-domain connections.</p>
</section1> </section1>
<section1 topic="Compression" anchor='compression'> <section1 topic="HTTP Overview" anchor='overview'>
<p>All information is encoded in the body of standard HTTP POST requests and responses. Each HTTP body contains a single &lt;body/&gt; wrapper which encapsulates the XML elements being transferred (see <link url="#wrapper">&lt;body/&gt; Wrapper Element</link>).</p>
<p>Clients SHOULD send all HTTP requests over a single persistent HTTP/1.1 connection using HTTP Pipelining. However, a client MAY deliver its POST requests in any way permited by <cite>RFC 1945</cite> or <cite>RFC 2616</cite>. For examples, constrained clients can be expected to open more than one persistent connection instead of using Pipelining, or in some cases to open a new HTTP/1.0 connection to send each request. However, clients and connection managers SHOULD NOT use Chunked Transfer Coding, since intermediaries may buffer each partial HTTP request or response and only forward the full request or reponse once it is available.</p>
<p>Clients MAY include an HTTP Accept-Encoding header in any request. If the connection manager receives a request with an Accept-Encoding header, it MAY include an HTTP Content-Encoding header in the response (indicating one of the encodings specified in the request) and compress the response body accordingly.</p> <p>Clients MAY include an HTTP Accept-Encoding header in any request. If the connection manager receives a request with an Accept-Encoding header, it MAY include an HTTP Content-Encoding header in the response (indicating one of the encodings specified in the request) and compress the response body accordingly.</p>
<p>TLS compression (as defined in <cite>RFC 3920</cite>) and Stream Compression (as defined in &xep0138;) are NOT RECOMMENDED since compression SHOULD be negotiated at the HTTP layer and with the 'accept' attribute (see the <link url="#session-create">Session Creation</link> section below). TLS compression and Stream Compression SHOULD NOT be used simultaneously with HTTP content encoding.</p> <p>Requests and responses MAY include HTTP headers not specified herein. The receiver SHOULD ignore any such headers.</p>
<p>Each BOSH session MAY share the HTTP connection(s) it uses with other HTTP traffic, including other BOSH sessions and HTTP requests and responses completely unrelated to this protocol (e.g., web page downloads).</p>
<p>The HTTP Content-Type header of all client requests SHOULD be "text/xml; charset=utf-8". However, clients MAY specify another value if they are constrained to do so (e.g., "application/x-www-form-urlencoded" or "text/plain"). The client and connection manager SHOULD ignore all HTTP Content-Type headers they receive.</p>
</section1> </section1>
<section1 topic="&lt;body/&gt; Wrapper Element" anchor='wrapper'> <section1 topic="&lt;body/&gt; Wrapper Element" anchor='wrapper'>
<p>The body of each HTTP request and response contains a single &lt;body/&gt; wrapper element. The &lt;body/&gt; element MUST contain zero or more complete XML elements. It MUST NOT contain partial XML elements.</p> <p>The body of each HTTP request and response contains a single &lt;body/&gt; wrapper element qualified by the 'http://jabber.org/protocol/httpbind' namespace. The content of the wrapper is the data being transfered. The &lt;body/&gt; element and it's content together MUST conform to the specifications set out in &w3xml;. They SHOULD also conform to &w3xmlnamespaces;. The content MUST NOT contain any of the following (all defined in <cite>XML 1.0</cite>):</p>
<p>If the &lt;body/&gt; wrapper element is not empty, then it MUST contain one of the following:</p>
<ul> <ul>
<li>One or more complete XMPP stanzas (&lt;message/&gt;, &lt;presence/&gt;, and/or &lt;iq/&gt;).</li> <li><p>Partial XML elements</p></li>
<li>A complete &lt;stream:features/&gt; element (in which case the body element MUST include namespace xmlns:stream='http://etherx.jabber.org/streams').</li> <li><p>XML comments</p></li>
<li>A complete element used for SASL negotiation and qualified by the 'urn:ietf:params:xml:ns:xmpp-sasl' namespace.</li> <li><p>XML processing instructions</p></li>
<li>XML elements associated with a binding error condition. For details, refer to the <link url="#errorstatus-binding">Binding Conditions</link> section below.</li> <li><p>Internal or external DTD subsets</p></li>
<li><p>Internal or external entity references (with the exception of predefined entities)</p></li>
<li><p>Character data or attribute values containing unescaped characters that map to the predefined entities (such characters MUST be escaped)</p></li>
</ul> </ul>
<p>Note: Inclusion of TLS negotiation elements is allowed but is NOT RECOMMENDED (see <link url="#preconditions">Additional Preconditions</link> below).</p> <p>The &lt;body/&gt; wrapper MUST NOT contain any XML character data, although its child elements MAY contain character data. The &lt;body/&gt; wrapper MUST contain zero or more complete XML immediate child elements (called "stanzas" in this document, e.g., XMPP stanzas, or elements containing XML character data that represents objects using the JSON data interchange format - see &rfc4627;). Each &lt;body/&gt; wrapper MAY contain stanzas qualified under a wide variety of different namespaces.</p>
<p>The &lt;body/&gt; wrapper element SHOULD be qualified by the 'http://jabber.org/protocol/httpbind' namespace, and child elements SHOULD be qualified by their respective namespaces (e.g., 'http://etherx.jabber.org/streams' for stream features, 'urn:ietf:params:xml:ns:xmpp-sasl' for SASL negotiation, and 'jabber:client' for XML stanzas). However, even if the client does not specify the namespaces, the connection manager MUST ensure that the XMPP it provides to the XMPP server or other entities on the network meets the namespacing requirements of <cite>RFC 3920</cite>.</p>
<p>The &lt;body/&gt; element of every client request MUST possess a sequential request ID encapsulated via the 'rid' attribute; For details, refer to the <link url="#rids">Request IDs</link> section of this document.</p> <p>The &lt;body/&gt; element of every client request MUST possess a sequential request ID encapsulated via the 'rid' attribute; For details, refer to the <link url="#rids">Request IDs</link> section of this document.</p>
</section1> </section1>
<section1 topic="Initiating an HTTP Session" anchor='session'> <section1 topic="Initiating an HTTP Session" anchor='session'>
<section2 topic="Requesting a Session" anchor='session-request'> <section2 topic="Session Creation Request" anchor='session-request'>
<p>The first request from the client to the connection manager creates a new session.</p> <p>The first request from the client to the connection manager requests a new session.</p>
<p>The &lt;body/&gt; element of the first request SHOULD possess the following attributes (they SHOULD NOT be included in any other requests except as specified in the <link url="#multi-add">Adding Streams To A Session</link> section below):</p> <p>The &lt;body/&gt; element of the first request SHOULD possess the following attributes (they SHOULD NOT be included in any other requests except as specified in <link url="#multi-add">Adding Streams To A Session</link>):</p>
<ul> <ul>
<li><strong>'to'</strong> -- This attribute specifies the target domain.</li> <li><strong>'to'</strong> -- This attribute specifies the target domain.</li>
<li><strong>'xml:lang'</strong> -- This attribute (as defined in Section 2.12 of &w3xml;) specifies the default language of any human-readable XML character data sent or received during the session.</li> <li><strong>'xml:lang'</strong> -- This attribute (as defined in Section 2.12 of &w3xml;) specifies the default language of any human-readable XML character data sent or received during the session.</li>
<li><strong>'wait'</strong> -- This attribute specifies the longest time (in seconds) that the connection manager is allowed to wait before responding to any request during the session. This enables the client to prevent its TCP connection from expiring due to inactivity, as well as to limit the delay before it discovers any network failure.</li> <li><strong>'ver'</strong> -- This attribute specifies the highest version of the BOSH protocol that the client supports. The numbering scheme is "&lt;major&gt;.&lt;minor&gt;" (where the minor number MAY be incremented higher than a single digit, so it MUST be treated as a separate integer). Note: The 'ver' attribute should not be confused with the version of any protocol being transported.</li>
<li><strong>'hold'</strong> -- This attribute specifies the maximum number of requests the connection manager is allowed to keep waiting at any one time during the session. (For example, if a constrained client is unable to keep open more than two HTTP connections to the same HTTP server simultaneously, then it SHOULD specify a value of "1".)</li> <li><strong>'wait'</strong> -- This attribute specifies the longest time (in seconds) that the connection manager is allowed to wait before responding to any request during the session. This enables the client to limit the delay before it discovers any network failure, and to prevent its HTTP/TCP connection from expiring due to inactivity.</li>
<li><strong>'hold'</strong> -- This attribute specifies the maximum number of requests the connection manager is allowed to keep waiting at any one time during the session. If the client is not able to use HTTP Pipelining then this SHOULD be set to "1".</li>
</ul> </ul>
<p>Note: Clients that only support polling behavior MAY prevent the connection manager from waiting by setting 'wait' or 'hold' to "0". However, polling is NOT RECOMMENDED since the associated increase in bandwidth consumption and the decrease in responsiveness are typically one or two orders of magnitude!</p> <p>Note: Clients that only support <link url="#poll">Polling Sessions</link> MAY prevent the connection manager from waiting by setting 'wait' or 'hold' to "0". However, polling is NOT RECOMMENDED since the associated increase in bandwidth consumption and the decrease in responsiveness are typically one or two orders of magnitude!</p>
<p>A connection manager MAY be configured to enable sessions with more than one XMPP server in different domains. When requesting a session with such a 'proxy' connection manager, a client SHOULD include a 'route' attribute that specifies the protocol, hostname, and port of the server with which it wants to communicate, formatted as "proto:host:port" (e.g., "xmpp:jabber.org:9999"). <note>Although the syntax of the 'route' attribute bears a superficial resemblance to a URI or IRI, it is not a URI/IRI and MUST NOT be processed in accordance with the rules specified in <cite>RFC 3986</cite>, <cite>RFC 3987</cite>, or <cite>draft-saintandre-xmpp-iri</cite>.</note> A connection manager that is configured to work only with a single XMPP server (or only with a defined list of XMPP domains and their respective hosts and ports) MAY ignore the 'route' attribute. (Note that the 'to' attribute specifies the XMPP domain, not the host machine.)</p> <p>A connection manager MAY be configured to enable sessions with more than one &server; in different domains. When requesting a session with such a 'proxy' connection manager, a client SHOULD include a <strong>'route'</strong> attribute that specifies the protocol, hostname, and port of the &server; with which it wants to communicate, formatted as "proto:host:port" (e.g., "xmpp:jabber.org:9999"). <note>Although the syntax of the 'route' attribute bears a superficial resemblance to a URI or IRI, it is not a URI/IRI and MUST NOT be processed in accordance with the rules specified in <cite>RFC 3986</cite>, <cite>RFC 3987</cite>, or <cite>draft-saintandre-xmpp-iri</cite>.</note> A connection manager that is configured to work only with a single &server; (or only with a defined list of domains and the associated list of hostnames and ports that are serving those domains) MAY ignore the 'route' attribute. (Note that the 'to' attribute specifies the domain being served, not the hostame of the machine that is serving the domain.)</p>
<p>A client MAY include a 'secure' attribute to specify that communications between the connection manager and the XMPP server must be "secure". (Note: The 'secure' attribute is of type xs:boolean (see &w3xmlschema2;) and the default value is "false". &BOOLEANNOTE;) If a connection manager receives a session request with the 'secure' attribute set to 'true' or '1', then it MUST respond to the client with a <link url="#errorstatus-terminal">remote-connection-failed</link> error as soon as it determines that it cannot communicate in a secure way with the XMPP server. A connection manager SHOULD consider communications with the XMPP server to be "secure" if they are encrypted using SSL or TLS with verified certificates, or if it is running on the same physical machine as the XMPP server. A connection manager MAY consider communications over a "private" network to be secure, even without SSL or TLS; however, a network SHOULD be considered "private" only if the administrator of the connection manager is sure that unknown individuals or processes do not have access to the network (i.e., individuals or processes who do not have access to either the connection manager or the XMPP server). The connection manager SHOULD try to establish a secure connection with the XMPP server even if the client does not specifically require it.</p> <p>A client MAY include a <strong>'from'</strong> attribute to enable the connection manager to forward its identity to the &server;.</p>
<p>Some clients are constrained to only accept HTTP responses with specific Content-Types (e.g., "text/html"). The &lt;body/&gt; element of the first request MAY possess a 'content' attribute. This specifies the value of the HTTP Content-Type header that MUST appear in all the connection manager's responses during the session. If the client request does not possess a 'content' attribute, then the HTTP Content-Type of responses MUST be "text/xml; charset=utf-8".</p> <p>A client MAY include a <strong>'secure'</strong> attribute to specify that communications between the connection manager and the &server; must be "secure". (Note: The 'secure' attribute is of type xs:boolean (see &w3xmlschema2;) and the default value is "false". &BOOLEANNOTE;) If a connection manager receives a session request with the 'secure' attribute set to "true" or "1", then it MUST respond to the client with a <link url="#errorstatus-terminal">remote-connection-failed</link> error as soon as it determines that it cannot communicate in a secure way with the &server;. A connection manager SHOULD consider communications with the &server; to be "secure" if they are encrypted using SSL or TLS with verified certificates, or if it is running on the same physical machine as the &server;. A connection manager MAY consider communications over a "private" network to be secure, even without SSL or TLS; however, a network SHOULD be considered "private" only if the administrator of the connection manager is sure that unknown individuals or processes do not have access to the network (i.e., individuals or processes who do not have access to either the connection manager or the &server;). The connection manager SHOULD try to establish a secure connection with the &server; even if the client does not specifically require it.</p>
<p>Note: The HTTP Content-Type of client requests SHOULD also be "text/xml; charset=utf-8". Clients MAY specify another value if they are constrained to do so (e.g., "application/x-www-form-urlencoded" or "text/plain"). The client and connection manager SHOULD ignore all HTTP Content-Type headers they receive.</p> <p>Some clients are constrained to only accept HTTP responses with specific Content-Types (e.g., "text/html"). The &lt;body/&gt; element of the first request MAY possess a <strong>'content'</strong> attribute. This specifies the value of the HTTP Content-Type header that MUST appear in all the connection manager's responses during the session. If the client request does not possess a 'content' attribute, then the HTTP Content-Type header of responses MUST be "text/xml; charset=utf-8".</p>
<example caption="Requesting an HTTP session"> <example caption="Requesting an HTTP session">
<![CDATA[POST /webclient HTTP/1.1 <![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org Host: httpcm.jabber.org
@ -222,284 +245,58 @@ Content-Length: 104
to='jabber.org' to='jabber.org'
route='xmpp:jabber.org:9999' route='xmpp:jabber.org:9999'
secure='true' secure='true'
ver='1.6'
wait='60' wait='60'
xml:lang='en' xml:lang='en'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>Note: Unlike the protocol defined in XEP-0025, an opening &lt;stream:stream&gt; tag is not sent. The protocol defined herein abstracts from XML streams between the connection manager and the client. Any XML streams between the connection manager and an XMPP server are the responsibility of the connection manager.</p> <p>Note: All requests after the first one MUST include a valid 'sid' attribute (provided by the connection manager in the <link url="#session-create">Session Creation Response</link>). The initialization request is unique in that the &lt;body/&gt; element MUST NOT possess a 'sid' attribute.</p>
<p>Note: All requests after the first one MUST include a valid 'sid' attribute (provided by the connection manager in the session creation response below). The initialization request is unique in that the &lt;body/&gt; element MUST NOT possess a 'sid' attribute.</p>
</section2> </section2>
<section2 topic="Session Creation" anchor='session-create'> <section2 topic="Session Creation Response" anchor='session-create'>
<p>After receiving a new session request, the connection manager MUST generate an opaque, unpredictable session identifier (or SID). The SID MUST be unique within the context of the connection manager application. The connection manager then returns that SID to the client in a response &lt;body/&gt; element.</p> <p>After receiving a new session request, the connection manager MUST generate an opaque, unpredictable session identifier (or SID). The SID MUST be unique within the context of the connection manager application. The &lt;body/&gt; element of the connection manager's response to the client's session creation request MUST possess the following attributes (they SHOULD NOT be included in any other responses):</p>
<p>The connection manager MUST specify a 'wait' attribute. This is the longest time (in seconds) that it will wait before responding to any request during the session. The time MUST be less than or equal to the value specified in the session request.</p> <ul>
<p>The connection manager MAY limit the number of simultaneous requests the client makes with the 'requests' attribute. The RECOMMENDED value is "2". Servers that only support polling behavior MUST prevent clients from making simultaneous requests by setting the 'requests' attribute to a value of "1" (however, polling is NOT RECOMMENDED). In any case, clients MUST NOT make more simultaneous requests than specified by the connection manager.</p> <li><strong>'sid'</strong> -- This attribute specifies the SID</li>
<p>The connection manager SHOULD include two additional attributes in the session creation response element, specifying the shortest allowable polling interval and the longest allowable inactivity period (both in seconds). Communication of these parameters enables the client to engage in appropriate behavior (e.g., not sending empty request elements more often than desired, and ensuring that the periods with no requests pending are never too long).</p> <li><strong>'wait'</strong> -- This is the longest time (in seconds) that it will wait before responding to any request during the session. The time MUST be less than or equal to the value specified in the session request.</li>
<p>The connection manager MAY include an 'accept' attribute in the session creation response element, to specify the content encodings it can decompress. After receiving a session creation response with an 'accept' attribute, clients MAY include an HTTP Content-Encoding header in subsequent requests (indicating one of the encodings specified in the 'accept' attribute) and compress the bodies of the requests accordingly.</p> </ul>
<p>For both requests and responses, the &lt;body/&gt; element and its content SHOULD be UTF-8 encoded. If the HTTP Content-Type header of a request/response specifies a character encoding other than UTF-8, then the connection manager MAY convert between UTF-8 and the other character encoding. However, even in this case, it is OPTIONAL for the connection manager to convert between encodings. The connection manager MAY inform the client which encodings it can convert by setting the optional 'charsets' attribute in the session creation response element to a space-separated list of encodings. <p>The &lt;body/&gt; element SHOULD also include the following attributes (they SHOULD NOT be included in any other responses):</p>
<note>Each character set name (or character encoding name -- we use the terms interchangeably) SHOULD be of type NMTOKEN, where the names are separated by the white space character #x20, resulting in a tokenized attribute type of NMTOKENS (see Section 3.3.1 of &w3xml;). Strictly speaking, the Character Sets registry maintained by the Internet Assigned Numbers Authority (see &lt;<link url='http://www.iana.org/assignments/character-sets'>http://www.iana.org/assignments/character-sets</link>&gt;) allows a character set name to contain any printable US-ASCII character, which might include characters not allowed by the NMTOKEN construction of XML 1.0; however, the only existing character set name which includes such a character is "NF_Z_62-010_(1973)".</note> <ul>
</p> <li><strong>'ver'</strong> -- This attribute specifies the highest version of the BOSH protocol that the connection manager supports, or the version specified by the client in its request, whichever is lower.</li>
<li><strong>'polling'</strong> -- This attribute specifies the shortest allowable polling interval (in seconds). This enables the client to not send empty request elements more often than desired (see <link url="#poll">Polling Sessions</link> and <link url="#overactive">Overactivity</link>).</li>
<li><strong>'inactivity'</strong> -- This attribute specifies the longest allowable inactivity period (in seconds). This enables the client to ensure that the periods with no requests pending are never too long (see <link url="#poll">Polling Sessions</link> and <link url="#inactive">Inactivity</link>).</li>
<li><strong>'requests'</strong> -- This attribute enables the connection manager to limit the number of simultaneous requests the client makes (see <link url="#overactive">Overactivity</link> and <link url="#poll">Polling Sessions</link>). The RECOMMENDED values are either "2" or one more than the value of the 'hold' attribute specified in the session request.</li>
<li><strong>'hold'</strong> -- This attribute informs the client about the maximum number of requests the connection manager may keep waiting at any one time during the session. This value MUST NOT be greater than the value specified by the client in the session request.</li>
</ul>
<p>The connection manager MAY include an <strong>'accept'</strong> attribute in the session creation response element, to specify the content encodings it can decompress. After receiving a session creation response with an 'accept' attribute, clients MAY include an HTTP Content-Encoding header in subsequent requests (indicating one of the encodings specified in the 'accept' attribute) and compress the bodies of the requests accordingly.</p>
<p>If the connection manager supports session pausing (see <link url="#inactive">Inactivity</link>) then it SHOULD advertise that to the client by including a <strong>'maxpause'</strong> attribute in the session creation response element. The value of the attribute indicates the maximum length of a temporary session pause (in seconds) that a client MAY request.</p>
<p>For both requests and responses, the &lt;body/&gt; element and its content SHOULD be UTF-8 encoded. If the HTTP Content-Type header of a request/response specifies a character encoding other than UTF-8, then the connection manager MAY convert between UTF-8 and the other character encoding. However, even in this case, it is OPTIONAL for the connection manager to convert between encodings. The connection manager MAY inform the client which encodings it can convert by setting the optional <strong>'charsets'</strong> attribute in the session creation response element to a space-separated list of encodings. <note>Each character set name (or character encoding name -- we use the terms interchangeably) SHOULD be of type NMTOKEN, where the names are separated by the white space character #x20, resulting in a tokenized attribute type of NMTOKENS (see Section 3.3.1 of &w3xml;). Strictly speaking, the Character Sets registry maintained by the Internet Assigned Numbers Authority (see &lt;<link url='http://www.iana.org/assignments/character-sets'>http://www.iana.org/assignments/character-sets</link>&gt;) allows a character set name to contain any printable US-ASCII character, which might include characters not allowed by the NMTOKEN construction of XML 1.0; however, the only existing character set name which includes such a character is "NF_Z_62-010_(1973)".</note></p>
<p>As soon as the connection manager has established a connection to the &server; and discovered its identity, it MAY forward the identity to the client by including a <strong>'from'</strong> attribute in a response, either in its session creation response, or (if it has not received the identity from the &server; by that time) in any subsequent response to the client. If it established a secure connection to the &server; (as defined in <link url='#session'>Initiating an HTTP Session</link>), then in the same response the connection manager SHOULD also include the <strong>'secure'</strong> attribute set to "true" or "1".</p>
<example caption="Session creation response"> <example caption="Session creation response">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 128 Content-Length: 128
<body authid='ServerStreamID' <body wait='60'
wait='60'
inactivity='30' inactivity='30'
polling='5' polling='5'
requests='2' requests='2'
hold='1'
accept='deflate,gzip' accept='deflate,gzip'
maxpause='120'
sid='SomeSID' sid='SomeSID'
charsets='ISO_8859-1 ISO-2022-JP'
ver='1.6'
from='jabber.org'
secure='true' secure='true'
charsets='ISO_8859-1 ISO-2022-JP'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>Note: The 'authid' attribute contains the value of the XMPP stream ID generated by the XMPP server. The connection manager MUST retrieve the stream ID and pass it unmodified to the client. This value is needed by the client to successfully complete digest authentication using &xep0078; (see the <link url="#preconditions-iqauth">jabber:iq:auth</link> section below).</p>
<p>Note: If the 'authid' attribute is not included in the connection manager's response to the session creation request (e.g., because the connection manager has not yet received a stream ID from the XMPP server), then the client SHOULD send empty request elements (see the "Requesting XML Stanzas" example below) until it receives a response with an 'authid' attribute. In any case, the connection manager MUST return the 'authid' in a response to the client as soon as possible after it receives the stream ID from the XMPP server.</p>
<p>Separate 'sid' and 'authid' attributes are required because the connection manager is not necessarily part of a single XMPP server (e.g., it may handle HTTP connections on behalf of multiple XMPP servers).</p> <example caption="Subsequent response with 'from' and 'secure' attributes">
<p>If it established a secure connection to the XMPP server (as defined in <link url='#session'>Initiating an HTTP Session</link>), then the connection manager SHOULD include the 'secure' attribute set to 'true' or '1' in the response to the client that contains the 'authid' attribute.</p>
</section2>
<section2 topic="Communication of Stream Features" anchor='session-features'>
<p>As an immediate child of the response that contains the 'authid' attribute, the connection manager SHOULD include a stream features element, as defined by <cite>RFC 3920</cite>.</p>
<example caption="Session creation response with stream features">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 417 Content-Length: 128
<body authid='ServerStreamID' <body from='jabber.org'
wait='60' secure='true'
inactivity='30' xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
polling='5'
requests='2'
accept='deflate,gzip'
sid='SomeSID'
charsets='ISO_8859-1 ISO-2022-JP'
xmlns='http://jabber.org/protocol/httpbind'
xmlns:stream='http://etherx.jabber.org/streams'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'>
</stream:features>
</body>]]></example>
<p>The stream features SHOULD NOT include a feature for Transport Layer Security (TLS), since channel encryption SHOULD be negotiated at the HTTP layer (see the <link url="#security">Security Considerations</link> section below).</p>
</section2>
</section1>
<section1 topic="Additional Preconditions" anchor='preconditions'>
<p>Initializing an HTTP session is the first precondition to sending XML message, presence, and IQ stanzas. However, before processing XML stanzas from the client, the connection manager MUST require completion of additional preconditions using either of the following methods:</p>
<ul>
<li>
<p>XMPP authentication, resource binding, and IM session creation, in the following order:</p>
<ol>
<li>Optionally, TLS negotiation as defined in Section 5 of <cite>RFC 3920</cite> (this is NOT RECOMMENDED since channel encryption and compression SHOULD be negotiated at the HTTP layer; see the <link url="#security">Security Considerations</link> section below)</li>
<li>SASL authentication as defined in Section 6 of <cite>RFC 3920</cite></li>
<li>Resource Binding as defined in Section 7 of <cite>RFC 3920</cite></li>
<li>IM Session Establishment as defined in Section 3 of <cite>RFC 3921</cite>, if appropriate</li>
</ol>
</li>
<li>
<p>Simultaneous authentication and resource binding as defined in <strong>Non-SASL Authentication</strong>, upon which a Jabber server will also establish an IM session on behalf of the connected resource.</p>
</li>
</ul>
<p>It is RECOMMENDED to use the XMPP methods as defined in <cite>RFC 3920</cite> and <cite>RFC 3921</cite>, rather than using older non-SASL authentication.</p>
<section2 topic="XMPP Methods" anchor='preconditions-xmpp'>
<p>A success case for authentication, resource binding, and IM session establishment using the XMPP protocols is shown below. For detailed specification of these protocols (including error cases) and for specification of TLS negotiation, refer to <cite>RFC 3920</cite> and <cite>RFC 3921</cite>.</p>
<example caption="SASL authentication step 1">
<![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 172
<body rid='1573741821'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
</body>]]></example>
<example caption="SASL authentication step 2">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 250
<body xmlns='http://jabber.org/protocol/httpbind'>
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>
</body>]]></example>
<example caption="SASL authentication step 3">
<![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 418
<body rid='1573741822'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>
</body>]]></example>
<example caption="SASL authentication step 4">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 190
<body xmlns='http://jabber.org/protocol/httpbind'>
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
</body>]]></example>
<example caption="SASL authentication step 5">
<![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 152
<body rid='1573741823'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>]]></example>
<example caption="SASL authentication step 6">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 121
<body xmlns='http://jabber.org/protocol/httpbind'>
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>]]></example>
<p>Note: Because the context for a client's communication with a connection manager in the HTTP transport binding is HTTP rather than XML streams (as in the TCP binding), there is no need to re-start communications (e.g., by generating a new SID) at this point.</p>
<example caption="Resource binding request">
<![CDATA[POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 240
<body rid='1573741824'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<iq id='bind_1'
type='set'
xmlns='jabber:client'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>httpclient</resource>
</bind>
</iq>
</body>]]></example>
<example caption="Resource binding result">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 221
<body xmlns='http://jabber.org/protocol/httpbind'>
<iq id='bind_1'
type='result'
xmlns='jabber:client'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<jid>stpeter@jabber.org/httpclient</jid>
</bind>
</iq>
</body>]]></example>
<example caption="IM session request">
<![CDATA[POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 261
<body rid='1573741825'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<iq from='stpeter@jabber.org/httpclient'
id='sess_1'
to='jabber.org'
type='set'
xmlns='jabber:client'>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</iq>
</body>]]></example>
<example caption="IM session result">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 175
<body xmlns='http://jabber.org/protocol/httpbind'>
<iq from='jabber.org'
id='sess_1'
to='stpeter@jabber.org/httpclient'
type='result'
xmlns='jabber:client'/>
</body>]]></example>
</section2>
<section2 topic="jabber:iq:auth" anchor='preconditions-iqauth'>
<p>A success case for simultaneous authentication, resource binding, and IM session creation using the original "jabber:iq:auth" protocol is shown below. For further details regarding use of this protocol, refer to XEP-0078. If digest authentication is used, then the stream ID value used to compute the hashed password MUST be the value of the 'authid' attribute provided by the connection manager in the response to the initialization element or in a subsequent response (see the <link url="#session-create">Session Creation</link> section above).</p>
<example caption="Non-SASL authentication request">
<![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 281
<body rid='1249243561'
sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'>
<iq id='A01'
type='set'
xmlns='jabber:client'>
<query xmlns='jabber:iq:auth'>
<username>stpeter</username>
<resource>httpclient</resource>
<password>jabber-rocks</password>
</query>
</iq>
</body>]]></example>
<example caption="Authentication result (success)">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 144
<body xmlns='http://jabber.org/protocol/httpbind'>
<iq id='A01'
type='result'
xmlns='jabber:client'/>
</body>]]></example>
<example caption="Authentication result (failure)">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 226
<body xmlns='http://jabber.org/protocol/httpbind'>
<iq id='A01'
type='error'
xmlns='jabber:client'>
<error code='401' type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
</body>]]></example>
</section2> </section2>
</section1> </section1>
<section1 topic="Sending and Receiving XML Stanzas" anchor='stanzas'> <section1 topic="Sending and Receiving XML Stanzas" anchor='stanzas'>
@ -516,16 +313,16 @@ Content-Length: 188
xmlns='http://jabber.org/protocol/httpbind'> xmlns='http://jabber.org/protocol/httpbind'>
<message to='contact@example.com' <message to='contact@example.com'
xmlns='jabber:client'> xmlns='jabber:client'>
<body>Hi there!</body> <body>I said "Hi!"</body>
</message> </message>
<message to='friend@example.com' <message to='friend@example.com'
xmlns='jabber:client'> xmlns='jabber:client'>
<body>Hi there!</body> <body>I said "Hi!"</body>
</message> </message>
</body>]]></example> </body>]]></example>
<p>Upon receipt of a request, the connection manager MUST forward the content of the &lt;body/&gt; element to the XMPP server as soon as possible. However, it must forward the content from different requests in the order specified by their 'rid' attributes.</p> <p>Upon receipt of a request, the connection manager SHOULD forward the content of the &lt;body/&gt; element to the &server; as soon as possible. In any case it MUST forward the content from different requests in the order specified by their 'rid' attributes.</p>
<p>The connection manager MUST also return an HTTP 200 OK response with a &lt;body/&gt; element to the client. Note: This does not indicate that the stanzas have been successfully delivered to the destination Jabber endpoint.</p> <p>The connection manager MUST also return an HTTP 200 OK response with a &lt;body/&gt; element to the client. Note: This does not indicate that the stanzas have been successfully delivered to the &server;.</p>
<p>It is RECOMMENDED that the connection manager not return an HTTP result until a stanza has arrived from the XMPP server for delivery to the client. However, the connection manager SHOULD NOT wait longer than the time specified by the client in the 'wait' attribute of its session creation request, and it SHOULD NOT keep more HTTP requests waiting at a time than the number specified in the 'hold' attribute of the session creation request. In any case it MUST respond to requests in the order specified by their 'rid' attributes.</p> <p>It is RECOMMENDED that the connection manager not return an HTTP result until a stanza has arrived from the &server; for delivery to the client. However, the connection manager SHOULD NOT wait longer than the time specified by the client in the 'wait' attribute of its <link url="#session-request">Session Creation Request</link>, and it SHOULD NOT keep more HTTP requests waiting at a time than the number specified in the 'hold' attribute of the session creation request. In any case it MUST respond to requests in the order specified by their 'rid' attributes.</p>
<p>If there are no stanzas waiting or ready to be delivered within the waiting period, then the connection manager SHOULD include an empty &lt;body/&gt; element in the HTTP result:</p> <p>If there are no stanzas waiting or ready to be delivered within the waiting period, then the connection manager SHOULD include an empty &lt;body/&gt; element in the HTTP result:</p>
<example caption="Empty response"> <example caption="Empty response">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
@ -533,24 +330,48 @@ Content-Type: text/xml; charset=utf-8
Content-Length: 64 Content-Length: 64
<body xmlns='http://jabber.org/protocol/httpbind'/>]]></example> <body xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>If the connection manager has received one or more stanzas from the XMPP server for delivery to the client, then it SHOULD return the stanzas in the body of its response as soon as possible after receiving them from the XMPP server.</p> <p>If the connection manager has received one or more stanzas from the &server; for delivery to the client, then it SHOULD return the stanzas in the body of its response as soon as possible after receiving them from the &server;. The example below includes stanzas qualified by different namespaces:</p>
<example caption="Response with queued stanza"> <example caption="Response with queued stanza">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 185 Content-Length: 185
<body xmlns='http://jabber.org/protocol/httpbind'> <bosh:body xmlns:bosh='http://jabber.org/protocol/httpbind'
<message from='contact@example.com' xmlns:json='http://json.org/'
to='user@example.com'
xmlns='jabber:client'> xmlns='jabber:client'>
<message from='contact@example.com'
to='user@example.com'>
<body>Hi yourself!</body> <body>Hi yourself!</body>
</message> </message>
<message from='friend@example.com' <message from='friend@example.com'
to='user@example.com' to='user@example.com'>
xmlns='jabber:client'>
<body>Hi yourself!</body> <body>Hi yourself!</body>
</message> </message>
</body>]]></example> <json:json>
[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]
</json:json>
</bosh:body>]]></example>
<p>The client MAY poll the connection manager for incoming stanzas by sending an empty &lt;body/&gt; element.</p> <p>The client MAY poll the connection manager for incoming stanzas by sending an empty &lt;body/&gt; element.</p>
<example caption="Requesting XML Stanzas"> <example caption="Requesting XML Stanzas">
<![CDATA[POST /webclient HTTP/1.1 <![CDATA[POST /webclient HTTP/1.1
@ -563,18 +384,51 @@ Content-Length: 88
sid='SomeSID' sid='SomeSID'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>The connection manager MUST wait and respond in the same way as it does after receiving stanzas from the client.</p> <p>The connection manager MUST wait and respond in the same way as it does after receiving stanzas from the client.</p>
<p>If the client sends two consecutive empty requests within a period shorter than that specified by the 'polling' attribute in the session creation response, then the connection manager SHOULD terminate the HTTP session and return an HTTP 403 (Forbidden) error to the client.</p> </section1>
<section1 topic='Inactivity' anchor='inactive'>
<p>After receiving a response from the connection manager, if none of the client's requests are still being held by the connection manager (and if the session is not a <link url="#poll">Polling Session</link>), the client SHOULD make a new request as soon as possible. In any case, if no requests are being held, the client MUST make a new request before the maximum inactivity period has expired. The length of this period in seconds is specified by the 'inactivity' attribute in the session creation response.</p>
<p>If the connection manager has responded to all the requests it has received within a session and the time since its last response is longer than the maximum inactivity period, then it SHOULD assume the client has been disconnected and terminate the session without informing the client. If the client subsequently makes another request, then the connection manager SHOULD respond as if the session does not exist.</p>
<p>If the connection manager did not specify a maximum inactivity period in the session creation response, then it SHOULD allow the client to be inactive for as long as it chooses.</p>
<p>If the session is not a polling session then the connection manager SHOULD specify a relatively short inactivity period to ensure disconnections are discovered as early as possible. The RECOMMENDED time would be a little more than the number of seconds for a comfortable network round trip between the connection manager and the client under difficult network conditions (since the client can be expected to make a new request immediately - see above).</p>
<p>If a client encounters an exceptional temporary situation during which it will be unable to send requests to the connection manager for a period of time greater than the maximum inactivity period, and if the connection manager included a 'maxpause' attribute in its <link url="#session-create">Session Creation Response</link>, then the client MAY request a temporary increase to the maximum inactivity period by including a 'pause' attribute in a request. Note: If the connection manager did not specify a 'maxpause' attribute at the start of the session then the client MUST NOT send a 'pause' attribute during the session.</p>
<example caption="Requesting a Session Pause">
<![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 98
<body rid='1249243564'
sid='SomeSID'
pause='60'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>Upon reception of a session pause request, if the requested period is not greater than the maximum permitted time, then the connection manager SHOULD respond immediately to all pending requests (including the pause request) and <em>temporarily</em> increase the maximum inactivity period to the requested time. Note: The response to the pause request MUST NOT contain any stanzas.</p>
<p>The connection manager SHOULD set the maximum inactivity period back to normal upon reception of the next request from the client (assuming the connection manager hasn't already terminated the session).</p>
</section1>
<section1 topic='Overactivity' anchor='overactive'>
<p>The client SHOULD NOT make more simultaneous requests than specified by the 'requests' attribute in the connection manager's <link url="#session-create">Session Creation Response</link>. However the client MAY make one additional request if it is to <link url="#inactive">pause</link> or <link url="#terminate">terminate</link> a session.</p>
<p>If during any period the client sends a sequence of new requests (i.e. requests with incremented rid attributes, not repeat requests) longer than the number specified by the 'requests' attribute, and if the connection manager has not yet responded to any of the requests, and if the last request did not include either a 'pause' attribute or a 'type' attribute set to "terminate", then the connection manager SHOULD consider that the client is making too many simultaneous requests and terminate the HTTP session and return an HTTP 403 (Forbidden) error to the client. Note: This behavior applies to equally to normal and polling sessions.</p>
<example caption="Too many simultaneous requests response">
<![CDATA[HTTP/1.1 403 Forbidden
Content-Length: 0]]></example>
<p>Note: If the connection manager did not specify a 'requests' attribute in the session creation response, then it MUST allow the client to send as many simultaneous requests as it chooses.</p>
<p>If during any period the client sends a sequence of new requests equal in length to the number specified by the 'requests' attribute, and if the connection manager has not yet responded to any of the requests, and if the last request was empty and did not include either a 'pause' attribute or a 'type' attribute set to "terminate", and if the last two requests arrived within a period shorter than the number of seconds specified by the 'polling' attribute in the session creation response, then the connection manager SHOULD consider that the client is making requests more frequently than it was permitted and terminate the HTTP session and return an HTTP 403 (Forbidden) error to the client. Note: the behavior for <link url="#poll">Polling Sessions</link> is slightly different.</p>
<example caption="Too frequent requests response">
<![CDATA[HTTP/1.1 403 Forbidden
Content-Length: 0]]></example>
<p>Note: If the connection manager did not specify a 'polling' attribute in the session creation response, then it MUST allow the client to send requests as frequently as it chooses.</p>
</section1>
<section1 topic='Polling Sessions' anchor='poll'>
<p>It may not be possible for a constrained client to either use HTTP Pipelining or open more than one HTTP connection with the connection manager at a time. In this case the client SHOULD inform the connection manager by setting the values of the 'wait' and/or 'hold' attributes in its session creation request to "0", and then "poll" the connection manager at regular intervals throughout the session for stanzas it may have received from the server. Note: Even if the client does not request a polling session then the connection manager MAY require a client to use polling by setting the 'requests' attribute (which specifies the number of simultaneous requests the client may make) of its <link url="#session-create">Session Creation Response</link> to "1", however this is NOT RECOMMENDED.</p>
<p>If a session will use polling the connection manager SHOULD specify a higher than normal value for the 'inactivity' attribute (see <link url="#inactive">Inactivity</link>) in its session creation response. The increase SHOULD be greater than the value it specifies for the 'polling' attribute.</p>
<p>If the client sends two consecutive empty new requests (i.e. requests with incremented rid attributes, not repeat requests) within a period shorter than the number of seconds specified by the 'polling' attribute (the shortest allowable polling interval) in the session creation response, and if the connection manager's response to the first request contained no stanzas, then upon reception of the second request the connection manager SHOULD terminate the HTTP session and return an HTTP 403 (Forbidden) error to the client.</p>
<example caption="Too frequent polling response"> <example caption="Too frequent polling response">
<![CDATA[HTTP/1.1 403 Forbidden <![CDATA[HTTP/1.1 403 Forbidden
Content-Type: text/xml; charset=utf-8
Content-Length: 0]]></example> Content-Length: 0]]></example>
<p>If the connection manager did not specify a shortest allowable polling interval in the session creation response, then it MUST allow the client to poll as frequently as it chooses.</p> <p>Note: If the connection manager did not specify a 'polling' attribute in the session creation response, then it MUST allow the client to poll as frequently as it chooses.</p>
<p>After receiving a response from the connection manager, if no other requests are pending and the client did not specify polling behavior in the session creation request (by setting 'wait' or 'hold' to "0"), it SHOULD make a new request as soon as possible. In any case, if no requests are pending, the client MUST make a new request before the maximum inactivity period has expired. This period is specified by the 'inactivity' attribute in the session creation response.</p>
<p>If the connection manager has responded to all the requests it has received and the time since its last response is longer than the maximum inactivity period, then it SHOULD terminate the session without informing the client (if the client makes another request, the connection manager SHOULD respond as if the session does not exist).</p>
<p>If the connection manager did not specify a maximum inactivity period in the session creation response, then it MUST allow the client to be inactive for as long as it chooses.</p>
</section1> </section1>
<section1 topic='Terminating the HTTP Session' anchor='terminate'> <section1 topic='Terminating the HTTP Session' anchor='terminate'>
<p>At any time, the client MAY gracefully terminate the session by sending a &lt;body/&gt; element with a 'type' attribute set to "terminate". The termination request SHOULD include an XMPP presence stanza of type "unavailable" to ensure graceful logoff with the XMPP server.</p> <p>At any time, the client MAY gracefully terminate the session by sending a &lt;body/&gt; element with a 'type' attribute set to "terminate". The termination request MAY include one or more stanzas that the connection manager MUST forward to the &server; to ensure graceful logoff.</p>
<example caption="Session termination by client"> <example caption="Session termination by client">
<![CDATA[POST /webclient HTTP/1.1 <![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org Host: httpcm.jabber.org
@ -582,7 +436,7 @@ Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 153 Content-Length: 153
<body rid='1249243564' <body rid='1249243565'
sid='SomeSID' sid='SomeSID'
type='terminate' type='terminate'
xmlns='http://jabber.org/protocol/httpbind'> xmlns='http://jabber.org/protocol/httpbind'>
@ -593,22 +447,20 @@ Content-Length: 153
</section1> </section1>
<section1 topic="Request IDs" anchor='rids'> <section1 topic="Request IDs" anchor='rids'>
<section2 topic='Syntax' anchor='rids-syntax'> <section2 topic='Syntax' anchor='rids-syntax'>
<p>The client MUST generate a large, random, positive integer for the initial 'rid' (see <link url="#security">Security Considerations</link>) and then increment that value by one for each subsequent request. The client MUST take care to choose an initial 'rid' that will never be incremented above 9007199254740991 <note>9007199254740991 is 2<span class='super'>53</span>-1. Some weakly typed languages use IEEE Standard 754 Doubles to represent all numbers. These Doubles cannot represent integers above 2<span class='super'>53</span> accurately.</note> within the session. In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary number of packets) to exceed the defined limit.</p> <p>The client MUST generate a large, random, positive integer for the initial 'rid' (this prevents proxies from caching Script Syntax responses, also see <link url="#security">Security Considerations</link>) and then increment that value by one for each subsequent request. The client MUST take care to choose an initial 'rid' that will never be incremented above 9007199254740991 <note>9007199254740991 is 2<span class='super'>53</span>-1. Some weakly typed languages use IEEE Standard 754 Doubles to represent all numbers. These Doubles cannot represent integers above 2<span class='super'>53</span> accurately.</note> within the session. In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary number of packets) to exceed the defined limit.</p>
</section2> </section2>
<section2 topic='In-Order Message Forwarding' anchor='rids-order'> <section2 topic='In-Order Message Forwarding' anchor='rids-order'>
<p>When a client makes simultaneous requests, the connection manager may receive them out of order. The connection manager MUST forward the stanzas to the XMPP server and respond to the client requests in the order specified by the 'rid' attributes. The client MUST process responses received from the connection manager in the order the requests were made.</p> <p>When a client makes simultaneous requests, the connection manager may receive them out of order. The connection manager MUST forward the stanzas to the &server; and respond to the client requests in the order specified by the 'rid' attributes. The client MUST process responses received from the connection manager in the order the requests were made.</p>
<p>The connection manager SHOULD expect the 'rid' attribute to be within a window of values greater than the 'rid' of the previous request. The size of the window is equal to the maximum number of simultaneous requests allowed by the connection manager. If it receives a request with a 'rid' greater than the values in the window, then the connection manager MUST terminate the session with an error:</p> <p>The connection manager SHOULD expect the 'rid' attribute to be within a window of values greater than the 'rid' of the previous request. The size of the window is equal to the maximum number of simultaneous requests allowed by the connection manager. If it receives a request with a 'rid' greater than the values in the window, then the connection manager MUST terminate the session with an error:</p>
<example caption="Unexpected rid error"> <example caption="Unexpected rid error">
<![CDATA[HTTP/1.1 404 Not Found <![CDATA[HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0]]></example> Content-Length: 0]]></example>
</section2> </section2>
<section2 topic='Broken Connections' anchor='rids-broken'> <section2 topic='Broken Connections' anchor='rids-broken'>
<p>Unreliable network communications or client constraints can result in broken connections. The connection manager SHOULD remember the 'rid' and the associated HTTP response body of the client's most recent requests which did not result in an HTTP or binding error. The number of responses kept in the buffer should be the same as the maximum number of simultaneous requests allowed by the connection manager.</p> <p>Unreliable network communications or client constraints can result in broken connections. The connection manager SHOULD remember the 'rid' and the associated HTTP response body of the client's most recent requests which were not session pause requests (see <link url="#inactive">Inactivity</link>) and which did not result in an HTTP or binding error. The number of responses to non-pause requests kept in the buffer SHOULD be the same as the maximum number of simultaneous requests allowed by the connection manager.</p>
<p>If the network connection is broken or closed before the client receives a response to a request from the connection manager, then the client MAY resend an exact copy of the original request. Whenever the connection manager receives a request with a 'rid' that it has already received, it SHOULD return an HTTP 200 (OK) response that includes the buffered copy of the original XML response to the client (i.e., a &lt;body/&gt; wrapper element possessing appropriate attributes and optionally containing one or more XML stanzas or other allowable XML elements). If the original response is not available (e.g., it is no longer in the buffer), then the connection manager MUST return an HTTP 404 (Not Found) error:</p> <p>If the network connection is broken or closed before the client receives a response to a request from the connection manager, then the client MAY resend an exact copy of the original request. Whenever the connection manager receives a request with a 'rid' that it has already received, it SHOULD return an HTTP 200 (OK) response that includes the buffered copy of the original XML response to the client (i.e., a &lt;body/&gt; wrapper possessing appropriate attributes and optionally containing one or more XML stanzas or other allowable XML elements). If the original response is not available (e.g., it is no longer in the buffer), then the connection manager MUST return an HTTP 404 (Not Found) error:</p>
<example caption="Response not in buffer error"> <example caption="Response not in buffer error">
<![CDATA[HTTP/1.1 404 Not Found <![CDATA[HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0]]></example> Content-Length: 0]]></example>
<p>Note: The error is the same whether the 'rid' is too large or too small. This makes it more difficult for an attacker to discover an acceptable value.</p> <p>Note: The error is the same whether the 'rid' is too large or too small. This makes it more difficult for an attacker to discover an acceptable value.</p>
</section2> </section2>
@ -616,7 +468,7 @@ Content-Length: 0]]></example>
<section1 topic="Protecting Insecure Sessions" anchor='keys'> <section1 topic="Protecting Insecure Sessions" anchor='keys'>
<section2 topic="Applicability" anchor='keys-applic'> <section2 topic="Applicability" anchor='keys-applic'>
<p>The OPTIONAL key sequencing mechanism described here MAY be used if the client's session with the connection manager is not secure. The session should be considered secure only if all client requests are made via SSL (or TLS) HTTP connections and the connection manager generates an unpredictable session ID. If the session is secure, it is not necessary to use this key sequencing mechanism.</p> <p>The OPTIONAL key sequencing mechanism described here MAY be used if the client's session with the connection manager is not secure. The session should be considered secure only if all client requests are made via SSL (or TLS) HTTP connections and the connection manager generates an unpredictable session ID. If the session is secure, it is not necessary to use this key sequencing mechanism.</p>
<p>Even if the session is not secure, the unpredictable session and request IDs specified in the preceding sections of this document already provide a level of protection similar to that provided by a standard XMPP connection bound to a single pair of persistent TCP/IP connections, and thus provide sufficient protection against a 'blind' attacker. However, in some circumstances, the key sequencing mechanism defined below helps to protect against a more determined and knowledgeable attacker.</p> <p>Even if the session is not secure, the unpredictable session and request IDs specified in the preceding sections of this document already provide a level of protection similar to that provided by a connection bound to a single pair of persistent TCP/IP connections, and thus provide sufficient protection against a 'blind' attacker. However, in some circumstances, the key sequencing mechanism defined below helps to protect against a more determined and knowledgeable attacker.</p>
<p>It is important to recognize that the key sequencing mechanism defined below helps to protect only against an attacker who is able to view the contents of all requests or responses in an insecure session but who is not able to alter the contents of those requests (in this case, the mechanism prevents the attacker from interjecting HTTP requests into the session, e.g., termination requests or responses). However, the key sequencing mechanism does not provide any protection when the attacker is able to alter the contents of insecure requests or responses.</p> <p>It is important to recognize that the key sequencing mechanism defined below helps to protect only against an attacker who is able to view the contents of all requests or responses in an insecure session but who is not able to alter the contents of those requests (in this case, the mechanism prevents the attacker from interjecting HTTP requests into the session, e.g., termination requests or responses). However, the key sequencing mechanism does not provide any protection when the attacker is able to alter the contents of insecure requests or responses.</p>
</section2> </section2>
<section2 topic="Introduction" anchor='keys-intro'> <section2 topic="Introduction" anchor='keys-intro'>
@ -664,7 +516,6 @@ Content-Length: 88
<p>The connection manager MAY verify the key by calculating the SHA-1 hash of the key and comparing it to the 'newkey' attribute of the previous request (or the 'key' attribute if the 'newkey' attribute was not set). If the values do not match (or if it receives a request without a 'key' attribute and the 'newkey' or 'key' attribute of the previous request was set), then the connection manager MUST NOT process the element, MUST terminate the session, and MUST return an HTTP 404 (Not Found) error.</p> <p>The connection manager MAY verify the key by calculating the SHA-1 hash of the key and comparing it to the 'newkey' attribute of the previous request (or the 'key' attribute if the 'newkey' attribute was not set). If the values do not match (or if it receives a request without a 'key' attribute and the 'newkey' or 'key' attribute of the previous request was set), then the connection manager MUST NOT process the element, MUST terminate the session, and MUST return an HTTP 404 (Not Found) error.</p>
<example caption="Invalid Key Sequence Error"> <example caption="Invalid Key Sequence Error">
<![CDATA[HTTP/1.1 404 Not Found <![CDATA[HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0]]></example> Content-Length: 0]]></example>
</section2> </section2>
<section2 topic="Switching to Another Key Sequence" anchor='keys-switch'> <section2 topic="Switching to Another Key Sequence" anchor='keys-switch'>
@ -690,7 +541,7 @@ Content-Length: 188
xmlns='http://jabber.org/protocol/httpbind'> xmlns='http://jabber.org/protocol/httpbind'>
<message to='contact@example.com' <message to='contact@example.com'
xmlns='jabber:client'> xmlns='jabber:client'>
<body>Hi there!</body> <body>I said "Hi!"</body>
</message> </message>
</body>]]></example> </body>]]></example>
</section2> </section2>
@ -698,30 +549,33 @@ Content-Length: 188
<section1 topic='Multiple Streams' anchor='multi'> <section1 topic='Multiple Streams' anchor='multi'>
<section2 topic="Introduction" anchor='multi-intro'> <section2 topic="Introduction" anchor='multi-intro'>
<p>The OPTIONAL feature described in this section enables multiple XMPP streams to be contained within a single HTTP session. This feature is essential in runtime environments that constrain the number of simultaneous HTTP requests a client may make to each connection manager, since clients running in such environments need multi-stream sessions if they are to connect using more than one account at the same time. This feature also reduces network traffic for any client that needs to establish parallel streams over HTTP.</p> <p>The OPTIONAL feature described in this section enables multiple XML streams to be contained within a single HTTP session. This feature is essential in runtime environments that prevent HTTP Pipelining, thereby constraining the number of simultaneous HTTP requests a client may make to each connection manager, since clients running in such environments need multi-stream sessions if they are to connect using more than one account at the same time. This feature also reduces network traffic for any client that needs to establish parallel streams over HTTP.</p>
</section2> </section2>
<section2 topic="Discovery" anchor='multi-discover'> <section2 topic="Discovery" anchor='multi-discover'>
<p>If a connection manager supports the multi-streams feature, it MUST include a 'stream' attribute in its session creation response. If a client does not receive the 'stream' attribute then it MUST assume that the connection manager does not support the feature. <note>Therefore a client and a connection manager will be compatible even if one or the other offers no support for multi-stream sessions.</note></p> <p>If a connection manager supports the multi-streams feature, it MUST include a 'stream' attribute in its <link url="#session-create">Session Creation Response</link>. If a client does not receive the 'stream' attribute then it MUST assume that the connection manager does not support the feature. <note>Therefore a client and a connection manager will be compatible even if one or the other offers no support for multi-stream sessions.</note></p>
<p>The 'stream' attribute identifies the first stream to be opened for the session. The value of each 'stream' attribute MUST be an opaque and unpredictable name that is unique within the context of the connection manager application.</p> <p>The 'stream' attribute identifies the first stream to be opened for the session. The value of each 'stream' attribute MUST be an opaque and unpredictable name that is unique within the context of the connection manager application.</p>
<example caption="Session creation response with stream name"> <example caption="Session creation response with stream name">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 128 Content-Length: 128
<body authid='ServerStreamID' <body wait='60'
wait='60'
inactivity='30' inactivity='30'
polling='5' polling='5'
requests='2' requests='2'
hold='1'
accept='deflate,gzip' accept='deflate,gzip'
sid='SomeSID'
secure='true'
stream='firstStreamName' stream='firstStreamName'
maxpause='120'
sid='SomeSID'
charsets='ISO_8859-1 ISO-2022-JP' charsets='ISO_8859-1 ISO-2022-JP'
ver='1.6'
from='jabber.org'
secure='true'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
</section2> </section2>
<section2 topic="Adding Streams To A Session" anchor='multi-add'> <section2 topic="Adding Streams To A Session" anchor='multi-add'>
<p>If the connection manager included a 'stream' attribute in its session creation response then the client MAY ask it to open another stream at any time by sending it an empty &lt;body/&gt; element with a 'to' attribute. The request MUST include valid 'sid' and 'rid' <note>The 'rid' attribute is always incremented normally without reference to any 'stream' attribute.</note> attributes, it SHOULD also include an 'xml:lang' attribute. The request MAY include 'route' and 'secure' attributes (see <link url="#session-request">Requesting a Session</link> above), but it SHOULD NOT include 'content', 'hold' or 'wait' attributes.</p> <p>If the connection manager included a 'stream' attribute in its session creation response then the client MAY ask it to open another stream at any time by sending it an empty &lt;body/&gt; element with a 'to' attribute. The request MUST include valid 'sid' and 'rid' <note>The 'rid' attribute is always incremented normally without reference to any 'stream' attribute.</note> attributes, it SHOULD also include an 'xml:lang' attribute. The request MAY include 'route', 'from' and 'secure' attributes (see <link url="#session-request">Session Creation Request</link>), but it SHOULD NOT include 'ver', 'content', 'hold' or 'wait' attributes (since a new session is not being created).</p>
<example caption="Requesting another stream"> <example caption="Requesting another stream">
<![CDATA[POST /webclient HTTP/1.1 <![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org Host: httpcm.jabber.org
@ -736,22 +590,22 @@ Content-Length: 104
secure='true' secure='true'
xml:lang='en' xml:lang='en'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>If the connection manager did not indicate its support for multiple streams at the start of the session then it MUST ignore the extra attributes and treat the request as a normal empty request for stanzas (see <link url="#stanzas">Sending and Receiving XML Stanzas</link> above). <note>This helps to ensure backwards-compatibility with older implementations.</note> Otherwise it MUST open a new stream with the specified server (see <link url="#session-create">Session Creation</link> above), generate a new stream name and respond to the client with the name. The response MAY also include 'authid' and 'secure' attributes, but it SHOULD NOT include 'sid', 'requests', 'polling', 'inactivity', 'accept', 'charsets' or 'wait' attributes.</p> <p>If the connection manager did not indicate its support for multiple streams at the start of the session then it MUST ignore the extra attributes and treat the request as a normal empty request for stanzas (see <link url="#stanzas">Sending and Receiving XML Stanzas</link>). <note>This helps to ensure backwards-compatibility with older implementations.</note> Otherwise it MUST open a new stream with the specified &server; (see <link url="#session-create">Session Creation Response</link>), generate a new stream name and respond to the client with the name. The response MAY also include 'from' and 'secure' attributes, but it SHOULD NOT include 'sid', 'requests', 'polling', 'hold', 'inactivity', 'maxpause', 'accept', 'charsets', 'ver' or 'wait' attributes.</p>
<example caption="Add stream response"> <example caption="Add stream response">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
Content-Length: 128 Content-Length: 128
<body stream='secondStreamName' <body stream='secondStreamName'
authid='ServerStreamID' from='jabber.org'
secure='true' secure='true'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>Note: If the response did not include an 'authid' then the attribute (and any associated 'secure' attribute) MUST be sent in a subsequent response instead (see <link url="#session-create">Session Creation</link> above). In that case the 'stream' attribute MUST also be specified.</p> <p>Note: If the response did not include either 'from' or 'secure' attributes then they MAY be sent in a subsequent response instead (see <link url="#session-create">Session Creation Response</link>). In that case the 'stream' attribute MUST also be specified.</p>
</section2> </section2>
<section2 topic="Transmitting Stanzas" anchor='multi-transmit'> <section2 topic="Transmitting Stanzas" anchor='multi-transmit'>
<p>If more than one stream has been opened within a session, then all non-empty &lt;body/&gt; elements sent by the connection manager MUST include a 'stream' attribute that specifies which stream all the stanzas it contains belong to. The client SHOULD include a 'stream' attribute for the same purpose. The client MAY omit the 'stream' attribute if it wants the connection manager to broadcast the stanzas over all open streams. Note: A &lt;body/&gt; element MUST NOT contain different stanzas for different streams.</p> <p>If more than one stream has been opened within a session, then all non-empty &lt;body/&gt; elements sent by the connection manager MUST include a 'stream' attribute that specifies which stream <em>all</em> the stanzas it contains belong to. The client SHOULD include a 'stream' attribute for the same purpose. The client MAY omit the 'stream' attribute if it wants the connection manager to broadcast the stanzas over all open streams. Note: A &lt;body/&gt; element MUST NOT contain different stanzas for different streams.</p>
<p>If a stream name does not correspond to one of the session's open streams, then the receiving connection manager SHOULD return an HTTP 404 (Not Found) error, or the receiving client SHOULD terminate the session. However, if the receiving entity has only just closed the stream (and the sender may not have been aware of that when it sent the stanzas), then it MAY instead simply silently ignore any stanzas the &lt;body/&gt; element contains.</p> <p>If a stream name does not correspond to one of the session's open streams, then the receiving connection manager SHOULD return an HTTP 404 (Not Found) error, or the receiving client SHOULD terminate the session. However, if the receiving entity has only just closed the stream (and the sender may not have been aware of that when it sent the stanzas), then it MAY instead simply silently ignore any stanzas the &lt;body/&gt; element contains.</p>
<p>Note: Empty &lt;body/&gt; elements that do not include an 'authid' attribute SHOULD NOT include a 'stream' attribute (since nothing is being transmitted for any stream). If such a &lt;body/&gt; element does include a 'stream' attribute then the receiving entity SHOULD ignore the attribute.</p> <p>Note: Empty &lt;body/&gt; elements that do not include a 'from' or 'secure' attribute SHOULD NOT include a 'stream' attribute (since nothing is being transmitted for any stream). If such a &lt;body/&gt; element does include a 'stream' attribute then the receiving entity SHOULD ignore the attribute.</p>
<example caption="Client sends stanza with a stream name"> <example caption="Client sends stanza with a stream name">
<![CDATA[POST /webclient HTTP/1.1 <![CDATA[POST /webclient HTTP/1.1
Host: httpcm.jabber.org Host: httpcm.jabber.org
@ -765,7 +619,7 @@ Content-Length: 188
xmlns='http://jabber.org/protocol/httpbind'> xmlns='http://jabber.org/protocol/httpbind'>
<message to='contact@example.com' <message to='contact@example.com'
xmlns='jabber:client'> xmlns='jabber:client'>
<body>Hi there!</body> <body>I said "Hi!"</body>
</message> </message>
</body>]]></example> </body>]]></example>
<p>Note: The value of the 'stream' attribute of the response MAY be different to the corresponding request. <note>Each HTTP response MUST belong to the same session as the request that triggered it, but not necessarily to the same stream.</note></p> <p>Note: The value of the 'stream' attribute of the response MAY be different to the corresponding request. <note>Each HTTP response MUST belong to the same session as the request that triggered it, but not necessarily to the same stream.</note></p>
@ -818,7 +672,7 @@ Content-Length: 153
</body>]]></example> </body>]]></example>
</section2> </section2>
<section2 topic='Error Conditions' anchor='multi-error'> <section2 topic='Error Conditions' anchor='multi-error'>
<p>If more than one stream is open within a session, the connection manager MAY include a 'stream' attribute in a fatal binding error (see <link url="#errorstatus-terminal">Terminal Binding Conditions</link> below). If a 'stream' attribute is specified then the stream MUST be closed by both entities but the session SHOULD NOT be terminated.</p> <p>If more than one stream is open within a session, the connection manager MAY include a 'stream' attribute in a fatal binding error (see <link url="#errorstatus-terminal">Terminal Binding Conditions</link>). If a 'stream' attribute is specified then the stream MUST be closed by both entities but the session SHOULD NOT be terminated.</p>
<example caption="Fatal stream error"> <example caption="Fatal stream error">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
@ -837,14 +691,13 @@ Content-Length: 68
<table caption='Error Condition Types'> <table caption='Error Condition Types'>
<tr><th>Condition Type</th><th>Description</th></tr> <tr><th>Condition Type</th><th>Description</th></tr>
<tr><td><strong>HTTP Conditions</strong></td><td>The connection manager responds to an invalid client request with a standard HTTP error. These are used for binding syntax errors, possible attacks, etc. Note that constrained clients are unable to differentiate between HTTP errors.</td></tr> <tr><td><strong>HTTP Conditions</strong></td><td>The connection manager responds to an invalid client request with a standard HTTP error. These are used for binding syntax errors, possible attacks, etc. Note that constrained clients are unable to differentiate between HTTP errors.</td></tr>
<tr><td><strong>Terminal Binding Conditions</strong></td><td>These error conditions may be read by constrained clients. They are used for connection manager problems, abstracting stream errors, and communication problems between the connection manager and the XMPP server.</td></tr> <tr><td><strong>Terminal Binding Conditions</strong></td><td>These error conditions may be read by constrained clients. They are used for connection manager problems, abstracting stream errors, and communication problems between the connection manager and the &server;.</td></tr>
<tr><td><strong>Recoverable Binding Conditions</strong></td><td>These report communication problems between the connection manager and the client. They do not terminate the session. Clients recover from these errors by resending all the preceding &lt;body/&gt; wrapper elements that have not received responses.</td></tr> <tr><td><strong>Recoverable Binding Conditions</strong></td><td>These report communication problems between the connection manager and the client. They do not terminate the session. Clients recover from these errors by resending all the preceding &lt;body/&gt; wrappers that have not received responses.</td></tr>
<tr><td><strong>XMPP Stanza Conditions</strong></td><td>XMPP errors relating to XML stanzas within &lt;body/&gt; wrapper elements are, in general, defined in the appropriate RFC or XEP. They do not terminate the session. (An example of such usage is shown in <link url="#preconditions-iqauth">jabber:iq:auth</link> above.)</td></tr> <tr><td><strong>Transported Protocol Conditions</strong></td><td>Errors relating to the XML stanzas <em>within</em> &lt;body/&gt; wrappers are, in general, defined in the documentation of the protocol being transported. They do not terminate the session.</td></tr>
</table> </table>
<p>Full descriptions are provided below.</p> <p>Full descriptions are provided below.</p>
<section2 topic='HTTP Conditions' anchor='errorstatus-http'> <section2 topic='HTTP Conditions' anchor='errorstatus-http'>
<p>The following HTTP error and status codes are used in particular ways by this protocol (other HTTP error and status codes may be used as appropriate). Upon receiving an HTTP error (400, 403, 404), the HTTP client MUST consider the HTTP session to be null and void.</p> <p>The following HTTP error and status codes are used in particular ways by this protocol (other HTTP error and status codes may be used as appropriate). Upon receiving an HTTP error (400, 403, 404), the HTTP client MUST consider the HTTP session to be null and void.</p>
<p>Note: These are pure HTTP codes as defined in the HTTP specification, and are not to be confused with the HTTP-style error codes traditionally used in Jabber protocols and documented in &xep0086;.</p>
<table caption='HTTP Error and Status Codes'> <table caption='HTTP Error and Status Codes'>
<tr> <tr>
<th>Code</th> <th>Code</th>
@ -864,17 +717,18 @@ Content-Length: 68
<tr> <tr>
<td>403</td> <td>403</td>
<td>Forbidden</td> <td>Forbidden</td>
<td>Inform client that it has broken the session rules (polling too-frequently, too many simultaneous connections).</td> <td>Inform client that it has broken the session rules (polling too frequently, requesting too frequently, too many simultaneous requests).</td>
</tr> </tr>
<tr> <tr>
<td>404</td> <td>404</td>
<td>Not Found</td> <td>Not Found</td>
<td>Inform client that (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) 'key' sequence is invalid.</td> <td>Inform client that (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) 'key' sequence is invalid, (6) Script Syntax is not supported.</td>
</tr> </tr>
</table> </table>
</section2> </section2>
<section2 topic='Terminal Binding Conditions' anchor='errorstatus-terminal'> <section2 topic='Terminal Binding Conditions' anchor='errorstatus-terminal'>
<p>In any response it sends to the client, the connection manager MAY return a fatal error by setting a 'type' attribute of the &lt;body/&gt; element to "terminate". These binding errors imply that the HTTP session is terminated (unless a 'stream' attribute is specified - see <link url="#multi-error">Multiple Stream Error Conditions</link> above). (Note: Many of these conditions correspond to the relevant XMPP stream error conditions specified in <cite>RFC 3920</cite>, but actual XMPP stream error conditions experienced between the connection manager and the server are contained only in the "remote-stream-error" condition as described below.)</p> <p>In any response it sends to the client, the connection manager MAY return a fatal error by setting a 'type' attribute of the &lt;body/&gt; element to "terminate". These binding errors imply that the HTTP session is terminated (unless a 'stream' attribute is specified - see <link url="#multi-error">Multiple Stream Error Conditions</link>).</p>
<p>Note: Although many of these conditions are similar to the XMPP stream error conditions specified in <cite>RFC 3920</cite>, they should not be confused with XMPP stream errors. In cases where this protocol is being used to transport XMPP, any fatal XMPP stream error conditions experienced between the connection manager and the XMPP server SHOULD only be reported using the "remote-stream-error" condition as described below.</p>
<example caption="Remote connection failed error"> <example caption="Remote connection failed error">
<![CDATA[HTTP/1.1 200 OK <![CDATA[HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8 Content-Type: text/xml; charset=utf-8
@ -884,7 +738,7 @@ Content-Length: 68
condition='remote-connection-failed' condition='remote-connection-failed'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
<p>The following values of the 'condition' attribute are defined:</p> <p>The following values of the 'condition' attribute are defined:</p>
<table caption='Binding Error Conditions'> <table caption='Terminal Binding Error Conditions'>
<tr> <tr>
<th>Condition</th> <th>Condition</th>
<th>Purpose</th> <th>Purpose</th>
@ -911,11 +765,11 @@ Content-Length: 68
</tr> </tr>
<tr> <tr>
<td>remote-connection-failed</td> <td>remote-connection-failed</td>
<td>The connection manager was unable to connect to, or unable to connect securely to, or has lost its connection to, the XMPP server.</td> <td>The connection manager was unable to connect to, or unable to connect securely to, or has lost its connection to, the &server;.</td>
</tr> </tr>
<tr> <tr>
<td>remote-stream-error</td> <td>remote-stream-error</td>
<td>Encapsulates an XMPP stream error. The content of the binding is a copy of the content of the &lt;stream:error/&gt; element received from the XMPP server.</td> <td>Encapsulates an error in the protocol being transported.</td>
</tr> </tr>
<tr> <tr>
<td>see-other-uri</td> <td>see-other-uri</td>
@ -927,7 +781,7 @@ Content-Length: 68
</tr> </tr>
<tr> <tr>
<td>undefined-condition</td> <td>undefined-condition</td>
<td>The error is not one of those defined herein; the connection manager SHOULD include application-specific information in the content of the &lt;body/&gt; wrapper element.</td> <td>The error is not one of those defined herein; the connection manager SHOULD include application-specific information in the content of the &lt;body/&gt; wrapper.</td>
</tr> </tr>
</table> </table>
<p>The following is an example of a "see-other-uri" condition:</p> <p>The following is an example of a "see-other-uri" condition:</p>
@ -970,29 +824,87 @@ Content-Length: 68
<body type='error' <body type='error'
xmlns='http://jabber.org/protocol/httpbind'/>]]></example> xmlns='http://jabber.org/protocol/httpbind'/>]]></example>
</section2> </section2>
<section2 topic='XMPP Stanza Conditions' anchor='errorstatus-stanza'> <section2 topic='XML Stanza Conditions' anchor='errorstatus-stanza'>
<p>Application-level error conditions will normally be generated by a third entity (e.g., an IM contact) and routed to the client through the connection manager; therefore they are out of scope for the transport binding defined herein and are described in the appropriate RFC or XEP.</p> <p>Application-level error conditions described in the documentation of the protocol being transported are routed to the client through the connection manager. They are transparent to the connection manager, and therefore out of scope for the transport binding defined herein.</p>
<p>However, it is possible that a connection manager will receive a stanza for delivery to a client even though the client connection is no longer active (e.g., before the connection manager is able to inform a server that the connection has died). In this case, the connection manager would return an error to the server; it is RECOMMENDED that the connection manager proceed as follows, since the situation is similar to that addressed by point #2 of Section 11.1 of <cite>RFC 3921</cite>:</p>
<ol>
<li>If the delivered stanza was &PRESENCE;, silently drop the stanza and do not return an error to the sender.</li>
<li>If the delivered stanza was &IQ;, return a &unavailable; error to the sender.</li>
<li>If the delivered stanza was &MESSAGE;, return a &recipient; error to the sender.</li>
</ol>
<p>When a server receives a &MESSAGE; stanza of type "error" containing a &recipient; condition from a connection manager, it SHOULD store the message for later delivery if offline storage is enabled, otherwise route the error stanza to the sender.</p>
</section2> </section2>
</section1> </section1>
<section1 topic='Implementation Notes' anchor='impl'> <section1 topic='Alternative Script Syntax' anchor='script'>
<p>While it is currently envisioned that implementations of the protocol specified herein will mostly be used as connection managers for XMPP servers, management of connections to non-XMPP implementations is also possible. Furthermore, a connection manager that implements the HTTP Binding will simply act as a pass-through mechanism for XML (not necessarily XML that conforms to the schemas for the 'jabber:client' and 'jabber:server' namespaces as specified in <cite>RFC 3920</cite> and <cite>RFC 3921</cite>). Therefore, the XML schemas defined herein are explicitly not limited to XMPP. Any error handling for non-XMPP elements and attributes is the responsibility of the application using such a connection manager, not the connection manager itself.</p> <section2 topic='Introduction' anchor='script-intro'>
<p>The cross domain security restrictions of some runtime environments permit clients to access pure XML text only if it was received from a specific server (e.g., the hostname a Web client was downloaded from). Astonishingly the same environments typically permit clients to receive and execute scripts from any server! <note>This security hole is unlikely to be closed by browser vendors since it facilitates online advertising.</note> The <link url="#security">Security Considerations</link> section below describes the significant risks of deploying Script Syntax.</p>
<p>To enable domain-restricted clients to use BOSH with any connection manager, this section proposes an <em>optional</em> alternative to the standard "BOSH Pure Syntax" seen in the other sections of this document. The "BOSH Script Syntax" defined here essentially inserts each &lt;body/&gt; element sent by the client into an HTTP GET header instead of into the body of a POST request. Each &lt;body/&gt; element sent by the connection manager is wrapped inside an &ECMAScript; string and function call. No changes to the &lt;body/&gt; element or to any other aspects of the protocol are required.</p>
<p>If, and only if, a client is <em>unable</em> to use the Pure Syntax, then it MAY send a session request to a BOSH connection manager using Script Syntax instead. If the connection manager supports Script Syntax then it MUST send its <link url="#session-create">Session Creation Response</link> using Script Syntax, and all subsequent client requests and connection manager responses within the session MUST be sent using Script Syntax. If the connection manager does not support the "BOSH Script" syntax then it SHOULD return an HTTP 404 (Not Found) error in response to the client's session request:</p>
<example caption="Script Syntax not supported error">
<![CDATA[HTTP/1.1 404 Not Found
Content-Length: 0]]></example>
</section2>
<section2 topic='Changes to the Request Syntax' anchor='script-request'>
<p>Clients MUST make the following changes to convert their requests to Script Syntax:</p>
<ol>
<li><p>Certain octets within the UTF-8 encoded &lt;body/&gt; element SHOULD be replaced according to the rules for escaping octets within URIs defined by &rfc3986;. Therefore all octets except those representing 7-bit alphanumeric characters or the characters -._~!$&amp;'()*+,;=:@/? should be substituted with a character triplet, consisting of the percent character "%" followed by the two hexadecimal digits that represent the value of the octet.</p></li>
<li><p>A '?' character and the URI-encoded &lt;body/&gt; element MUST be appended to the URI at which the connection manager is operating within its server.</p></li>
<li><p>The resulting URI MUST be sent to the connection manager within an HTTP GET request.</p></li>
</ol>
<example caption="Requesting an HTTP session in Script Syntax">
<![CDATA[GET /webclient?%3Cbody%20content='text/xml;%20charset=utf-8'%20hold='1'%20rid='1573741820'%20to='jabber.org'%20route='xmpp:jabber.org:9999'%20secure='true'%20ver='1.6'%20wait='60'%20xml:lang='en'%20xmlns='http://jabber.org/protocol/httpbind'/%3E HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Length: 0]]></example>
<example caption="Transmitting stanzas in Script Syntax">
<![CDATA[GET /webclient?%3Cbody%20rid='1249243562'%20sid='SomeSID'%20xmlns='http://jabber.org/protocol/httpbind'%3E%3Cmessage%20to='friend@example.com'%20xmlns='jabber:client'%3E%3Cbody%3EI%20said%20%22Hi!%22%3C/body%3E%3C/message%3E%3C/body%3E HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Length: 0]]></example>
<p>Although <cite>RFC 2616</cite> does not limit the length of HTTP URIs, the runtime environment of the client might restrict the length of the URI that it can include in each GET request. <note>Internet Explorer versions 4.0 thru 7.0 have a maximum <em>path</em> length of 2048 characters and a maximum URL length of 2083 characters. Other popular browsers appear to have no limit.</note> In these cases the client MUST reduce the content of the &lt;body/&gt; element accordingly and send the remaining content in subsequent HTTP GET requests wrapped in new &lt;body/&gt; elements (with incremented 'rid' attributes). This is possible since, unlike Pure Syntax, with Script Syntax the connection manager MUST treat the string of characters between the opening and closing &lt;body&gt; tags of each request as part of an octet stream instead of as a set of complete XML stanzas. The content of any one &lt;body/&gt; element MUST NOT be parsed in isolation from the rest of the stream.</p>
</section2>
<section2 topic='Changes to the Response Syntax' anchor='script-response'>
<p>Connection managers MUST make the following changes to convert their responses to Script Syntax:</p>
<ol>
<li><p>Certain characters within the &lt;body/&gt; element MUST be replaced according to the rules for escaping characters within strings defined by <cite>ECMAScript</cite>. The necessary substitutions are summarised in the table below.</p>
<table caption='Character Substitutions'>
<tr><th>Character</th><th>Unicode Code Point Value</th><th>Escape sequence</th></tr>
<tr><td>"</td><td>U+0022</td><td>\"</td></tr>
<tr><td>Line Feed (New Line)</td><td>U+000A</td><td>\n</td></tr>
<tr><td>Carriage Return</td><td>U+000D</td><td>\r</td></tr>
<tr><td>Line Separator</td><td>U+2028</td><td>\u2028</td></tr>
<tr><td>Paragraph Separator</td><td>U+2029</td><td>\u2029</td></tr>
<tr><td>\</td><td>U+005C</td><td>\\</td></tr>
</table>
<p>Each Unicode format-control character (i.e., the characters in category "Cf" in the Unicode Character Database, e.g., LEFT-TO-RIGHT MARK or RIGHT-TO-LEFT MARK) MUST also be substituted by its Unicode escape sequence (e.g. \u200e or \u200f).</p></li>
<li>The following eight characters MUST be prepended to the &lt;body/&gt; element: <code>_BOSH_("</code></li>
<li>The following two characters MUST be appended to the &lt;body/&gt; element: <code>")</code></li>
<li>If the client request does not possess a 'content' attribute, then the HTTP Content-Type header of responses MUST be either "text/javascript; charset=utf-8" or "application/x-javascript; charset=utf-8".</li>
</ol>
<example caption="Session creation response in Script Syntax">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8
Content-Length: 233
_BOSH_("<body wait='60' inactivity='30' polling='5' requests='2' hold='1' accept='deflate,gzip' maxpause='120' sid='SomeSID' charsets='ISO_8859-1 ISO-2022-JP' ver='1.6' from='jabber.org' secure='true' xmlns='http://jabber.org/protocol/httpbind'/>")]]></example>
<example caption="Receiving stanzas in Script Syntax">
<![CDATA[HTTP/1.1 200 OK
Content-Type: text/javascript; charset=utf-8
Content-Length: 212
_BOSH_("<body rid='1249243562' sid='SomeSID' xmlns='http://jabber.org/protocol/httpbind'>\n<message to='contact@example.com' xmlns='jabber:client'>\n<body>I said \"Hi!\"</body>\n</message>\n</body>")]]></example>
<p>Note: As with Pure Syntax, each &lt;body/&gt; element sent to the client MUST encapsulate zero or more complete XML stanzas.</p>
</section2>
</section1> </section1>
<section1 topic='Security Considerations' anchor='security'> <section1 topic='Security Considerations' anchor='security'>
<section2 topic='Encryption' anchor='security-crypt'>
<p>All communications SHOULD occur over encrypted HTTP connections. Negotiation of encryption between the client and the connection manager SHOULD occur at the transport layer or the HTTP layer, not the application layer; such negotiation SHOULD follow the HTTP/SSL protocol defined in &ssl;, it MAY follow the HTTP/TLS protocol defined in &rfc2818; or the TLS Within HTTP protocol defined in &rfc2817;.</p> <p>All communications SHOULD occur over encrypted HTTP connections. Negotiation of encryption between the client and the connection manager SHOULD occur at the transport layer or the HTTP layer, not the application layer; such negotiation SHOULD follow the HTTP/SSL protocol defined in &ssl;, it MAY follow the HTTP/TLS protocol defined in &rfc2818; or the TLS Within HTTP protocol defined in &rfc2817;.</p>
<p>If the HTTP connection used to send the initial session request is encrypted, then all the other connections used within the session SHOULD also be encrypted. Furthermore, if authentication certificates are exchanged when establishing the encrypted connection that is used to send the initial session request, then the client and/or connection manager SHOULD ensure that the same authentication certificates are employed for all subsequent connections used by the session. Once such a 'secure session' has been established:</p> <p>If the HTTP connection used to send the initial session request is encrypted, then all the other HTTP connections used within the session MUST also be encrypted. Furthermore, if authentication certificates are exchanged when establishing the encrypted connection that is used to send the initial session request, then the client and/or connection manager SHOULD ensure that the same authentication certificates are employed for all subsequent connections used by the session. Once such a 'secure session' has been established:</p>
<ul> <ul>
<li>If the connection manager refuses to establish an encrypted connection or offers a different certificate, then the client SHOULD close the connection and terminate the session without sending any more requests.</li> <li>If the connection manager refuses to establish an encrypted connection or offers a different certificate, then the client SHOULD close the connection and terminate the session without sending any more requests.</li>
<li>If the client sends a wrapper element that is part of a 'secure session' over a connection that either is not encrypted or uses a different certificate then the connection manager SHOULD simply close the connection. The connection manager SHOULD NOT terminate the session since that would facilitate denial of service attacks.</li> <li>If the client sends a wrapper element that is part of a 'secure session' over a connection that either is not encrypted or uses a different certificate then the connection manager SHOULD simply close the connection. The connection manager SHOULD NOT terminate the session since that would facilitate denial of service attacks.</li>
</ul> </ul>
<p>In cases where the connection manager acts as a 'translating proxy' independent of the &server;, it creates another security vulnerability in addition to those on the &server;s. It is RECOMMENDED that clients ensure the security of stanzas sent through the connection manager (and &server;s) in both directions by encrypting them end-to-end (e.g., by establishing &xep0116;).</p>
</section2>
<section2 topic='Unpredictable SID and RID' anchor='security-sidrid'>
<p>The session identifier (SID) and initial request identifier (RID) are security-critical and therefore MUST be both unpredictable and nonrepeating (see &rfc1750; for recommendations regarding randomness of SIDs and initial RIDs for security purposes).</p> <p>The session identifier (SID) and initial request identifier (RID) are security-critical and therefore MUST be both unpredictable and nonrepeating (see &rfc1750; for recommendations regarding randomness of SIDs and initial RIDs for security purposes).</p>
<p>In cases where the connection manager acts as a 'proxy' independent of the XMPP server, it creates another security vulnerability in addition to those on the XMPP servers. It is RECOMMENDED that clients ensure the security of stanzas sent through the connection manager (and XMPP servers) in both directions by encrypting them end-to-end (e.g., by establishing &xep0116;).</p> </section2>
<section2 topic='Script Syntax' anchor='security-script'>
<p>The alternative Script Syntax returns code for the client to execute. This code is typically executed immediately without any validation and with the same rights as the code of the client itself. This vulnerability could be exploited to steal passwords and private keys, or to fabricate messages sent from and received by the client, or to forward or modify priviledged information on the servers to which the client has access, or to interfere with any aspect of the client's functionality - limited only by the extent of the runtime environment ("sandbox"), by the extent that users may be tricked into doing things outside that environment, and by the attacker's fertile imagination. Therefore, although the client could use Script Syntax with any connection manager on the network, in practice it MUST take care to employ it only with connection managers that the client's user trusts (as much as the server from which the client was downloaded). To prevent a-man-in-the-middle from manipulating the code clients SHOULD only use Script Syntax over encrypted connections (see above). If the client was downloaded over an encrypted connection then it MUST NOT use Script Syntax over connections that are not encrypted.</p>
</section2>
</section1> </section1>
<section1 topic='IANA Considerations' anchor='iana'> <section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p> <p>This document requires no interaction with &IANA;.</p>
@ -1069,10 +981,13 @@ Content-Length: 68
</xs:simpleType> </xs:simpleType>
</xs:attribute> </xs:attribute>
<xs:attribute name='content' type='xs:string' use='optional'/> <xs:attribute name='content' type='xs:string' use='optional'/>
<xs:attribute name='from' type='xs:string' use='optional'/>
<xs:attribute name='hold' type='xs:byte' use='optional'/> <xs:attribute name='hold' type='xs:byte' use='optional'/>
<xs:attribute name='inactivity' type='xs:short' use='optional'/> <xs:attribute name='inactivity' type='xs:short' use='optional'/>
<xs:attribute name='key' type='xs:string' use='optional'/> <xs:attribute name='key' type='xs:string' use='optional'/>
<xs:attribute name='maxpause' type='xs:short' use='optional'/>
<xs:attribute name='newkey' type='xs:string' use='optional'/> <xs:attribute name='newkey' type='xs:string' use='optional'/>
<xs:attribute name='pause' type='xs:short' use='optional'/>
<xs:attribute name='polling' type='xs:short' use='optional'/> <xs:attribute name='polling' type='xs:short' use='optional'/>
<xs:attribute name='requests' type='xs:byte' use='optional'/> <xs:attribute name='requests' type='xs:byte' use='optional'/>
<xs:attribute name='rid' type='xs:positiveInteger' use='optional'/> <xs:attribute name='rid' type='xs:positiveInteger' use='optional'/>
@ -1089,6 +1004,7 @@ Content-Length: 68
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:attribute> </xs:attribute>
<xs:attribute name='ver' type='xs:string' use='optional'/>
<xs:attribute name='wait' type='xs:short' use='optional'/> <xs:attribute name='wait' type='xs:short' use='optional'/>
<xs:attribute name='xml:lang' type='xs:string' use='optional'/> <xs:attribute name='xml:lang' type='xs:string' use='optional'/>
<xs:anyAttribute namespace='##other' processContents='lax'/> <xs:anyAttribute namespace='##other' processContents='lax'/>