xmpp即时通讯三

6.1 概述

      XMPP包含一个认证流的方法,此方法依靠一个简单认证与安全层(SASL)协议[SASL]的XMPP-specific profile。SASL提供一个一般化方法,用于给基于连接的协议加认证支持,并且,XMPP使用一个一般化XML命名空间profile,用于 SASL,遵从[SASL]的profiling需求。

      以下规则应用:

      1) 如果两个服务器间发生SASL协商,直到由服务器宣称的域名系统(DNS)主机名被解析了(参考服务器到服务器通信(14.4)),通信才可处理。

      2) 如果实始实体能够进行SASL协商,,它必须在初始流头中包含值至少为“1.0”的版本属性。

      3) 如果接收实体能够进行SASL协商,它必须在一个<mechanisms/>元素中广告一个或多个认证机制,此元素靠 'urn:ietf:params:xml:ns:xmpp-sasl'命名空间响应从初始实体(如果开放流标记包含所设值至少为“1.0”的版本属性)接收的开放流标记认证。

      4) 在SASL协商期间,实体不准在根流元素中发送任何空白字符(匹配[XML]内容,产品[3])作为元素间(任何在SASL例子中的空白字符都只是为了便于阅读)的分隔符;这种限制有助于确保合适的安全层字节精度。

      5) 任何包含在XML元素中的XML字符数据,在SASL协商期间使用,必须使用base64编码,编码在RFC3548第三节有定义。

      6) 如果所提供的一个“简单用户名”能够被选定SASL机制(例:由DIGEST-MD5与CRAM-MD5机制所支持,但不靠EXTERNAL与 GSSAPI机制所支持)所支持,在认证期间,初始实体应当作为简单用户名提供它的发送域(IP地址或包含在域标识符中的全认证域名)在服务器对服务器的通信情况下,或是它的已注册帐户名(包含在XMPP结点标识符中的用户或结点名)在客户到服务器的通信情况下。

      7) 如果初始实体希望代表其它实体与支持授权身份传输的被选SASL机制来行动,初始实体在SASL协商期间必须提供一个授权身份。如果初始实体不希望代表另一个实体行动,它不准提供一个授权身份。正如[SASL]中指定的,初始实体不准提供一个授权身份,除非一个授权身份不同于缺省授权身份,此缺省授权身份派生于描述在[SASL]中的认证身份。如果提供了,授权身份值对服务器来说必须是<domain>值形式(例:只有一个域标识符),对客户端来说,必须是<node@domain>值形式(例:结点标识符与域标识符)。

      8) 靠涉及到安全层协商的SASL协商的成功,接收实体必须抛弃来自本身没有获得SASL协商的初始实体的任何知识。

      9) 靠涉及到安全层协商的SASL协商的成功,初始实体必须抛弃来自本身没有获得SASL协商的接收实体的任何知识。

      10) 参考必须被支持的相关机制的强制实施技术(14.7)。

