mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-17 14:55:05 -05:00
460 lines
16 KiB
XML
460 lines
16 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [
|
|
<!ENTITY % ents SYSTEM 'xep.ent'>
|
|
<!ENTITY MOVED "<moved/>">
|
|
%ents;
|
|
]>
|
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
|
|
<xep>
|
|
<header>
|
|
<title>Moved</title>
|
|
<abstract>This document defines an XMPP protocol extension that enables a user to inform its contacts about a change in JID.</abstract>
|
|
&LEGALNOTICE;
|
|
<number>xxxx</number>
|
|
<status>ProtoXEP</status>
|
|
<type>Standards Track</type>
|
|
<sig>Standards</sig>
|
|
<approver>Council</approver>
|
|
<dependencies>
|
|
<spec>XMPP Core</spec>
|
|
</dependencies>
|
|
<supersedes>
|
|
</supersedes>
|
|
<supersededby/>
|
|
<shortname>moved</shortname>
|
|
<author>
|
|
<firstname>Tory</firstname>
|
|
<surname>Patnoe</surname>
|
|
<email>tpatnoe@cisco.com</email>
|
|
<jid>tpatnoe@cisco.com</jid>
|
|
</author>
|
|
<revision>
|
|
<version>0.0.7</version>
|
|
<date>2010-06-09</date>
|
|
<initials>tp</initials>
|
|
<remark>
|
|
<p>Modified syntax to use 'old' and 'new' attributes.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.6</version>
|
|
<date>2010-06-07</date>
|
|
<initials>tp</initials>
|
|
<remark>
|
|
<ul>
|
|
<li>Update ordering so that it recommends sending the unsubscribe/unsubscribed, before, sending the subscribe</li>
|
|
<li>Add section documenting what happens when a contact is offline when the unsubscribe/unsubscribed/subscribe stanzas are sent.</li>
|
|
<li>Added an example about a hacker sending an unsolicited subscribe by guessing a roster entry.</li>
|
|
</ul>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.5</version>
|
|
<date>2010-06-02</date>
|
|
<initials>tp</initials>
|
|
<remark>
|
|
<p>Added one-way subscription section</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.4</version>
|
|
<date>2010-05-30</date>
|
|
<initials>tp</initials>
|
|
<remark>
|
|
<p>Change MUST NOT to SHOULD NOT for clients auto-subscribing back; differentiate between inbound and outbound subscriptions.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.3</version>
|
|
<date>2010-06-02</date>
|
|
<initials>tp</initials>
|
|
<remark><p>Add one-way subscription comments.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.2</version>
|
|
<date>2010-05-25</date>
|
|
<initials>tp</initials>
|
|
<remark><p>Minor tweaks.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.1</version>
|
|
<date>2010-05-22</date>
|
|
<initials>tp</initials>
|
|
<remark><p>First draft.</p></remark>
|
|
</revision>
|
|
</header>
|
|
<section1 topic='Introduction' anchor='intro'>
|
|
<p>There are a variety of reasons why a user may wish to change
|
|
their JID. For example, a surname change because of marriage or simply
|
|
an easier JID to remember.
|
|
</p>
|
|
|
|
<p>This XEP defines an approach for communicating that your JID has
|
|
moved to a new JID, extending the existing subscription protocol documented
|
|
in &rfc3921;. The steps outlined here may be done either through a client
|
|
or automated by a server.
|
|
</p>
|
|
</section1>
|
|
|
|
<section1 topic='Requirements' anchor='reqs'>
|
|
<ul>
|
|
<li>The methods described here maintain compatibility with &rfc3920; and
|
|
&rfc3921;</li>
|
|
</ul>
|
|
</section1>
|
|
|
|
<section1 topic='The Move'>
|
|
<p>In this scenario user@example.com moves to user2@example2.com.
|
|
Both the user@example.com and user2@example2.com accounts have been
|
|
created and still exist. The roster for user@example2.com is empty
|
|
and the user wants to populate it with their entries from
|
|
user@example.com.</p>
|
|
|
|
<dl>
|
|
<dt><strong>original JID</strong></dt>
|
|
<dd>user@example.com</dd>
|
|
<dt><strong>new JID</strong></dt>
|
|
<dd>user2@example2.com</dd>
|
|
</dl>
|
|
|
|
<section2 topic='Unsubscribing the original JID from outbound subscriptions'
|
|
anchor='unsubscribe'>
|
|
<p>Because the original JID is no longer going to be used, the user SHOULD
|
|
unsubscribe from all the outbound subscriptions user@example.com had.
|
|
These can be identified as those in the 'to' or 'ask' states as
|
|
defined in the 'jabber:iq:roster' protocol in &rfc3921;.</p>
|
|
|
|
<p>To unsubscribe all outbound subscriptions for the original JID send an
|
|
unsubscribe &PRESENCE; stanza to all the old contacts with a &MOVED;
|
|
element containing the new JID.</p>
|
|
|
|
<p>There is the potential for other users to send a malicious unsubscribe
|
|
containing a spoofed &MOVED; JID. Therefore, clients SHOULD NOT
|
|
automatically subscribe to the JID contained in the &MOVED; stanza when
|
|
receiving a subscribe &PRESENCE; stanza without displaying the &MOVED;
|
|
JID to the user. See the Security Considerations section for
|
|
details.</p>
|
|
|
|
<example caption='Client unsubscribes outbound subscriptions from original JID'>
|
|
<![CDATA[
|
|
<presence from='user@example.com' to='contact@example.com' type='unsubscribe'>
|
|
<status>I've changed JIDs from user@example.com to user2@example2.com</status>
|
|
<moved xmlns='urn:xmpp:moved:0' new='user2@example2.com'/>
|
|
</presence>
|
|
]]>
|
|
</example>
|
|
|
|
</section2>
|
|
|
|
<section2 topic='Unsubscribing the original JID from inbound subscriptions'
|
|
anchor='unsubscribed'>
|
|
<p>Because the original JID is no longer going to be used, the user SHOULD
|
|
unsubscribe from all contacts the user@example.com had an inbound
|
|
subscription from. These can be identified as those in the 'from'
|
|
subscription state as defined in in the 'jabber:iq:roster' protocol
|
|
in &rfc3921;.</p>
|
|
|
|
<p>To unsubscribe all inbound subscriptions send an unsubscribed
|
|
&PRESENCE; stanza to all the old contacts with a &MOVED; element
|
|
containing the new JID.</p>
|
|
|
|
<p>There is the potential for other users to send a malicious unsubscribed
|
|
containing a spoofed &MOVED; JID. Therefore, clients SHOULD NOT
|
|
automatically subscribe to the JID contained in the &MOVED; stanza
|
|
without displaying the &MOVED; JID to the user. See the Security
|
|
Considerations section for details.</p>
|
|
|
|
<example caption='Client unsubscribes inbound subscriptions from original JID'>
|
|
<![CDATA[
|
|
<presence from='user@example.com' to='contact@example.com' type='unsubscribed'>
|
|
<status>I've changed JIDs from user@example.com to user2@example2.com</status>
|
|
<moved xmlns='urn:xmpp:moved:0' new='user2@example2.com'/>
|
|
</presence>
|
|
]]>
|
|
</example>
|
|
|
|
</section2>
|
|
<section2 topic='Subscribing the new JID to all your existing contacts'
|
|
anchor='subscribe'>
|
|
|
|
<p>Once the new JID has been created on a server it is possible for the
|
|
new JID to subscribe to the contacts they had on the original JID's
|
|
roster. This is done by sending a new subscription request with a
|
|
&MOVED; element containing the new JID.
|
|
</p>
|
|
|
|
<p>The new subscription MUST come from the new JID's server.</p>
|
|
|
|
<p>There is the potential for other users to send a malicious subscribe
|
|
request and spoof the content of the &MOVED; element identifying an
|
|
original JID. Therefore, clients SHOULD NOT automatically unsubscribe
|
|
an existing roster entry if is listed as the target in the &MOVED;
|
|
element when a subscribe is received. See the Security
|
|
Consideration section for details.</p>
|
|
|
|
<p>Clients accepting the moved subscription SHOULD indicate to the
|
|
user that that this subscription request was the result of a move
|
|
operation and because of potential malicious behavior SHOULD NOT
|
|
auto-accept the subscription without displaying the &MOVED; JID to the
|
|
user.</p>
|
|
|
|
<example caption='Client requests subscription from new JID'>
|
|
<![CDATA[
|
|
<presence from='user2@example2.com' to='contact@example.com' type='subscribe'>
|
|
<status>I've changed JIDs from user@example.com to user2@example2.com</status>
|
|
<moved xmlns='urn:xmpp:moved:0' old='user@example.com'/>
|
|
</presence>
|
|
]]>
|
|
</example>
|
|
|
|
</section2>
|
|
|
|
<section2 topic='Contacts Offline at the Time the Rename Occurs'
|
|
anchor='offline'>
|
|
<p>&rfc3920bis; clarifies that an incoming subscribe &PRESENCE; stanza
|
|
MUST be preserved by the server and &PRESENCE; stanzas of type
|
|
unsubscribe and unsubscribed are not preserved on the server.
|
|
Therefore, for a contact who is offline, their servers MAY have
|
|
automatically removed the original roster entry when seeing the
|
|
unsubscribe and unsubscribed stanzas. At the time of writing this XEP,
|
|
NOT saving and forwarding the presence stanzas will be the default
|
|
behavior of most servers.
|
|
</p>
|
|
|
|
<p>What this means is that a contact coming online after the rename
|
|
outlined above MAY only see the &PRESENCE; of type 'subscribe' with
|
|
the &MOVED; element. Clients should be aware of this behavior.
|
|
</p>
|
|
</section2>
|
|
|
|
<section2 topic='Presence Ordering' anchor='ordering'>
|
|
<p>In following the principle of least surprise, it is considered good
|
|
practice to send the subscribe stanza after the unsubscribe and unsubscribed
|
|
stanzas.
|
|
</p>
|
|
</section2>
|
|
|
|
<section2 topic='Preservation of Groups' anchor='grouping'>
|
|
<p>One of the side effects of this scheme is the potential for a contact
|
|
to lose the groups to which it had organized the original JID. Clients
|
|
aware of the &MOVED; element can mitigate this with the following rules.
|
|
</p>
|
|
|
|
<ul>
|
|
<li>If the contacts client receives an unsubscribed with a &MOVED;
|
|
element, remove the subscription but initiate a roster push for the
|
|
original JID with the subscription set to 'none'. When the new
|
|
subscription is received the new JID MAY be placed into the roster
|
|
in the same groups as the original JID and the original JID can then be
|
|
removed from the roster.
|
|
</li>
|
|
|
|
<li>If a subscribe is received with a &MOVED; element, the client MAY
|
|
automatically place the new JID into the same groups as the original JID.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>As discussed in 'Contacts Offline at the Time the Rename Occurs', a
|
|
server MAY automatically handle the unsubscribe and unsubscribed stanzas.
|
|
If this occurs it will be impossible to preserve the original groups.
|
|
</p>
|
|
|
|
</section2>
|
|
|
|
<section2 topic='One-way subcriptions and full roster state' anchor='one-way'>
|
|
<section3 topic='One-way Inbound subscription' anchor='from_subs'>
|
|
<p>If the original JID, user@example.com, had only an inbound subscription
|
|
(from or pending in), then the contact will only receive an
|
|
unsubscribed &PRESENCE; stanza. The contact's client, knowing the
|
|
state of the subscription (which is 'to' or 'none' with 'ask='subscribe'
|
|
from the contact's perspective), at that point MAY choose to prompt the
|
|
user to subscribe to the new JID listed in the &MOVED; element.</p>
|
|
|
|
<p>Because of the ability to spoof the &MOVED; element, the client SHOULD
|
|
NOT automatically subscribe to the &MOVED; element target, but SHOULD
|
|
present the new JID to the contact before sending out a subscription
|
|
request.</p>
|
|
</section3>
|
|
|
|
<section3 topic='One-way Outbound subscription' anchor='to_subs'>
|
|
<p>If the original JID, user@example.com, had only an outbound
|
|
subscription (to or ask), then the contact SHOULD only receive an
|
|
unsubscribe &PRESENCE; stanza. The contact's client, knowing the
|
|
state of the subscription (which is 'from' from the contact's perspective),
|
|
at that point MAY choose to prompt
|
|
the user to subscribe to the new JID listed in the &MOVED; element.</p>
|
|
|
|
<p>Because of the ability to spoof the &MOVED; element, the client SHOULD
|
|
NOT automatically subscribe to the &MOVED; element target</p>.
|
|
</section3>
|
|
|
|
<section3 topic='Roster state and action table' anchor='actions'>
|
|
<table caption="Roster states and actios from the renamed user's perspective">
|
|
<tr>
|
|
<td>Server state</td>
|
|
<td>Client state (jabber:iq:roster)</td>
|
|
<td>Send unsubscribe from original JID</td>
|
|
<td>Send unsubscribed from original JID</td>
|
|
<td>Send subscribe from new JID</td>
|
|
</tr>
|
|
<tr>
|
|
<td>none</td>
|
|
<td>none</td>
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
<tr>
|
|
<td>none + pending out</td>
|
|
<td>none + ask='subscribe'</td>
|
|
<td>yes</td>
|
|
<td></td>
|
|
<td>yes</td>
|
|
</tr>
|
|
<tr>
|
|
<td>none + pending in</td>
|
|
<td>n/a</td>
|
|
<td></td>
|
|
<td>yes - server only</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr>
|
|
<td>none + pending in/out</td>
|
|
<td>none + ask='subscribe'</td>
|
|
<td>yes</td>
|
|
<td>yes - server only</td>
|
|
<td>yes</td>
|
|
</tr>
|
|
<tr>
|
|
<td>to</td>
|
|
<td>to</td>
|
|
<td>yes</td>
|
|
<td></td>
|
|
<td>yes</td>
|
|
</tr>
|
|
<tr>
|
|
<td>to + pending in</td>
|
|
<td>to</td>
|
|
<td>yes</td>
|
|
<td>yes - server only</td>
|
|
<td>yes</td>
|
|
</tr>
|
|
<tr>
|
|
<td>from</td>
|
|
<td>from</td>
|
|
<td></td>
|
|
<td>yes</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr>
|
|
<td>from + pending out</td>
|
|
<td>from/none + ask='subscribe'</td>
|
|
<td>yes</td>
|
|
<td>yes</td>
|
|
<td>yes</td>
|
|
</tr>
|
|
<tr>
|
|
<td>both</td>
|
|
<td>both</td>
|
|
<td>yes</td>
|
|
<td>yes</td>
|
|
<td>yes</td>
|
|
</tr>
|
|
</table>
|
|
</section3>
|
|
</section2>
|
|
</section1>
|
|
|
|
<section1 topic='Security Considerations' anchor='security'>
|
|
<p>It is not intended for servers to strip any &MOVED; elements from
|
|
&PRESENCE; stanzas sent in from a client. This allows clients as well as
|
|
servers to implement these same procedures.</p>
|
|
|
|
<p>In order to prevent other users from maliciously altering contacts
|
|
the client SHOULD NOT automatically subscribe to a &MOVED; JID when it
|
|
receives an unsubscribe and SHOULD NOT automatically unsubscribe to
|
|
a &MOVED; JID when it receives a subscribe.</p>
|
|
|
|
<p>The following illustrates an example malicious attack.</p>
|
|
|
|
<ol>
|
|
<li>userA@example.com subscribes to userB@example.com</li>
|
|
<li>The userB@example.com automatically accepts the subscription from
|
|
userA@example.com. (Automatically done by the client using a simple
|
|
domain trust).</li>
|
|
<li>userA@example.com unsubscribes with the &MOVED; 'new' JID set to
|
|
companyCEO@example.com.</li>
|
|
<li>The previous steps can be repeated and have userB@example.com subscribe
|
|
to a large number of people.</li>
|
|
</ol>
|
|
|
|
<p>A similar attack can be done with a new subscribe request causing users
|
|
by guessing which users are subscribed to a contact.</p>
|
|
|
|
<ol>
|
|
<li>hacker@example.com subscribes to userB@example.com guessing that
|
|
userA@example.com is on userB's roster.
|
|
<![CDATA[
|
|
<presence from='hacker@example.com' to='userB@example.com' type='subscribe'>
|
|
<status>Subscribe to me!</status>
|
|
<moved xmlns='urn:xmpp:moved:0' old='userA@example.com'/>
|
|
</presence>
|
|
]]>
|
|
</li>
|
|
<li>If userB's client automatically accepted the subscription without
|
|
displaying at prompt to userB showing the new JID to be hacker@example.com,
|
|
then the user has no idea that hacker@example.com was just added to
|
|
the roster.
|
|
</li>
|
|
</ol>
|
|
|
|
</section1>
|
|
|
|
<section1 topic='IANA Considerations' anchor='iana'>
|
|
<p>This document requires no interaction with &IANA;.</p>
|
|
</section1>
|
|
<section1 topic='XMPP Registrar Considerations' anchor='reg'>
|
|
<section2 topic='Protocol Namespaces' anchor='registrar-ns'>
|
|
<p>This specification defines the following XML namespace:</p>
|
|
<ul>
|
|
<li>urn:xmpp:moved:0</li>
|
|
</ul>
|
|
<p>Upon advancement of this specification from a status of Experimental
|
|
to a status of Draft, the ®ISTRAR; shall add the foregoing namespace
|
|
to the registry located at &NAMESPACES;, as described in Section 4 of
|
|
&xep0053;.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Protocol Versioning' anchor='registrar-versioning'>
|
|
&NSVER;
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='XML Schema' anchor='schema'>
|
|
<code><![CDATA[
|
|
<?xml version='1.0' encoding='UTF-8'?>
|
|
|
|
<xs:schema
|
|
xmlns:xs='http://www.w3.org/2001/XMLSchema'
|
|
targetNamespace='urn:xmpp:moved:0'
|
|
xmlns='urn:xmpp:moved:0'
|
|
elementFormDefault='qualified'>
|
|
|
|
<xs:element name='moved'>
|
|
<xs:complexType>
|
|
<xs:simpleContent>
|
|
<xs:extension base='xs:string'>
|
|
<xs:attribute name='new' type='xs:string' use='optional'/>
|
|
<xs:attribute name='old' type='xs:string' use='optional'/>
|
|
</xs:extension>
|
|
</xs:simpleContent>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
</xs:schema>
|
|
]]></code>
|
|
</section1>
|
|
<section1 topic='Acknowledgements' anchor='ack'>
|
|
<p>The author wishes to thank Doug Abbink, Mikhail Belov, Peter Saint-Andre, and Peter Sheu for their feedback.</p>
|
|
</section1>
|
|
</xep>
|