mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-24 02:02:16 -05:00
XEP-0389: overhaul document structure
This also adds more information to the <success> element to make flows where the server assigns the JID possible.
This commit is contained in:
parent
a8b67624ac
commit
ae5f2c7ade
284
xep-0389.xml
284
xep-0389.xml
@ -31,6 +31,19 @@
|
|||||||
<supersededby/>
|
<supersededby/>
|
||||||
<shortname>ibr2</shortname>
|
<shortname>ibr2</shortname>
|
||||||
&sam;
|
&sam;
|
||||||
|
<revision>
|
||||||
|
<version>0.5.0</version>
|
||||||
|
<date>2020-05-26</date>
|
||||||
|
<initials>ssw</initials>
|
||||||
|
<remark>
|
||||||
|
<ul>
|
||||||
|
<li>Overhaul document for readability.</li>
|
||||||
|
<li>Add JID and username information to success element.</li>
|
||||||
|
<li>Always require disco/caps feature.</li>
|
||||||
|
<li>More examples.</li>
|
||||||
|
</ul>
|
||||||
|
</remark>
|
||||||
|
</revision>
|
||||||
<revision>
|
<revision>
|
||||||
<version>0.4.0</version>
|
<version>0.4.0</version>
|
||||||
<date>2020-04-22</date>
|
<date>2020-04-22</date>
|
||||||
@ -209,7 +222,7 @@
|
|||||||
…
|
…
|
||||||
</query>]]></example>
|
</query>]]></example>
|
||||||
</section1>
|
</section1>
|
||||||
<section1 topic='Registration Flows' anchor='flows'>
|
<section1 topic='Flows' anchor='flows'>
|
||||||
<p>
|
<p>
|
||||||
Registration or recovery is completed after responding to a series of
|
Registration or recovery is completed after responding to a series of
|
||||||
challenges issued by the server.
|
challenges issued by the server.
|
||||||
@ -223,15 +236,16 @@
|
|||||||
<section2 topic='Stream Feature'>
|
<section2 topic='Stream Feature'>
|
||||||
<p>
|
<p>
|
||||||
If a server supports registering for or recovering an account using
|
If a server supports registering for or recovering an account using
|
||||||
Extensible IBR, it MUST inform the connecting client when returning stream
|
Extensible IBR during stream negotiation, it MUST inform the connecting
|
||||||
features during the stream negotiation process.
|
client when returning stream features during the stream negotiation process.
|
||||||
This is done by including a <register/> element, qualified by the
|
This is done by including a <register/> element, qualified by the
|
||||||
'urn:xmpp:register:0' namespace for account registration, or a
|
'urn:xmpp:register:0' namespace for account registration, or a
|
||||||
<recovery/> element qualified by the same namespace for account
|
<recovery/> element qualified by the same namespace for account
|
||||||
recovery.
|
recovery.
|
||||||
The register and recovery features are always voluntary-to-negotiate.
|
The register and recovery features are always voluntary-to-negotiate.
|
||||||
The registration and recovery features MUST NOT be advertised before
|
The registration and recovery features MUST NOT be advertised before a
|
||||||
encryption has been negotiated, eg. using direct TLS or opportunistic TLS.
|
security layer has been negotiated, eg. using direct TLS or opportunistic
|
||||||
|
TLS.
|
||||||
They SHOULD be advertised at the same time as the SASL authentication
|
They SHOULD be advertised at the same time as the SASL authentication
|
||||||
feature, meaning that after registration or recovery is completed SASL
|
feature, meaning that after registration or recovery is completed SASL
|
||||||
authentication can proceed.
|
authentication can proceed.
|
||||||
@ -244,15 +258,17 @@
|
|||||||
workflow that only contains challenges which the client supports.
|
workflow that only contains challenges which the client supports.
|
||||||
Each <flow/> element MUST have a unique "id" attribute which is used
|
Each <flow/> element MUST have a unique "id" attribute which is used
|
||||||
by the client to identify the flow being selected.
|
by the client to identify the flow being selected.
|
||||||
They must also have at least one <name/> element containing a short,
|
The id attribute is only used during this particular flow negotiation and
|
||||||
|
has no meaning after a flow has been selected.
|
||||||
|
Flows must also have at least one <name/> element containing a short,
|
||||||
human readable description of the flow.
|
human readable description of the flow.
|
||||||
If multiple <name/> elements are present they MUST have unique values
|
If multiple <name/> elements are present they MUST have unique values
|
||||||
for the "xml:lang" attribute.
|
for the "xml:lang" attribute.
|
||||||
Clients MAY use the name element to show the different flows to the user and
|
Clients MAY use the name element to show the different flows to the user and
|
||||||
ask them to pick between them.
|
ask them to pick between them.
|
||||||
Each flow must also contain an unordered set of <challenge/> elements
|
Each flow element must also contain an unordered set of <challenge/>
|
||||||
representing the various challenges that must be completed to complete the
|
elements representing the various challenge types that may be required to
|
||||||
registration or recovery flow.
|
complete the registration or recovery flow.
|
||||||
Each <challenge/> element contains a "type" attribute that uniquely
|
Each <challenge/> element contains a "type" attribute that uniquely
|
||||||
identifies the challenge for the purpose of determining if it is supported.
|
identifies the challenge for the purpose of determining if it is supported.
|
||||||
If a flow would offer the same challenge twice (eg. two data forms asking
|
If a flow would offer the same challenge twice (eg. two data forms asking
|
||||||
@ -296,7 +312,18 @@
|
|||||||
</recovery>
|
</recovery>
|
||||||
</stream:features>]]></example>
|
</stream:features>]]></example>
|
||||||
</section2>
|
</section2>
|
||||||
|
<p>
|
||||||
|
Just because a challenge type is listed by the server in the initial flow
|
||||||
|
element does not mean that it will be issued by the server.
|
||||||
|
Servers MAY choose to issue more or fewer challenges based on the result of
|
||||||
|
previous challenges and may not use every challenge type listed in the
|
||||||
|
original flow.
|
||||||
|
</p>
|
||||||
<section2 topic='Retrieving the Flows'>
|
<section2 topic='Retrieving the Flows'>
|
||||||
|
<p>
|
||||||
|
Registration or recovery may also be completed after stream neogtiation if
|
||||||
|
server policy allows it.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To find what flows an entity provides (if any) after stream negotiation is
|
To find what flows an entity provides (if any) after stream negotiation is
|
||||||
complete the requester can send an IQ of type "get" containing a
|
complete the requester can send an IQ of type "get" containing a
|
||||||
@ -309,7 +336,7 @@
|
|||||||
</iq>]]></example>
|
</iq>]]></example>
|
||||||
<p>
|
<p>
|
||||||
When responding to a query for registration or recovery flows the list of
|
When responding to a query for registration or recovery flows the list of
|
||||||
challenges should be included just as it would be if during stream feature
|
challenges MUST be included just as it would be during stream feature
|
||||||
negotiation.
|
negotiation.
|
||||||
That is, a "register" or "recovery" element containing a list of flows,
|
That is, a "register" or "recovery" element containing a list of flows,
|
||||||
each with an id, containing a name and a list of challenges.
|
each with an id, containing a name and a list of challenges.
|
||||||
@ -333,67 +360,140 @@
|
|||||||
</register>
|
</register>
|
||||||
</iq>]]></example>
|
</iq>]]></example>
|
||||||
<p>
|
<p>
|
||||||
If an entity supports this specification but does not provide any flows
|
If an entity supports issuing challenges but does not provide any flows
|
||||||
after stream negotiation it MUST respond with an empty list.
|
after stream negotiation is complete it MUST respond with an empty list.
|
||||||
|
Similarly, an entity that supports this specification but does not support
|
||||||
|
issuign challenges itself (for example, a client that only supports
|
||||||
|
receiving challenges) it MUST respond successfully with an empty list.
|
||||||
</p>
|
</p>
|
||||||
<example caption='Empty registration flows results'><![CDATA[
|
<example caption='Empty registration flows results'><![CDATA[
|
||||||
<iq type='result'>
|
<iq type='result'>
|
||||||
<register xmlns='urn:xmpp:register:0'/>
|
<register xmlns='urn:xmpp:register:0'/>
|
||||||
</iq>]]></example>
|
</iq>]]></example>
|
||||||
</section2>
|
</section2>
|
||||||
</section1>
|
<section2 topic='Issuing Challenges' anchor='challenge'>
|
||||||
<section1 topic='Challenges' anchor='challenge'>
|
<p>
|
||||||
<p>
|
A client selects the registration or recovery feature for negotiation by
|
||||||
A client selects the registration or recovery feature for negotiation by
|
replying with an element of the same name and namespace.
|
||||||
replying with an element of the same name and namespace.
|
The element MUST contain a <flow> element that MUST have an "id"
|
||||||
The element MUST contain a <flow> element that MUST have an "id"
|
attribute matching one of the flows advertised by the server.
|
||||||
attribute matching one of the flows advertised by the server.
|
For example, to select the "Verify by Phone Call" registration flow from
|
||||||
For example, to select the "Verify by Phone Call" registration flow from
|
the previous example, the client would reply with:
|
||||||
the previous example, the client would reply with:
|
</p>
|
||||||
</p>
|
|
||||||
<example caption='Client selects a recovery flow'><![CDATA[
|
<example caption='Client selects a recovery flow'><![CDATA[
|
||||||
<register xmlns='urn:xmpp:register:0'>
|
<register xmlns='urn:xmpp:register:0'>
|
||||||
<flow id='1'/>
|
<flow id='1'/>
|
||||||
</register>]]></example>
|
</register>]]></example>
|
||||||
<p>
|
<p>
|
||||||
If the client is initiating registration or recovery after a stream has
|
If the client is initiating registration or recovery after a stream has
|
||||||
already been initiated it uses the same registration element wrapped in an
|
already been initiated it uses the same registration element wrapped in an
|
||||||
IQ of type "set".
|
IQ of type "set".
|
||||||
</p>
|
</p>
|
||||||
<example caption='Client selects a recovery flow after stream negotiation'><![CDATA[
|
<example caption='Client selects a recovery flow after stream negotiation'><![CDATA[
|
||||||
<iq type='set' id='foo'>
|
<iq type='set' id='foo'>
|
||||||
<recovery xmlns='urn:xmpp:register:0'>
|
<recovery xmlns='urn:xmpp:register:0'>
|
||||||
<flow id='0'/>
|
<flow id='0'/>
|
||||||
</recovery>
|
</recovery>
|
||||||
</iq>]]></example>
|
</iq>]]></example>
|
||||||
<p>
|
<p>
|
||||||
The server then replies to the IQ or feature selection with a challenge.
|
The server then replies to the IQ or feature selection with a challenge.
|
||||||
If replying to an IQ, the challenge must be wrapped in an IQ of type
|
If replying to an IQ, the challenge must be wrapped in an IQ of type
|
||||||
"result".
|
"result".
|
||||||
Challenges take the form of a <challenge/> element qualified by the
|
Challenges take the form of a <challenge/> element qualified by the
|
||||||
'urn:xmpp:register:0' namespace with a 'type' attribute that uniquely
|
'urn:xmpp:register:0' namespace with a 'type' attribute that uniquely
|
||||||
identifies the type of payload a client might expect the element to contain.
|
identifies the type of payload a client might expect the element to
|
||||||
</p>
|
contain.
|
||||||
|
</p>
|
||||||
<example caption='Server issues a challenge'><![CDATA[
|
<example caption='Server issues a challenge'><![CDATA[
|
||||||
<challenge xmlns='urn:xmpp:register:0'
|
<challenge xmlns='urn:xmpp:register:0'
|
||||||
type='urn:example:challenge'>
|
type='urn:example:challenge'>
|
||||||
<example xmlns='urn:example:challenge'>Payload</example>
|
<example xmlns='urn:example:challenge'>Payload</example>
|
||||||
</challenge>]]></example>
|
</challenge>]]></example>
|
||||||
<p>
|
<p>
|
||||||
After a challenge is received, the client replies to the challenge by
|
After a challenge is received, the client replies to the challenge by
|
||||||
sending a <response/> element qualified by the 'urn:xmpp:register:0'
|
sending a <response/> element qualified by the 'urn:xmpp:register:0'
|
||||||
namespace or a cancellation as defined later in this document.
|
namespace or a cancellation as defined later in this document.
|
||||||
If the client sends a response, it MUST also include the payload
|
If the client sends a response, it MUST also include the payload
|
||||||
corresponding to the challenges 'type' element (which may be empty).
|
corresponding to the challenges 'type' element (which may be empty).
|
||||||
</p>
|
</p>
|
||||||
<example caption='Client responds to a challenge'><![CDATA[
|
<example caption='Client responds to a challenge'><![CDATA[
|
||||||
<response xmlns='urn:xmpp:register:0'>
|
<response xmlns='urn:xmpp:register:0'>
|
||||||
<result xmlns='urn:example:challenge'>Example Response</result>
|
<result xmlns='urn:example:challenge'>Example Response</result>
|
||||||
</response>]]></example>
|
</response>]]></example>
|
||||||
|
<p>
|
||||||
|
After a response is received, if the server needs more information it MAY
|
||||||
|
issue another challenge.
|
||||||
|
For example, if the user has entered their email in response to a
|
||||||
|
challenge, the server might send an email and then issue another challenge
|
||||||
|
asking for the unique code sent in the email.
|
||||||
|
</p>
|
||||||
|
</section2>
|
||||||
|
<section2 topic='Completing Registration or Recovery' anchor='completion'>
|
||||||
|
<p>
|
||||||
|
If after receiving a challenge or response a client or server does not
|
||||||
|
wish to continue registration or recovery, it may send an empty
|
||||||
|
<cancel/> element qualified by the 'urn:xmpp:register:0' namespace.
|
||||||
|
This informs the client or server that registration is complete.
|
||||||
|
This is the same as submitting a data form of type 'cancel' in response to
|
||||||
|
a data form challenge.
|
||||||
|
</p>
|
||||||
|
<example caption='User Cancels Registration or Recovery'><![CDATA[
|
||||||
|
<cancel xmlns='urn:xmpp:register:0'/>]]></example>
|
||||||
|
<p>
|
||||||
|
If the IQ based registration or recovery flow is being used and the server
|
||||||
|
wishes to cancel the flow, it MAY respond to any IQ with the cancel
|
||||||
|
element and type "result".
|
||||||
|
</p>
|
||||||
|
<example caption='Client or server cancels request'><![CDATA[
|
||||||
|
<iq type='result' id='bar'>
|
||||||
|
<cancel xmlns='urn:xmpp:register:0'/>
|
||||||
|
</iq>]]></example>
|
||||||
|
<p>
|
||||||
|
A server may also issue a cancelation IQ with type 'set' if it wishes to
|
||||||
|
cancel after a request/response has been received (ie. when there is no
|
||||||
|
existing IQ to respond to).
|
||||||
|
</p>
|
||||||
|
<example caption='Server cancels flow'><![CDATA[
|
||||||
|
<iq type='set' id='bar'>
|
||||||
|
<cancel xmlns='urn:xmpp:register:0'/>
|
||||||
|
</iq>]]></example>
|
||||||
|
<p>
|
||||||
|
If the client successfully completes all required challenges during stream
|
||||||
|
negotiation the server MUST return a <success/> element qualified by
|
||||||
|
the 'urn:xmpp:register:0' namespace, at which point it may continue with
|
||||||
|
the stream negotiation process.
|
||||||
|
The success element MUST contain a <jid> element containing the bare
|
||||||
|
JID as registered or recovered by the server and a <username>
|
||||||
|
element containing the simple user name for use with SASL (normally this
|
||||||
|
will be the same as the localpart of the JID).
|
||||||
|
</p>
|
||||||
|
<example caption='Server indicates success during steam negotiation'><![CDATA[
|
||||||
|
<success xmlns='urn:xmpp:register:0'>
|
||||||
|
<jid>mercutio@example.net</jid>
|
||||||
|
<username>mercutio</username>
|
||||||
|
</success>]]></example>
|
||||||
|
<p>
|
||||||
|
If the IQ based flow is being used and the server wishes to indicate
|
||||||
|
success after a challenge has been completed it sends an IQ of type "set"
|
||||||
|
containing the <success/> element.
|
||||||
|
</p>
|
||||||
|
<example caption='Server indicates success after stream negotiation'><![CDATA[
|
||||||
|
<iq type='set' id='bar'>
|
||||||
|
<success xmlns='urn:xmpp:register:0'>
|
||||||
|
<jid>mercutio@example.net</jid>
|
||||||
|
<username>mercutio</username>
|
||||||
|
</success>
|
||||||
|
</iq>]]></example>
|
||||||
|
</section2>
|
||||||
|
</section1>
|
||||||
|
<section1 topic='Challenges' anchor='challenge'>
|
||||||
|
<p>
|
||||||
|
This document defines several challenges that use existing technologies.
|
||||||
|
</p>
|
||||||
<section2 topic='Data Form' anchor='dataform'>
|
<section2 topic='Data Form' anchor='dataform'>
|
||||||
<p>
|
<p>
|
||||||
This document defines a type of 'jabber:x:data' which MUST always contain a
|
Challenges of type 'jabber:x:data' MUST always contain a data form (an 'x'
|
||||||
data form (an 'x' element with type 'form') as defined by &xep0004;.
|
element with type 'form') as defined by &xep0004;.
|
||||||
</p>
|
</p>
|
||||||
<example caption='Server issues a data form challenge'><![CDATA[
|
<example caption='Server issues a data form challenge'><![CDATA[
|
||||||
<challenge xmlns='urn:xmpp:register:0'
|
<challenge xmlns='urn:xmpp:register:0'
|
||||||
@ -446,7 +546,7 @@
|
|||||||
</section2>
|
</section2>
|
||||||
<section2 topic='Out of Band Data' anchor='oob'>
|
<section2 topic='Out of Band Data' anchor='oob'>
|
||||||
<p>
|
<p>
|
||||||
Challenges of the type "jabber:x:oob" MUST contain an <x/> element
|
Challenges of type "jabber:x:oob" MUST contain an <x/> element
|
||||||
qualified by the "jabber:x:oob" namespace as defined in &xep0066;.
|
qualified by the "jabber:x:oob" namespace as defined in &xep0066;.
|
||||||
</p>
|
</p>
|
||||||
<example caption='Server issues an OOB challenge'><![CDATA[
|
<example caption='Server issues an OOB challenge'><![CDATA[
|
||||||
@ -462,44 +562,54 @@
|
|||||||
<example caption='Client acknowledges the OOB challenge'><![CDATA[
|
<example caption='Client acknowledges the OOB challenge'><![CDATA[
|
||||||
<response xmlns='urn:xmpp:register:0'/>]]></example>
|
<response xmlns='urn:xmpp:register:0'/>]]></example>
|
||||||
</section2>
|
</section2>
|
||||||
</section1>
|
<section2 topic='SASL' anchor='sasl'>
|
||||||
<section1 topic='Completing Registration or Recovery' anchor='completion'>
|
<p>
|
||||||
<p>
|
Servers can support changing passwords by providing a reset flow
|
||||||
If after receiving a challenge or response a client or server does not wish
|
containing a SASL challenge.
|
||||||
to continue registration or recovery, it may send an empty <cancel/>
|
The SASL challenge re-uses the SASL profile from &rfc6120;.
|
||||||
element qualified by the 'urn:xmpp:register:0' namespace.
|
The server begins by sending the mechanisms list, and the client responds
|
||||||
This informs the client or server that registration is complete.
|
by selecting a mechanism and possibly including initial data.
|
||||||
This is the same as submitting a data form of type 'cancel' in response to a
|
Each step in the SASL process is issued as a new SASL challenge.
|
||||||
data form challenge.
|
</p>
|
||||||
</p>
|
<example caption='SASL challenge flow'><![CDATA[
|
||||||
<example caption='User Cancels Registration or Recovery'><![CDATA[
|
<!-- Server -->
|
||||||
<cancel xmlns='urn:xmpp:register:0'/>]]></example>
|
<challenge xmlns='urn:xmpp:register:0'
|
||||||
<p>
|
type='urn:ietf:params:xml:ns:xmpp-sasl'>
|
||||||
If the IQ based registration or recovery flow is being used and the server
|
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
|
||||||
wishes to cancel the flow, it MAY respond to any IQ from the client with the
|
<mechanism>EXTERNAL</mechanism>
|
||||||
cancel element and type "result".
|
<mechanism>SCRAM-SHA-1-PLUS</mechanism>
|
||||||
</p>
|
<mechanism>SCRAM-SHA-1</mechanism>
|
||||||
<example caption='Server cancels request'><![CDATA[
|
<mechanism>PLAIN</mechanism>
|
||||||
<iq type='result' id='bar'>
|
</mechanisms>
|
||||||
<cancel xmlns='urn:xmpp:register:0'/>
|
</challenge>
|
||||||
</iq>]]></example>
|
|
||||||
<p>
|
<!-- Client -->
|
||||||
If the client successfully completes all required challenges during stream
|
<response xmlns='urn:xmpp:register:0'>
|
||||||
negotiation the server MUST return an empty <success/> element
|
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
|
||||||
qualified by the 'urn:xmpp:register:0' namespace, at which point it may
|
mechanism="SCRAM-SHA-1">
|
||||||
continue with the stream negotiation process.
|
biwsbj1qdWxpZXQscj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQQ==
|
||||||
If the server needs more information, for example, in the previous challenge
|
</auth>
|
||||||
the user entered an email and now the server wishes to ask for a code that
|
</response>
|
||||||
was sent to that email, the server MAY send another challenge.
|
|
||||||
</p>
|
<!-- Server -->
|
||||||
<example caption='Server indicates success during steam negotiation'><![CDATA[
|
<challenge xmlns='urn:xmpp:register:0'
|
||||||
<success xmlns='urn:xmpp:register:0'/>]]></example>
|
type='urn:ietf:params:xml:ns:xmpp-sasl'>
|
||||||
<p>
|
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
||||||
If the IQ based flow is being used and the server wishes to indicate success
|
cj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQWUxMjQ2OTViLTY5Y
|
||||||
it sends an empty IQ response of type "result".
|
TktNGRlNi05YzMwLWI1MWIzODA4YzU5ZSxzPU5qaGtZVE0wTURndE5HWTBaaT
|
||||||
</p>
|
AwTmpkbUxUa3hNbVV0TkRsbU5UTm1ORE5rTURNeixpPTQwOTY=
|
||||||
<example caption='Server indicates success after stream negotiation'><![CDATA[
|
</challenge>
|
||||||
<iq type='result' id='bar' />]]></example>
|
</challenge>
|
||||||
|
|
||||||
|
<!-- Client -->
|
||||||
|
<response xmlns='urn:xmpp:register:0'>
|
||||||
|
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
|
||||||
|
Yz1iaXdzLHI9b01zVEFBd0FBQUFNQUFBQU5QMFRBQUFBQUFCUFUwQUFlMTI0N
|
||||||
|
jk1Yi02OWE5LTRkZTYtOWMzMC1iNTFiMzgwOGM1OWUscD1VQTU3dE0vU3ZwQV
|
||||||
|
RCa0gyRlhzMFdEWHZKWXc9
|
||||||
|
</response>
|
||||||
|
</response>]]></example>
|
||||||
|
</section2>
|
||||||
</section1>
|
</section1>
|
||||||
<section1 topic='Internationalization Considerations' anchor='i18n'>
|
<section1 topic='Internationalization Considerations' anchor='i18n'>
|
||||||
<p>
|
<p>
|
||||||
@ -518,10 +628,10 @@
|
|||||||
Servers that allow in-band registration need to take measures to prevent
|
Servers that allow in-band registration need to take measures to prevent
|
||||||
abuse.
|
abuse.
|
||||||
Common techniques to prevent spam registrations include displaying CAPTCHAs
|
Common techniques to prevent spam registrations include displaying CAPTCHAs
|
||||||
or requiring proof-of-possession of a valid email address or telephone number
|
or requiring proof-of-possession of a valid email address or telephone
|
||||||
by sending a unique code (e.g. an HMAC that can later be verified as having
|
number by sending a unique code (e.g. an HMAC that can later be verified as
|
||||||
originated at the server) to the users email and requiring that they enter
|
having originated at the server) to the users email and requiring that they
|
||||||
the code before continuing.
|
enter the code before continuing.
|
||||||
Servers that do not take such measures risk being black listed by other
|
Servers that do not take such measures risk being black listed by other
|
||||||
servers in the network.
|
servers in the network.
|
||||||
</p>
|
</p>
|
||||||
|
Loading…
Reference in New Issue
Block a user