6.2叙述

      当初始实体使用SASL认证接收实体时,步骤如下:

      1) 初始实体请求SASL认证,通过在开放XML流头中包含版本属性,并将其发送给接收实体,属性值设为“1.0”。

      2) 发送一个XML流头作为回应后,接收实体广告一个可利用的SASL认证机制列表;列表中每一项都是一个<mechanism/>元素,作为<mechanism/>容器元素的子元素,由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间认证,在流命名空间中,依次是<features/>元素的子元素。如果使用TLS(5)需要在一个特别认证机制可能使用之间建立,接收实体不准提供在 TLS协商之前的可利用SASL认证机制列表中的机制。如果初始实体在TLS协商之前出示了有效证书,接收实体应当在SASL协商(参考[SASL])之间,提供SASL EXTERNAL机制给初始实体,虽然EXTERNAL机制可能在其它环境下被提供了。

      3) 初始实体选择一个机制,靠发送一个已被'urn:ietf:params:xml:ns:xmpp-sasl'命名空间认定为合格的<auth/>元素给接收实体,并为‘mechanism’属性包含一个合适的值。如果此机制需要XML字符数据,此元素可能包含XML字符数据(在SASL术语中,“初始响应”);如果初始实体需要发送一个0长度的初始响应,它必须按一个单等号符号(“=”)传输此响应,意味着响应出现,但不包含数据。

      4) 如果需要,接收实体靠发送一个<chanllenge/>元素来挑战实始实体,此元素由给初始实体的 'urn:ietf:params:xml:ns:xmpp-sasl'命名空间来限定;此元素可能包含XML字符数据(必须根据由初始实体选择的 SASL机制的定义一致的来计算)。

      5) 初始实体响应此挑战,靠发送由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的<response/> 元素给接收实体;此元素可能包含XML字符数据(必须根据由初始实体选择的SASL机制的定义一致的来计算)。

      6) 如果需要,接收实体发送更多的挑战,初始实体发送更多的响应。

      Challenge/response序列对继续,直到以下三种事情之一发生:

      1) 初始实体终止握手,靠发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的<abort/>元素给接收实体。根据接收一个<abort/>元素,接收实体应当允许一个可配置的但合理的重试号(至少2),之后,必须终止TCP连接;这使初始实体(例:一个终端用户客户端)能够忍受已提供的不正确的信任(例:一个错误类型的password)而不用被迫重连。

      2) 接收实体报告握手失败,靠发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的<failure/>元素给初始实体(失败的特殊原因应当以<failure/>元素的子元素进行通信,<failure/>元素定义在SASL错误中(6.4))。如果错误情况发生,接收实体应当允许一个可配置的,但合理的重试号(至少 2),之后,它必须终止TCP连接;这使初始实体(例:一个终端用户客户端)能够忍受已提供的不正确的信任(例:一个错误类型的password)而不用被迫重连。

      3) 接收实体报告握手成功,靠发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的<success/>元素给初始实体;此元素可能包含XML字符数据(在SASL术语中,“additional data with success”),如果需要靠选定的SASL机制。根据接收的<success/>元素,初始实体必须靠发送一个开放的XML流头去初始化一个新流给接收实体(它不必事先发送一个关闭</stream>标记,因为接收实体与初始实体必须考虑源流根据发送或接收<success/>元素而将被关闭)。根据从初始实体接收的新流头,接收实体必须发送一个新XML流头给初始实体作为响应,并带有任何可利用的特征(但并不包含STARTTLS与SASL特征)或一个空<features/>元素(重要表示没有其它特征可利用);任何那种其它在此未定义的特征必须由XMPP的相关扩展来定义。

6.3 SASL定义

      [SASL]的profiling需求要求协议定义提供以下信息:

      服务名:“xmpp”

      初始序列:初始实体提供一个开放XML流头后,并且接收实体按此响应后,接收实体提供一个可接收的认证方法列表。初始实体从列表中选择一个方法并作为 ‘machanism’属性值发送给接收实体,此属性被<auth/>元素拥有,随意的包括一个初始响应以避免环路。

      交换序列:挑战与响应通过由接收实体到初始实体<challenge/>元素的交换与由初始实体到接收实体的<response />元素的交换而执行。接收实体靠发送一个<failure/>元素报告错误,发送一个<success/>元素报告成功;初始实体靠发送<abort/>元素终止交换。根据成功协商,两端都认为源XML流将被关并且新流头由两端实体发送。

      安全层协商:安全层在为接收实体发送<success/>元素的关闭“>”字符后立即有效,安全层在为初始实体发送<success/>元素的关闭“>”字符后立即有效。层顺序为:首先是[TCP],然后是[TLS],然后是[SASL],然后是 XMPP。

      使用授权身份:授权身份可以被XMPP用于指示客户端非缺省<node@domain>或服务器发送<domain>。

6.4 SASL错误

      以下是SASL相关错误条件的定义:(略)

1)<aborted/>--

2)<incorrect-encoding/>--

3)<invalid-authzid/>--

4)<invalid-mechanism/>--

5)<mechanism-too-weak/>--

6)<not-authorized/>--

7)<temporary-auth-failure/>--

6.5 客户端到服务器的例子

      以下例子显示了使用SASL授权的客户端与服务器端的数据流,正常情况下,是在TLS协商(注:显示在下面的替换步骤用于显示错误情况的协议;他们并不详尽也不是必要的由本例中数据发送而触发。)成功之后。

步1:客户端初始流给服务器:

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       to='example.com'

       version='1.0'>

步2:服务器使用一个流标记作为响应发送给客户端:

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       id='c2s_234'

       from='example.com'

       version='1.0'>

