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鏈接。這兩個檢查有助於阻止關聯到特別節的哄騙。
本文同步分享在 博客「xiangzhihong8」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。node