No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xep-0025.xml 15KB

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <!DOCTYPE xep SYSTEM 'xep.dtd' [
  3. <!ENTITY % ents SYSTEM 'xep.ent'>
  4. %ents;
  5. ]>
  6. <?xml-stylesheet type='text/xsl' href='xep.xsl'?>
  7. <xep>
  8. <header>
  9. <title>Jabber HTTP Polling</title>
  10. <abstract>This document defines an XMPP protocol extension that enables access to a Jabber server from behind firewalls which do not allow outgoing sockets on port 5222, via HTTP requests.</abstract>
  12. <number>0025</number>
  13. <status>Obsolete</status>
  14. <type>Historical</type>
  15. <sig>Standards</sig>
  16. <dependencies>
  17. <spec>XMPP Core</spec>
  18. </dependencies>
  19. <supersedes/>
  20. <supersededby>
  21. <spec>XEP-0124</spec>
  22. </supersededby>
  23. <shortname>httppoll</shortname>
  24. &hildjj;
  25. <author>
  26. <firstname>Craig</firstname>
  27. <surname>Kaes</surname>
  28. <email></email>
  29. <jid></jid>
  30. </author>
  31. <author>
  32. <firstname>David</firstname>
  33. <surname>Waite</surname>
  34. <email></email>
  35. <jid></jid>
  36. </author>
  37. <revision>
  38. <version>1.2</version>
  39. <date>2009-06-03</date>
  40. <initials>psa</initials>
  41. <remark><p>Per a vote of the XMPP Council, changed status to Obsolete.</p></remark>
  42. </revision>
  43. <revision>
  44. <version>1.1</version>
  45. <date>2006-07-26</date>
  46. <initials>psa</initials>
  47. <remark><p>Per a vote of the Jabber Council, changed status to Deprecated.</p></remark>
  48. </revision>
  49. <revision>
  50. <version>1.0</version>
  51. <date>2002-10-11</date>
  52. <initials>psa</initials>
  53. <remark><p>Per a vote of the Jabber Council, advanced status to Active.</p></remark>
  54. </revision>
  55. <revision>
  56. <version>0.2</version>
  57. <date>2002-09-23</date>
  58. <initials>dew</initials>
  59. <remark><p>Changed format to allow socket-equivalent security.</p></remark>
  60. </revision>
  61. <revision>
  62. <version>0.1</version>
  63. <date>2002-03-14</date>
  64. <initials>jjh</initials>
  65. <remark><p>Initial version.</p></remark>
  66. </revision>
  67. </header>
  68. <section1 topic="Introduction">
  69. <p><em>Note Well: This protocol specified in this document has been superseded by the protocol specified in &xep0124;.</em></p>
  70. <p>
  71. This specification documents a method to allow Jabber clients to access Jabber
  72. servers from behind existing firewalls. Although several similar methods
  73. have been proposed, this approach should work through all known firewall
  74. configurations which allow outbound HTTP access.
  75. </p>
  76. </section1>
  77. <section1 topic="Background">
  78. <p>
  79. In general, a firewall is a box that protects a network from outsiders,
  80. by controlling the IP connections that are allowed to pass through the
  81. box. Often, a firewall will also allow access outside only by proxy,
  82. either explicit proxy support or implicit through Network Address
  83. Translation (NAT).
  84. </p>
  85. <p>
  86. In the interest of security, many firewall administrators do not allow
  87. outbound connections to unknown and unused ports. Until Jabber becomes
  88. more widely deployed, port 5222/tcp (for Jabber client connections) will
  89. often be blocked.
  90. </p>
  91. <p>
  92. The best solution for sites that are concerned about security is to run
  93. their own Jabber server, either inside the firewall, or in a DMZ
  94. <note>
  95. DMZ definition at
  96. <link
  97. url=",,sid27_gci213891,00.html">
  99. </link>
  100. </note>
  101. network. However, there are network configuration where an external
  102. Jabber server must still be used and port 5222/tcp outbound cannot be
  103. allowed. In these situations, different methods for connecting to a
  104. Jabber server are required. Several methods exist today for doing this
  105. traversal. Most rely on the fact that a most firewalls are configured to
  106. allow access through port 80/tcp. Although some less-complicated
  107. firewalls will allow any protocol to traverse this port, many will proxy,
  108. filter, and verify requests on this port as HTTP. Because of this, a
  109. normal Jabber connection on port 80/tcp will not suffice.
  110. </p>
  111. <p>
  112. In addition, many firewalls/proxy servers will also not allow or not
  113. honor HTTP Keep-alives (as defined in section of &rfc2068;)
  114. and will consider long-lived socket connections as security issues.
  115. Because of this the traditional Jabber connection model, where one
  116. socket is one stream is one session, will not work reliably.
  117. </p>
  118. <p>
  119. In light of all of the ways that default firewall rules can interfere
  120. with Jabber connectivity, a lowest-common denominator approach was
  121. selected. HTTP is used to send XML as POST requests and receieve pending
  122. XML within the responses. Additional information is prepended in the
  123. request body to ensure an equivalent level of security to TCP/IP sockets.
  124. </p>
  125. </section1>
  126. <section1 topic="Normal data transfer">
  127. <p>
  128. The client makes HTTP requests periodically to the server. Whenever the
  129. client has something to send, that XML is included in the body of the
  130. request. When the server has something to send to the client, it must be
  131. contained in the body of the response.
  132. </p>
  133. <p>
  134. In some browser/platform combinations, sending cookies from the client is
  135. not possible due to design choices and limitations in the
  136. browser. Therefore, a work-around was needed to support clients based on
  137. these application platforms.
  138. </p>
  139. <p>
  140. All requests to the server are HTTP POST requests, with Content-Type:
  141. application/x-www-form-urlencoded. Responses from the server have
  142. Content-Type: text/xml. Both the request and response bodies are UTF-8
  143. encoded text, even if an HTTP header to the contrary exists. All
  144. responses contain a Set-Cookie header with an identifier, which is sent
  145. along with future requests as described below. This identifier cookie
  146. must have a name of 'ID'. The first request to a server always uses 0 as
  147. the identifier. The server must always return a 200 response code,
  148. sending any session errors as specially-formatted identifiers.
  149. </p>
  150. <p>The client sends requests with bodies in the following format:</p>
  151. <code>
  152. identifier ; key [ ; new_key] , [xml_body]
  153. </code>
  154. <p>If the identifier is zero, key indicates an initial key. In this case,
  155. new_key should not be specified, and must be ignored.</p>
  156. <table caption="Request Values">
  157. <tr>
  158. <th>Identifier</th>
  159. <th>Purpose</th>
  160. </tr>
  161. <tr>
  162. <td>identifier</td>
  163. <td>
  164. To uniquely identify the session server-side. This field is only
  165. used to identify the session, and provides no security.
  166. </td>
  167. </tr>
  168. <tr>
  169. <td>key</td>
  170. <td>
  171. To verify this request is from the originator of the session. The
  172. client generates a new key in the manner described below for each
  173. request, which the server then verifies before processing the
  174. request.
  175. </td>
  176. </tr>
  177. <tr>
  178. <td>new_key</td>
  179. <td>
  180. The key algorithm can exhaust valid keys in a sequence, which
  181. requires a new key sequence to be used in order to continue the
  182. session. The new key is sent along with the last used key in the
  183. old sequence.
  184. </td>
  185. </tr>
  186. <tr>
  187. <td>xml_body</td>
  188. <td>
  189. The body of text to send. Since a POST must be sent in order for
  190. the server to respond with recent messages, a client may send
  191. a request without an xml_body in order to just retrieve new
  192. incoming packets. This is not required to be a full XML document or
  193. XML fragment, it does not need to start or end on element boundaries.
  194. </td>
  195. </tr>
  196. </table>
  197. <p>
  198. The identifier is everything before the first semicolon, and must consist
  199. of the characters [A-Za-z0-9:-]. The identifier returned from the first
  200. request is the identifier for the session. Any new identifier that ends
  201. in ':0' indicates an error, with the entire identifier indicating the
  202. specific error condition. Any new identifier that does not end in ':0' is
  203. a server programming error, the client should discontinue the
  204. session. For new sessions, the client identifier is considered to be 0.
  205. </p>
  206. <section2 topic="Error conditions">
  207. <p>
  208. Any identifier that ends in ':0' indicates an error. Any previous
  209. identifier associated with this session is no longer valid.
  210. </p>
  211. <section3 topic="Unknown Error">
  212. <p>
  213. Server returns ID=0:0. The response body can contain a textual error
  214. message.
  215. </p>
  216. </section3>
  217. <section3 topic="Server Error">
  218. <p>Server returns ID=-1:0</p>
  219. </section3>
  220. <section3 topic="Bad Request">
  221. <p>Server returns ID=-2:0</p>
  222. </section3>
  223. <section3 topic="Key Sequence Error">
  224. <p>Server returns ID=-3:0</p>
  225. </section3>
  226. </section2>
  227. <p>
  228. The key is a client security feature to allow TCP/IP socket equivalent
  229. security. It does not protect against intermediary attacks, but does
  230. prevent a person who is capable of listening to the HTTP traffic from
  231. sending messages and receiving incoming traffic from another machine.
  232. </p>
  233. <p>The key algorithm should be familiar with those with knowledge of Jabber zero-knowledge authentication.</p>
  234. <code>
  235. K(n, seed) = Base64Encode(SHA1(K(n - 1, seed))), for n &gt; 0
  236. K(0, seed) = seed, which is client-determined
  237. </code>
  238. <p>Note: Base64 encoding is defined in &rfc3548;. SHA1 is defined in &rfc3174;.</p>
  239. <p>
  240. No framing is implied by a single request or reply. A single request can
  241. have no content sent, in which case the body contains only the identifier
  242. followed by a comma. A reply may have no content to send, in which case
  243. the body is empty. Zero or more XMPP packets may be sent in a single
  244. request or reply, including partial XMPP packets.
  245. </p>
  246. <p>
  247. The absense of a long-lived connection requires the server to consider
  248. client traffic as a heartbeat to keep the session alive. If a
  249. server-configurable period of time passes without a successful POST
  250. request sent by the client, the server must end the client session. Any
  251. client requests using the identifier associated with that now dead
  252. session must return an error of '0:0'.
  253. </p>
  254. <p>
  255. The maximum period of time to keep a client session active without an
  256. incoming POST request is not defined, but five minutes is the recommended
  257. minimum. The maximum period of time recommended for clients between
  258. requests is two minutes; if the client has not sent any XML out for two
  259. minutes, a request without an XML body should be sent. If a client is
  260. disconnecting from the server, a closing &lt;stream:stream&gt; must be
  261. sent to end the session. Failure to do this may have the client continue
  262. to be represented to other users as available.
  263. </p>
  264. <p>
  265. If the server disconnects the user do to a session timeout, the server
  266. MUST bounce pending IQ requests and either bounce or store offline
  267. incoming messages.
  268. </p>
  269. </section1>
  270. <section1 topic="Usage">
  271. <p>The following is the sequence used for client communication:</p>
  272. <ol>
  273. <li>
  274. The client generates some initial K(0, seed) and runs the algorithm
  275. above 'n' times to determine the initial key sent to the server,
  276. K(n, seed)
  277. </li>
  278. <li>
  279. The client sends the request to the server to start the stream,
  280. including an identifier with a value of zero and K(n, seed)
  281. </li>
  282. <li>
  283. The server responds with the session identifier in the headers
  284. (within the Set-Cookie field).
  285. </li>
  286. <li>
  287. For each further request done by the client, the identifier from the
  288. server and K(n - 1, seed) are sent along.
  289. </li>
  290. <li>
  291. The server verifies the incoming value by generating
  292. K(1, incoming_value), and verifying that value against the value sent
  293. along with the last client request. If the values do not match, the
  294. request should be ignored or logged, with an error code being
  295. returned of -3:0. The request must not be processed, and must not
  296. extend the session keepalive.
  297. </li>
  298. <li>
  299. The client may send a new key K(m, seed') at any point, but should
  300. do this for n &gt; 0 and must do this for n = 0. If K(0, seed) is
  301. sent without a new key, the client will not be able to continue the
  302. session.
  303. </li>
  304. </ol>
  305. <example caption="Initial request (without keys)">
  306. <![CDATA[POST /wc12/webclient HTTP/1.1
  307. Content-Type: application/x-www-form-urlencoded
  308. Host:
  309. 0,<stream:stream to=""
  310. xmlns="jabber:client"
  311. xmlns:stream="">]]>
  312. </example>
  313. <example caption="Initial response">
  314. <![CDATA[Date: Fri, 15 Mar 2002 20:30:30 GMT
  315. Server: Apache/1.3.20
  316. Set-Cookie: ID=7776:2054; path=/webclient/; expires=-1
  317. Content-Type: text/xml
  318. <?xml version='1.0'?>
  319. <stream:stream xmlns:stream=''
  320. id='3C9258BB'
  321. xmlns='jabber:client' from=''>]]>
  322. </example>
  323. <example caption="Next request (without keys)">
  324. <![CDATA[POST /wc12/webclient HTTP/1.1
  325. Content-Type: application/x-www-form-urlencoded
  326. Host:
  327. 7776:2054,<iq type="get" id="WEBCLIENT3">
  328. <query xmlns="jabber:iq:auth">
  329. <username>hildjj</username>
  330. </query>
  331. </iq>]]>
  332. </example>
  333. <example caption='key sequence'>
  334. K(0, "foo") = "foo"
  335. K(1, "foo") = "C+7Hteo/D9vJXQ3UfzxbwnXaijM="
  336. K(2, "foo") = "6UU8CDmH3O4aHFmCqSORCn721+M="
  337. K(3, "foo") = "vFFYSOhGyaGUgLrldtMBX7x91Wc="
  338. K(4, "foo") = "ZaDxCilBVTHS9dJfbBo1NsC2b+8="
  339. K(5, "foo") = "moPFsvHytDGiJQOjp186AMXAeP0="
  340. K(6, "foo") = "VvxEk07IFy6hUmG/PPBlTLE2fiA="
  341. </example>
  342. <example caption="Initial request (with keys)">
  343. <![CDATA[POST /wc12/webclient HTTP/1.1
  344. Content-Type: application/x-www-form-urlencoded
  345. Host:
  346. 0;VvxEk07IFy6hUmG/PPBlTLE2fiA=,<stream:stream to=""
  347. xmlns="jabber:client"
  348. xmlns:stream="">]]>
  349. </example>
  350. <example caption="Next request (with keys)">
  351. <![CDATA[POST /wc12/webclient HTTP/1.1
  352. Content-Type: application/x-www-form-urlencoded
  353. Host:
  354. 7776:2054;moPFsvHytDGiJQOjp186AMXAeP0=,<iq type="get" id="WEBCLIENT3">
  355. <query xmlns="jabber:iq:auth">
  356. <username>hildjj</username>
  357. </query>
  358. </iq>]]>
  359. </example>
  360. <example caption='Changing key'>
  361. <![CDATA[POST /wc12/webclient HTTP/1.1
  362. Content-Type: application/x-www-form-urlencoded
  363. Host:
  364. 7776:2054;C+7Hteo/D9vJXQ3UfzxbwnXaijM=;Tr697Eff02+32FZp38Xaq2+3Bv4=,<presence/>]]>
  365. </example>
  366. </section1>
  367. <section1 topic="Known issues">
  368. <ul>
  369. <li>This method works over HTTPS, which is good from the standpoint of functionality, but bad in the sense that a massive amount of hardware would be needed to support reasonable polling intervals for non-trivial numbers of clients.</li>
  370. </ul>
  371. </section1>
  372. </xep>