步3:服务器通知客户端可利用的认证机制:

   <stream:features>

     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

       <mechanism>DIGEST-MD5</mechanism>

       <mechanism>PLAIN</mechanism>

     </mechanisms>

   </stream:features>

步4:客户端选择一个认证机制:

   <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'

         mechanism='DIGEST-MD5'/>

步5:服务器发送一个[BASE64]编码挑战给客户端:

   <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>  cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==

   </challenge>

解码挑战是:

   realm="somerealm",nonce="OA6MG9tEQGm2hh",\

   qop="auth",charset=utf-8,algorithm=md5-sess

步5(替换):服务器返回错误给客户端:

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <incorrect-encoding/>

   </failure>

   </stream:stream>

步6:客户端发送一个[BASE64]编码响应挑战:

   <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i

T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw

MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i   LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK

   </response>

步7:服务器发送另一个[BASE64]编码挑战给客户端:

   <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

   cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=

   </challenge>

解码挑战是:

   rspauth=ea40f60335c427b5527b84dbabcdfffd

步7(替换):服务器返回错误给客户端:

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <temporary-auth-failure/>

   </failure>

   </stream:stream>

步8:客户端响应挑战:

   <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

步9:服务器通知客户端认证成功:

   <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

步9(替换):服务器通知客户端认证失败:

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <temporary-auth-failure/>

   </failure>

   </stream:stream>

步10:客户端初始化一个新流给服务器:

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       to='example.com'

       version='1.0'>

步11:服务器通过发送流头来响应客户端,伴随有任意另外的特征(或空特征元素):

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       id='c2s_345'

       from='example.com'

       version='1.0'>

   <stream:features>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>

     <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>

   </stream:features>

6.6服务器到服务器的例子

      以下例子显示服务器与服务器使用SASL认证的数据流,正常情况下,是在TLS协商之后(注:以下可替换步骤是由失败情况提供的;他们不是详尽的也不是必要的由数据发送而触发)。

步1:Server1初始化流给Server2:

   <stream:stream

       xmlns='jabber:server'

       xmlns:stream='http://etherx.jabber.org/streams'

       to='example.com'

       version='1.0'>

步2:Server2发送一个流标记响应Server1:

   <stream:stream

       xmlns='jabber:server'

       xmlns:stream='http://etherx.jabber.org/streams'

       from='example.com'

       id='s2s_234'

       version='1.0'>

步3:Server2通知Server1可利用的认证机制:

   <stream:features>

     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

       <mechanism>DIGEST-MD5</mechanism>

       <mechanism>KERBEROS_V4</mechanism>

     </mechanisms>

   </stream:features>

步4:Server1选择一个认证机制:

   <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'

         mechanism='DIGEST-MD5'/>

步5:Server2发送一个[BASE64]编码挑战给Server1:

   <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

 cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9

   ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz

   </challenge>

编码挑战是:

   realm="somerealm",nonce="OA6MG9tEQGm2hh",\

   qop="auth",charset=utf-8,algorithm=md5-sess

步5(替换):Server2返回错误给Server1

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <incorrect-encoding/>

   </failure>

   </stream:stream>

步6:Server1发送[BASE64]编码响应挑战:

   <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

   dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j

   ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j

PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5vcmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK

   </response>

解码响应是:

   username="example.org",realm="somerealm",\

   nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\

   nc=00000001,qop=auth,digest-uri="xmpp/example.org",\

   response=d388dad90d4bbd760a152321f2143af7,charset=utf-8

步7:Server2发送另一个[BASE64]编码挑战给Server1:

   <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

   cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=

   </challenge>

解码挑战是:

   rspauth=ea40f60335c427b5527b84dbabcdfffd

步7(替换):Server2返回错误给Server1:

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <invalid-authzid/>

   </failure>

   </stream:stream>

步8:Server1响应挑战:

   <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

步8(替换):Server1终止协商:

   <abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

步9:Server2通知Server1成功认证:

   <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

步9(替换):Server2通知Server1认证失败:

   <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

     <aborted/>

   </failure>

   </stream:stream>

步10:Server1初始化一个新流给Server2:

   <stream:stream

       xmlns='jabber:server'

       xmlns:stream='http://etherx.jabber.org/streams'

       to='example.com'

       version='1.0'>

