mirror of
https://github.com/moparisthebest/xeps
synced 2024-12-24 08:38:53 -05:00
Merge branch 'xep-0283' into premerge
This commit is contained in:
commit
08baaba5b2
676
xep-0283.xml
676
xep-0283.xml
@ -11,7 +11,7 @@
|
||||
<abstract>This document defines an XMPP protocol extension that enables a user to inform its contacts about a change in JID.</abstract>
|
||||
&LEGALNOTICE;
|
||||
<number>0283</number>
|
||||
<status>Deferred</status>
|
||||
<status>Experimental</status>
|
||||
<type>Standards Track</type>
|
||||
<sig>Standards</sig>
|
||||
<approver>Council</approver>
|
||||
@ -22,12 +22,13 @@
|
||||
</supersedes>
|
||||
<supersededby/>
|
||||
<shortname>moved</shortname>
|
||||
<author>
|
||||
<firstname>Tory</firstname>
|
||||
<surname>Patnoe</surname>
|
||||
<email>tpatnoe@cisco.com</email>
|
||||
<jid>tpatnoe@cisco.com</jid>
|
||||
</author>
|
||||
&mwild;
|
||||
<revision>
|
||||
<version>0.2.0</version>
|
||||
<date>2021-07-20</date>
|
||||
<initials>mw</initials>
|
||||
<remark><p>Re-write the flow with a more focused approach.</p></remark>
|
||||
</revision>
|
||||
<revision>
|
||||
<version>0.1.1</version>
|
||||
<date>2018-08-06</date>
|
||||
@ -98,375 +99,384 @@
|
||||
<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>
|
||||
an easier JID to remember. Another common reason is that the provider goes
|
||||
out of service (with a notice).</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 &xmppim;. The steps outlined here may be done either through a client
|
||||
or automated by a server.
|
||||
</p>
|
||||
or automated by a server.</p>
|
||||
</section1>
|
||||
|
||||
<section1 topic='Requirements' anchor='reqs'>
|
||||
<p>This document aims to satisfy the following requirements:</p>
|
||||
<ul>
|
||||
<li>The methods described here maintain compatibility with &xmppcore; and <cite>RFC 6121</cite>.</li>
|
||||
<li>Users should be able to notify their contacts of a change of address.</li>
|
||||
<li>Contacts should be able to verify that such a notification is legitimate, to prevent malicious actors from spoofing notifications.</li>
|
||||
<li>It should be possible for a contact's server to automatically update the contact's roster for seamless migrations.</li>
|
||||
<li>In the absence of a contact's support for this protocol, it should fall back to a simple manual subscription approval.</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 user2@example2.com is empty
|
||||
and the user wants to populate it with their entries from
|
||||
user@example.com.</p>
|
||||
|
||||
<section1 topic='Glossary' anchor='glossary'>
|
||||
<dl>
|
||||
<di>
|
||||
<dt>original JID</dt>
|
||||
<dd>user@example.com</dd>
|
||||
<dt>Moved notification</dt>
|
||||
<dd>An XML <moved/> element sent to a contact to inform them that
|
||||
the user is moving to a new address.
|
||||
</dd>
|
||||
</di>
|
||||
<di>
|
||||
<dt>new JID</dt>
|
||||
<dd>user2@example2.com</dd>
|
||||
<dt>Moved statement</dt>
|
||||
<dd>An XML <moved/> element published by the user on their old
|
||||
account. It is used by contacts to verify that moved notifications
|
||||
are genuine.
|
||||
</dd>
|
||||
</di>
|
||||
</dl>
|
||||
</section1>
|
||||
|
||||
<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 <cite>RFC 6121</cite>.</p>
|
||||
<section1 topic='Use Cases' anchor='usecases'>
|
||||
<p>We start with the situation where the user, let's call them Juliet, has two accounts -
|
||||
her original account <tt>juliet@im.example.net</tt> and a shiny new account on her personal
|
||||
domain, <tt>juliet@capulet.example</tt>.</p>
|
||||
<p>Juliet would like to migrate all her data and contacts to her new account, with minimal
|
||||
disruption.</p>
|
||||
<section2 topic='User publishes moved statement' anchor='publish-statement'>
|
||||
<p>Before notifying contacts of the move, Juliet must connect to her old
|
||||
account and publish a "statement" that the account is no longer in
|
||||
use. This statement includes the address of her new account.
|
||||
</p>
|
||||
<p>The statement should be posted to a PEP node with the name 'urn:xmpp:moved:1'. The
|
||||
payload should be a <moved/> element in the 'urn:xmpp:moved:1' namespace. This
|
||||
element should in turn contain a single <new-jid/> element with the user's new JID
|
||||
as its text content.</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>
|
||||
<example caption='Juliet's client publishes a moved statement on her old account'><![CDATA[
|
||||
<iq from='juliet@im.example.net/VR0sAGae'
|
||||
type='set'
|
||||
id='pub1'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<publish node='urn:xmpp:moved:1'>
|
||||
<item id='current'>
|
||||
<moved xmlns='urn:xmpp:moved:1'>
|
||||
<new-jid>juliet@capulet.example</new-jid>
|
||||
</moved>
|
||||
</item>
|
||||
</publish>
|
||||
</pubsub>
|
||||
</iq>
|
||||
]]></example>
|
||||
</section2>
|
||||
<section2 topic='User notifies contacts of move' anchor='publish-notification'>
|
||||
<p>After publishing a moved statement on her old account, Juliet proceeds
|
||||
to notify her contacts about the move.</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>
|
||||
<p>Juliet connects to her new account, and sends a subscription request to
|
||||
each of her contacts. These subscription requests MUST contain a <moved/>
|
||||
element in the 'urn:xmpp:moved:1' namespace. This element contains a single
|
||||
<old-jid/> element with the old JID as its text content.></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'/>
|
||||
<example caption='Juliet sends a subscription request to Romeo from her new account'><![CDATA[
|
||||
<presence type='subscribe' to='romeo@montague.example' id='sub1'>
|
||||
<moved xmlns='urn:xmpp:moved:1'>
|
||||
<old-jid>juliet@im.example.net</old-jid>
|
||||
</moved>
|
||||
</presence>
|
||||
]]></example>
|
||||
</section2>
|
||||
|
||||
<section2 topic='Contact receives subscription request with moved notification' anchor='receive-notification-client'>
|
||||
<p>Juliet's contact, Romeo, receives the subscription request from Juliet's
|
||||
new JID. At this point Romeo has not verified that the new account
|
||||
actually belongs to Juliet, and MUST perform such verification before
|
||||
acting on the request any differently to usual.</p>
|
||||
|
||||
<p>If the value of <old-jid/> is not in the roster with an approved
|
||||
incoming subscription ('from' or 'both'), the <moved/> element
|
||||
MUST be ignored entirely.</p>
|
||||
|
||||
<p>To verify the request, Romeo makes a request to the JID specified in
|
||||
<old-jid/> (which MUST be a bare JID) to fetch a published move
|
||||
statement.</p>
|
||||
|
||||
<example caption='Romeo requests a moved statement from Juliet's old account'><![CDATA[
|
||||
<iq type='get'
|
||||
from='romeo@capulet.example/laptop'
|
||||
to='juliet@im.example.net'
|
||||
id='83hKgF'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<items node='urn:xmpp:moved:1'>
|
||||
<item id='current'/>
|
||||
</items>
|
||||
</pubsub>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<p>On success, Juliet's server will return the moved statement that Juliet published.</p>
|
||||
|
||||
<example caption='Juliet's old server returns the published moved statement to Romeo'><![CDATA[
|
||||
<iq type='result'
|
||||
from='juliet@im.example.net'
|
||||
to='romeo@capulet.example/laptop'
|
||||
id='83hKgF'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<items node='urn:xmpp:moved:1'>
|
||||
<item id='current'>
|
||||
<moved xmlns='urn:xmpp:moved:1'>
|
||||
<new-jid>juliet@capulet.example</new-jid>
|
||||
</moved>
|
||||
</item>
|
||||
</items>
|
||||
</pubsub>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<p>Romeo MUST now verify that the received subscription request was from
|
||||
the same bare JID contained in the <new-jid/> element in the moved
|
||||
statement. If the JIDs do not match, or if there was an error fetching
|
||||
the moved statement (except for "gone" - see note below), the
|
||||
<moved/> element in the incoming subscription request MUST be
|
||||
ignored entirely.</p>
|
||||
|
||||
<p class="box">
|
||||
<strong>Note:</strong> As a special case, if the attempt to retrieve the
|
||||
moved statement results in an error with the <gone/> condition as
|
||||
defined in RFC 6120, and that <gone/> element contains a valid
|
||||
XMPP URI (e.g. <tt>xmpp:user@example.com</tt>), then the error response
|
||||
MUST be handled equivalent to a <moved/> statement containing a
|
||||
<new-jid/> element with the JID provided in the URI (e.g.
|
||||
<tt>user@example.com</tt>).
|
||||
</p>
|
||||
|
||||
|
||||
<p>Upon successful verification, Romeo's client may present an appropriate
|
||||
user interface, informing about Juliet's change of address, and a prompt
|
||||
to accept the subscription request from the new address. On the user's
|
||||
approval of such a subscription request, the client will typically want
|
||||
to also send a subscription request to the contact's new JID to establish
|
||||
a mutual subscription.</p>
|
||||
|
||||
<p>Due to the potential for races between multiple clients connected to
|
||||
the same account, it is NOT RECOMMENDED for a client to automatically
|
||||
act upon migration notifications, but instead await manual interaction
|
||||
from the user. As with any inbound subscription request it SHOULD pay
|
||||
attention to roster pushes related to the contact, and update the UI
|
||||
appropriately if the new contact address is authorized from another
|
||||
device.</p>
|
||||
</section2>
|
||||
|
||||
<section2 topic='Server-side processing of inbound moved notification' anchor='receive-notification-server'>
|
||||
<p>It is not required for Romeo's server to support this specification.
|
||||
However if Romeo's server does understand this extension, it SHOULD
|
||||
handle the inbound subscription request on behalf of Romeo's clients.
|
||||
This improves the user experience for Romeo, especially when he has
|
||||
multiple devices.</p>
|
||||
|
||||
<p>Broadly the server should follow exactly the same process as a client
|
||||
would. Specifically:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Receive subscription request with 'moved' payload.</li>
|
||||
<li>Verify that the old JID has an approved subscription to the user (i.e. a subscription of 'both' or 'from').</li>
|
||||
<li>Request moved statement from the old account JID.</li>
|
||||
<li>Verify that the new JID in the moved statement matches the 'from' of the subscription request.</li>
|
||||
</ol>
|
||||
|
||||
<example caption='Romeo's server requests a moved statement from Juliet's old account'><![CDATA[
|
||||
<iq type='get'
|
||||
from='romeo@capulet.example'
|
||||
to='juliet@im.example.net'
|
||||
id='83hKgF'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<items node='urn:xmpp:moved:1'>
|
||||
<item id='current'/>
|
||||
</items>
|
||||
</pubsub>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<example caption='Juliet's old server returns the published moved statement to Romeo's server'><![CDATA[
|
||||
<iq type='result'
|
||||
from='juliet@im.example.net'
|
||||
to='romeo@capulet.example/laptop'
|
||||
id='83hKgF'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<items node='urn:xmpp:moved:1'>
|
||||
<item id='current'>
|
||||
<moved xmlns='urn:xmpp:moved:1'>
|
||||
<new-jid>juliet@capulet.example</new-jid>
|
||||
</moved>
|
||||
</item>
|
||||
</items>
|
||||
</pubsub>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<p>If verification fails (e.g. due to a missing or incorrect moved
|
||||
statement), the server MUST ignore the <moved/> element in the
|
||||
subscription request, and process the stanza as a normal subscription
|
||||
request. It MUST NOT strip the <moved/> element before forwarding,
|
||||
even if verification fails.</p>
|
||||
|
||||
<p>Upon successful verification, the server MUST NOT forward the stanza to
|
||||
Romeo's clients, but instead MUST create a roster entry for the new JID
|
||||
with a subscription of 'from' (sending out the appropriate roster push),
|
||||
and then auto-reply to the subscription request with a presence of type
|
||||
'subscribed'.</p>
|
||||
|
||||
<example caption='Romeo's server notifies Romeo about the new roster entry'><![CDATA[
|
||||
<iq id='a78b4q6ha463'
|
||||
to='romeo@montague.example/orchard'
|
||||
type='set'>
|
||||
<query xmlns='jabber:iq:roster'>
|
||||
<item jid='juliet@capulet.example''
|
||||
subscription='from'/>
|
||||
</query>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<p>After authorizing the new JID, the server should revoke the presence
|
||||
subscription of the old account.</p>
|
||||
|
||||
<example caption='Romeo's server notifies Juliet's old account about unsubscription'><![CDATA[
|
||||
<presence to='juliet@im.example.net' type='unsubscribed'/>
|
||||
]]></example>
|
||||
|
||||
<example caption='Romeo's server notifies Romeo's clients about the old roster entry'><![CDATA[
|
||||
<iq id='a78b4q6ha463'
|
||||
to='romeo@montague.example/orchard'
|
||||
type='set'>
|
||||
<query xmlns='jabber:iq:roster'>
|
||||
<item jid='juliet@im.example.net''
|
||||
subscription='to'/>
|
||||
</query>
|
||||
</iq>
|
||||
]]></example>
|
||||
|
||||
<p>Finally, if the old JID was in the user's roster with a subscription of 'both', the
|
||||
server MUST also send a presence of type 'subscribe' to the new JID in
|
||||
order to seek establishment of a mutual subscription.</p>
|
||||
|
||||
<example caption='Romeo's server sends subscription request to Juliet's new JID'><![CDATA[
|
||||
<presence type='subscribe' id='uc51xs63' from='romeo@montague.example' to='juliet@capulet.example'/>
|
||||
]]></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 <cite>RFC 6121</cite>.</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>
|
||||
</section1>
|
||||
|
||||
<section1 topic='Implementation Notes' anchor='impl'>
|
||||
<section2 topic='Lifetime of moved statement' anchor='impl-lifetime'>
|
||||
<p>The moved statement is required for contacts to automatically verify
|
||||
the authenticity of moved notifications. After publishing a moved
|
||||
statement, the user should keep the statement published and the account
|
||||
active for long enough for contacts to switch to the user's new account.</p>
|
||||
<p>It is not necessary to remain connected to the old account during the
|
||||
transition period. However the account must not be deleted, and the
|
||||
server must be available.</p>
|
||||
<p>In the event that the move statement is unpublished, the account is deleted,
|
||||
or the server becomes unavailable, any contacts that have not yet transitioned
|
||||
to the user's new JID will be unable to verify the migration. Those contacts
|
||||
will have to manually approve the subscription from the user's new address.</p>
|
||||
<p>Migration progress of contacts is obervable through subscription revocations to
|
||||
the old account, and subscription approvals to the new account.</p>
|
||||
</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><cite>RFC 6120</cite> 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 topic='Alternative verification methods' anchor='impl-alt-verify'>
|
||||
<p>Future revisions of this document, or alternative documents, may define
|
||||
alternative verification methods. Such methods SHOULD be communicated via
|
||||
child elements of <moved/> in an appropriate namespace. As is usual
|
||||
throughout XMPP, entities MUST ignore unknown child elements of
|
||||
<moved/> in unrecognised namespaces.</p>
|
||||
</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>
|
||||
|
||||
<section2 topic='User considerations' anchor='security-user'>
|
||||
<p>The following are considerations for the user (exemplified by Juliet in this document):</p>
|
||||
<ul>
|
||||
<li>A malicious client or other entity with access to the user's account
|
||||
can perform a migration, potentially against the user's will and/or
|
||||
without their knowledge. Although this is a concern, any malicious
|
||||
actor with access to a user's account can abuse that access in many
|
||||
ways. Servers that support granting restricted access to accounts
|
||||
should consider blocking attempts to publish to the
|
||||
'urn:xmpp:moved:1' PEP node from restricted entities.</li>
|
||||
<li>To avoid leaking the user's new JID to non-contacts, the PEP node
|
||||
containing the moved statement SHOULD be configured to use the
|
||||
"presence" access model (this is the default access model defined
|
||||
by PEP).</li>
|
||||
</ul>
|
||||
</section2>
|
||||
<section2 topic='Contact considerations' anchor='security-contact'>
|
||||
<p>The following are considerations for the contact (exemplified by Romeo in this document), and the contact's server:</p>
|
||||
<ul>
|
||||
<li>A presence subscription with a <moved/> is trivial for a
|
||||
malicious third-party to spoof. The verification methods discussed
|
||||
in this document MUST be followed to prevent accepting rogue
|
||||
subscription requests.</li>
|
||||
<li>It is important to verify that the original JID of the migrating
|
||||
user was already authorized to view presence before processing a
|
||||
migration.</li>
|
||||
<li>After successfully processing a migration, the original account
|
||||
should have its presence subscription revoked. This ensures that
|
||||
each JID may only be migrated once. Without this precaution the
|
||||
migration mechanism can be abused to introduce unlimited arbitrary
|
||||
JIDs to contacts' rosters. This precaution also ensures, if the
|
||||
old account ends up owned by a new entity, that they will not
|
||||
unexpectedly inherit a presence subscription.</li>
|
||||
</ul>
|
||||
</section2>
|
||||
</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>
|
||||
|
||||
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
|
||||
<p>This specification defines the following XML namespace:</p>
|
||||
<ul>
|
||||
<li>urn:xmpp:moved:1</li>
|
||||
</ul>
|
||||
</section1>
|
||||
|
||||
<section1 topic='Design Considerations' anchor='design'>
|
||||
<section2 topic='Verification methods' anchor='design-verification'>
|
||||
<p>There are two general approaches for verification - network-based
|
||||
verification, or cryptographic verification. Network-based verification
|
||||
(as described in this document) requests a verification statement from
|
||||
the user's old account. Cryptographic verification would check a move
|
||||
notification against a previously-established cryptographic identify of
|
||||
the user.</p>
|
||||
<p>Network-based verification:</p>
|
||||
<ul>
|
||||
<li>urn:xmpp:moved:0</li>
|
||||
<li>Pro: Simple and easy to implement</li>
|
||||
<li>Con: depends on the original server being available and supporting PEP</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;
|
||||
<p>Cryptographic verification:</p>
|
||||
<ul>
|
||||
<li>Pro: Can work even if the original server goes offline or begins blocking
|
||||
migration attempts.</li>
|
||||
<li>Con: More complex implementation.</li>
|
||||
<li>Con: Requires user and contacts to manage/track cryptographic keys and
|
||||
identies. It may be possible to piggyback on top of an existing cryptographic
|
||||
layer, e.g. OMEMO. However this would eliminate the server-side assistance,
|
||||
and OMEMO support is not universal among clients.</li>
|
||||
</ul>
|
||||
|
||||
<p>Ultimately this document defines a network-based verification method, but
|
||||
leaves an obvious path to extend the protocol with alternative verification
|
||||
methods (either in an update to this document, or defined by other
|
||||
documents).</p>
|
||||
</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>
|
||||
<p>To be done upon advancement to Draft.</p>
|
||||
</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>
|
||||
<p>This document was formerly driven by Tory Patnoe with the support and feedback provided by Doug Abbink, Mikhail Belov, Peter Saint-Andre, and Peter Sheu.</p>
|
||||
<p>It has since been taken over by the current author who thanks Kim Alvefur, Maxime Buquet and Jonas Schäfer for their input and feedback on this specification.</p>
|
||||
</section1>
|
||||
</xep>
|
||||
|
Loading…
Reference in New Issue
Block a user