步11:Server2通过发送一个流头响应Server1,并伴随着其它特征(或空特征元素):

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       from='example.com'

       id='s2s_345'

       version='1.0'>

   <stream:features/>

7.资源绑定

        接收实体SASL协商(6)之后,初始实体可能想要或是需要绑定一个特殊资源至那个流。普通的,这仅用于客户端:为了遵从在此指定的寻址格式(3)与节传送规则(10),必须有一个资源标识符联合客户端的<node@domain>(即可以由服务器产生也可以由客户应用提供);这确保基于流使用的地址是“全JID”形式<node@domain/resource>。

        根据在SASL协商中接收的一个成功指示,客户端必须发送一个新流头给服务器,服务器必须用可利用流特征列表中的内容来响应。特别的,如果服务器需要客户端在SASL成功协商后,将资源绑定到流上,它必须包括一个由在流特征列表中的'urn:ietf:params:xml:ns:xmpp-bind'命名空间限定的空<bind/>元素。成功SASL协商后(不是前),它通过发送响应流的头表示给客户端:

服务器广告资源绑定特征给客户端:

   <stream:stream

       xmlns='jabber:client'

       xmlns:stream='http://etherx.jabber.org/streams'

       id='c2s_345'

       from='example.com'

       version='1.0'>

   <stream:features>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>

   </stream:features>

        根据这样的通知,资源绑定是需要的,客户端必须靠送给服务器一个包含由'urn:ietf:params:xml:ns:xmpp-bind' 命名空间限定的,类型“set”(参考IQ语义(9.2.3))的IQ节,将资源绑定到流上。

        如果客户端希望允许服务器代表自己产生资源标识符,它发送一个类型“set”的IQ节,包含一个空<bind/>元素:

        客户端请求服务器绑定资源:

   <iq type='set' id='bind_1'>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>

   </iq>

        支持资源绑定的服务器必须能代表一个客户端产生一个资源标识符。由服务器产生的资源标识符必须对<node@domain>是唯一的。如果客户端希望指定资源标识符,它发送一个类型为“set”的IQ节,包含所需资源的标识符,作为<bind/>元素子元素<resource/>的XML字符数据。

        客户端绑定一个资源:

   <iq type='set' id='bind_2'>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

       <resource>someresource</resource>

     </bind>

   </iq>

        一旦服务器为客户端产生了一个资源标识符或是接受了由客户端提供的资源标识符,它必须返回一个类型为“result”的IQ节给客户端,必须包含一个<jid>子元素,来为服务器决定的已连接资源指定全JID:

        服务器通知客户端成功资源绑定:

   <iq type='result' id='bind_2'>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

       <jid>somenode@example.com/someresource</jid>

     </bind>

   </iq>

        服务器应当接受由客户端提供的资源标识符,但可能用一个服务器产生的资源标识符覆盖它;在这种情况,服务器不应当返回一个节错误(例:<forbidden/>)给客户端,取而代之,应当以以上显示的IQ结果,传达产生的资源标识符给客户端。

         当客户端提供一个资源标识符,以下节错误条件是可能的(参考节错误(9.3)):

1) 提供的资源标识符不能被与Resourceprep(附录B)一致的服务器处理。

2) 客户端不允许绑定资源到流上(例:因为结点或用户已经达到了在被允许的连接的资源的数目)。

3) 已提供资源标识符已经使用,但服务器并不允许用同样的标识符绑定多连接资源。

        用于这些错误条件的协议显示如下。

        资源标识符不能被处理:

   <iq type='error' id='bind_2'>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

       <resource>someresource</resource>

     </bind>

     <error type='modify'>

       <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>

     </error>

   </iq>

        客户端不允许绑定资源:

   <iq type='error' id='bind_2'>

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

       <resource>someresource</resource>

     </bind>

     <error type='cancel'>

       <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>

     </error>

   </iq>

        资源标识符在使用:

     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

       <resource>someresource</resource>

     </bind>

     <error type='cancel'>

       <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>

     </error>

   </iq>

        如果,完成资源绑定步骤之前,客户端尝试发送一个XML节,而不只是一个带有由'urn:ietf:params:xml:ns:xmpp-bind'命名空间限定的<bind/>子元素的IQ节,服务器不准处理此节,并且,应当返回一个<not-authorized/>节错误给客户端。

8.服务器回叫

8.1概述

        Jabber协议来自于XMPP适用的,包含一个“服务器回叫”方法,用以保护免受域哄骗,因此,使哄骗XML节更困难。服务器回叫并不是一个安全机制,并且仅导致服务器身份弱验证(参考服务器到服务器的通信(14.4)相关方法的安全特性)。域需要健壮的安全性,应当使用TLS与SASL;参考服务器到服务器通信(4.4)细节。如果SASL用于服务器到服务器的认证,回叫不应当使用,因为它是不必要的。包含回叫文档主要是出于与现存实现与部署向后兼容的原因。

        服务器回叫方法因域名系统(DNS)存在而成为可能,由于一个服务器能够(正常的)对一个给定域发现授权服务器。因为回叫依靠DNS,域内通信不准处理,直到由服务器宣称的域名系统(DNS)的主机名被解析(参考服务器到服务器的通信(14.4))。

        服务器回叫是单向的,导致一个方向上一个流身份的(弱)验证。因为服务器回叫不是一个认证机制,通过回叫是不可能进行双向认证的。因此,服务器回叫必须在每个方向上完成,为了使在两个域间进行双向通信成为可能。

        产生与验证密钥的方法用于服务器回叫,必须考虑被用的主机名,由接收服务器产生的流ID,和由授权服务器的网络秘密知道。流ID在服务器回叫中是严格安全的,并且因此必须是即不可预测也不可重复的(参考[RANDOM]推荐资料相关用于安全观点的随机性。)

        任何在回叫协商期间发生的错误必须考虑一个流错误,导致终止流与潜在的TCP连接。协议描述中说明的可能的错误条件如下。

        以下术语应用:

1) 源服务器——试图在两个域间建立连接的服务器。

2) 接收服务器——尝试认证源服务器是否按它声明的那样去表达。

3) 授权服务器——回答由源服务器宣称的DNS主机名;对基本环境来说是源服务器,但在源服务器网络中可以是一个分离的机器。

8.2事件顺序

        以下是回叫事件顺序的简单总结:

1) 源服务器建立到接收服务器的连接。

2) 源服务器通过连接,给接收服务器发送‘key’值。

3) 接收服务器建立到认证服务器的连接。

4) 接收服务器向授权服务器发送相同的‘key’值。

5) 授权服务器回答密钥值是否有效。

6) 接收服务器通知源服务器授权是否通过。

        我们可以将事件顺序以下图表示:

   Originating               Receiving

     Server                    Server

   -----------               ---------

       |                         |

       |   establish connection  |

       | ----------------------> |

       |                         |

       |   send stream header    |

       | ----------------------> |

       |                         |

       |   send stream header    |

       | <---------------------- |

       |                         |                   Authoritative

       |   send dialback key     |                       Server

       | ----------------------> |                   -------------

       |                         |                         |

                                 |   establish connection  |

                                 | ----------------------> |

                                 |                         |

                                 |   send stream header    |

                                 | ----------------------> |

                                 |                         |

                                 |   send stream header    |

                                 | <---------------------- |

                                 |                         |

                                 |   send verify request   |

                                 | ----------------------> |

                                 |                         |

                                 |   send verify response  |

                                 | <---------------------- |

                                 |

       |  report dialback result |

       | <---------------------- |

       |                         |

8.3协议

        服务器间具体协议交互如下:

1) 源服务器建立TCP连接到接收服务器。

2) 源服务器发送流头给接收服务器:

   <stream:stream

       xmlns:stream='http://etherx.jabber.org/streams'

       xmlns='jabber:server'

       xmlns:db='jabber:server:dialback'>

      注:‘to’与‘from’属性在根流元素中是可选的。包含xmlns:db命名空间声明,名字显示向接收实体指示源服务器支持回叫。如果命名空间名不正确,那么,接收服务器必须产生一个<invalid-namespace/>流错误条件并终止XML流与TCP连接。

3) 接收服务器应当发送一个流头返回给源服务器,包含一个用于交互的唯一的ID:

   <stream:stream

       xmlns:stream='http://etherx.jabber.org/streams'

       xmlns='jabber:server'

       xmlns:db='jabber:server:dialback'

       id='457F9224A0...'>

      注:‘to’与‘from’属性在根流元素中是可选的。如果命名空间名不正确,那么源服务器必须产生一个<invalid- namespace/>流错误条件,并终止XML流与TCP连接。而且,接收服务器应当回应,但可能根据适当的安全策略默默终止XML流与TCP连接。然而,如果接收服务器想要处理,它必须发送一个流头返回给源服务器。

4) 源服务器发送一个回叫密钥给接收服务器:

   <db:result

       to='Receiving Server'

       from='Originating Server'>

     98AF014EDC0...

   </db:result>

      注:此密钥并不被接收服务器所检查,因为接收服务器并不保存相关源服务器间会话信息。由源服务器产生的密钥必须部分基于接收服务器在先前步骤提供的ID 值,并部分基于源服务器与授权服务器的保密共享。如果‘to’地址值并不与接收服务器所识别的主机名匹配,那么,接收服务器必须产生一个<host-unknown/>流错误条件并终止XML流与潜在的TCP连接。如果‘from’地址值与带有接收服务器已经建立的连接的域匹配,那么,接收服务器可能选择为新连接产生一个<not-authorized/>流错误条件,然后终止XML流与潜在的与新请求相关的 TCP连接。

5) 接收服务器建立一个TCP连接支持由源服务器宣称的域,作为它连接到授权服务器的结果。(注意:作为优化,一个实现可能重用一个现存的连接。)

6) 接收服务器发送给授权服务器一个流头:

   <stream:stream

       xmlns:stream='http://etherx.jabber.org/streams'

       xmlns='jabber:server'

       xmlns:db='jabber:server:dialback'>

注:在根流元素中,‘to’与‘from’属性是可选的。如果命名空间名不正确,则授权服务器必须产生一个<invalid-namespace/>流错误条件并终止两个XML流与潜在的TCP连接。

7) 授权服务器发送给接收服务器一个流头:

   <stream:stream

       xmlns:stream='http://etherx.jabber.org/streams'

       xmlns='jabber:server'

       xmlns:db='jabber:server:dialback'

id='1251A342B...'>

      注:如果命名空间名不正确,则接收服务器必须产生一个<invalid-namespace/>流错误条件并终止它与授权服务器间的两个 XML流与潜在的TCP连接。如果流错误发生在接收服务器与授权服务器间,则接收服务器必须产生一个<remote-connection- failed/>流错误条件并终止它与发起服务器间的两个XML流与潜在的TCP连接。

8) 接收服务器发给授权服务器要求认证密钥的请求:

   <db:verify

       from='Receiving Server'

       to='Originating Server'

       id='457F9224A0...'>

     98AF014EDC0...

   </db:verify>

      注:经过这儿的是来自接收服务器的流头的主机名、源标识符,到步骤3中的发起服务器,源服务器发送给接收服务器的密钥在步骤4。根据这些信息,还有授权服务器网络中的共享密钥信息,密钥被验证。任何验证方法可能用于产生密钥。如果‘to’地址值与授权服务器识别的主机名不匹配,那么,授权服务器必须产生一个<host-unknown/>流错误条件并终止两个XML与潜在的TCP连接。如果‘from’地址值与源服务器打开TCP连接时(或任意相关有效域,例如接收服务器的主机名或其它有效域一个有效子域)所表示的主机名不匹配,则授权服务器必须产生一个<invalid- from/>流错误条件并终止两个XML流与潜在的TCP连接。

9) 授权服务器验证密钥是否有效

   <db:verify

       from='Originating Server'

       to='Receiving Server'

       type='valid'

       id='457F9224A0...'/>

   或

   <db:verify

       from='Originating Server'

       to='Receiving Server'

       type='invalid'

id='457F9224A0...'/>

      注:如果ID与步骤3中的接收服务器不匹配,那么接收服务器必须产生一个<invalid-id/>流错误条件并终止两个XML流与潜在的 TCP连接。如果‘to’地址值与接收服务器所识别的主机名不匹配,则接收服务器必须产生一个<host-unknown/>流错误条件并终止两个XML流与潜在的TXP连接。如果‘from’地址值与源服务器打开TCP连接时(或任意相关有效域,例如接收服务器的主机名或其它有效域一个有效子域)所表示的主机名不匹配,则接收服务器必须产生一个<invalid-from/>流错误条件并终止两个XML流与潜在的TCP连接。返回认证信息给接收服务器之后,授权服务器应当终止他们之间的流。

10) 接收服务器通知源服务器结果:

   <db:result

       from='Receiving Server'

       to='Originating Server'

type='valid'/>

      注:在这里,连接可通过一个type='valid'或报告为无效来被认证。如果连接无效,则接收服务器必须终止两个XML流与潜在的TCP连接。如果连接被认证,数据可被源服务器发送并被接收服务器读取;在此这前,所有发送给接收服务器的XML节应该默默被扔掉。

      前述结果是接收服务器已经认证了源服务器的身份,为了节通过“初始流”(如,从源服务器到接收服务器的流)的XML能被源服务器发送与接收服务器能接收,为了验证使用“响应流”(如,从接收服务器到源服务器)实体的身份,回叫必须以相反方向完成。

      成功回叫协调后,接收服务器应当接收来自通过现存已认证连接的源服务器的子序列<db:result/>包(例如,认证需求发送到子域或其它由接收服务器服务主机名);这使在一个方向上的原来的已认证连接的"piggybacking"成为可能。

      即使回叫协调成功,服务器必须认证从其它服务器接收的XML节,包括‘from’属性与‘to’属性;如果一个节并不满足此限制,接收节的服务器必须产生一个<improper-addressing/>流错误条件并终止两个XML流与潜在的TCP连接。进一步讲,服务器必须认证从其它服务器,包括流的一个已验证域的‘from’属性;如果节并不满足此限制,收到节的服务器必须产生一个<invalid-from/>流错误条件并终止两个XML流与潜在的TCP连接。这两个检查有助于阻止关联到特别节的哄骗。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏熊训德的专栏

Hbase replication源码分析

本文主要通过Replication的核心原理和failover 过程,对Hbase replication源码分析,希望对大家了解Hbase源码有所帮助。

1.5K00
来自专栏互联网大杂烩

操作系统-进程和线程

进程线程的区别 1、进程是什么? 是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独立运行...

16140
来自专栏张首富-小白的成长历程

redis缓存服务器

#你当前没有指定配置文件,以默认的配置文件启动,如果你想指定配置文件你可以redis-server 文件所在位置

63120
来自专栏周明礼的专栏

一步一步带你搭建一个“摩登”的前端开发环境

最近几年也陆续推出了多种不同的js类型系统用于增强js的健壮性,其中像 typescript 就是其中的佼佼者。当然我今天要讲的并不是typescript,而是...

1.5K00
来自专栏张善友的专栏

替换EnterPrise Library 4.0 缓存应用程序块的CacheManager

缓存是用来提高应用程序性能的常见技术,其实现方式是将常用数据从慢数据源复制到更快的数据源。对于数据驱动的应用程序来说,该技术通常需要将从数据库或 Web 服务检...

20370
来自专栏CDA数据分析师

Python 探针实现原理

本文将简单讲述一下 Python 探针的实现原理。 同时为了验证这个原理,我们也会一起来实现一个简单的统计指定函数执行时间的探针程序。 探针的实现主要涉及以下几...

41180
来自专栏领域驱动设计DDD实战进阶

微服务实战(八):落地微服务架构到直销系统(服务高可用性)

在微服务架构风格的系统中,如果单个微服务垮掉或地址不可访问,虽然对系统的影响是有限的,但我们也必须采取一定的手段来保证每个微服务尽量可用;并且在大并发的情况下,...

25530
来自专栏性能与架构

Redis 实现接口访问频率限制

为什么限制访问频率 做服务接口时通常需要用到请求频率限制 Rate limiting,例如限制一个用户1分钟内最多可以范围100次 主要用来保证服务性能和保护数...

71780
来自专栏PPV课数据科学社区

【平台】HBase学习总结

HBase的下载与安装 (HBase是一种数据库:Hadoop数据库,它是一种NoSQL存储系统,专门设计用来快速随机读写大规模数据。本文介绍HBase的下...

74370
来自专栏Java后端技术栈

【动画】当我们在读写Socket时,我们究竟在读写什么?

套接字socket是大多数程序员都非常熟悉的概念,它是计算机网络编程的基础,TCP/UDP收发消息都靠它。我们熟悉的web服务器底层依赖它,我们用到的MySQL...

13320

扫码关注云+社区

领取腾讯云代金券