xmpp协议6
6.3. SASL定义
SASL要求必备的压型(profiling)要求协议的定义提供以下信息:
服务名称:
"xmpp"
初始顺序:
在初始实体发送了一个开的XML流header且接收实体也这样回应之后,接收实体给出一个可接受的认证方法的列表。初始实体从列表中选择一个方法,把它作为<auth/>元素的‘mechanism’属性的值发送给接收实体 ,可选的包含一个初始响应以避免往返的传送(round trip)。
交换顺序:
召唤和响应通过接收实体到初始实体的<challenge/>元素和初始实体到接收实体的< response/>元素的交换携带。接收实体通过发送<failure/>元素报告错误,发送<success/> 元素报告成功;初始实体通过发送<abort/>元素中断交换。成功的协商后,双方认为初始XML流已经关闭,两个实体发送新的XML流 header。
安全层协商:
安全层在给接受实体发送了<success/>元素的闭字符“>”后立即生效,也在给初始实体发送了<success/>元素的闭字符“>”后立即生效。层的次序是先TCP,然后TLS,接着SASL,再是XMPP。
使用认证标识符:
认证 标识符可能被XMPP用于指示一个客户端的非默认<node@domain>,或一个服务器发送的<domain>。
6.4. SASL错误
以下定义了SASL相关的错误因素:
* <aborted/> -- 接收实体肯定应答由初始实体发来的<abort/>元素;给<abort/>元素发送响应。
* <incorrect-encoding/> -- 初始实体提供的数据由于BASE64编码错误而处理不了(如,编码不符合BASE64的规范);给一个<response/>元素或一个 <auth/>元素发送带有初始响应数据的回复。
* <invalid-authzid/> -- 初始实体提供的的authzid无效,或者因为它被错误的格式化或者因为初始实体没有权限授权此ID;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <invalid-mechanism/> -- 初始实体未提供机制或请求到一个不被接受实体支持的机制;发送回复给<auth/>元素。
* <mechanism-too-weak/> - 初始实体请求的机制比服务器策略允许的弱;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <not-authorized/> -- 由于初始实体未提供有效凭证(包含但不局限于未知用户名的情况),认证失败;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <temporary-auth-failure/> -- 由于接受实体内临时性的错误因素使得认证失败;给一个<response/>元素或一个<auth/>元素发送回复。
6.5. C/S 的例子
下面的例子展示了一个客户端与一个服务器用SASL认证的数据流,通常在成功的TLS协商后(注意:下面交叉的步骤用于阐述失败情况下的协议;它们不是很详尽,且不是必需是例子中传送的数据引发的)。
Step 1: 客户端向服务器初始化流:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: 服务器响应,通过发送一个流标识客户端:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_234'
from='example.com'
version='1.0'>
Step 3: 服务器告知客户端可用的认证机制:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Step 4: 客户端选择一个认证机制:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: 服务器发送一个以BASE64编码的召唤给客户端:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>
解码后的召唤是:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): 服务器返回错误到客户端:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: 客户端发送以BASE64编码的响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>
解码后的响应是:
username="somenode",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.com",\
response=d388dad90d4bb*760*152321*2143*f7,charset=utf-8
Step 7: 服务器发送又一个以BASE64编码的召唤给客户端:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
解码后的召唤是:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): 服务器返回错误到客户端:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 8: 客户端发送响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: 服务器告知客户端认证成功:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): 服务器告知客户端认证失败:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 10: 客户端初始化一个新的流到服务器:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: 服务器通过发送一个流header,连同任何附加特性(或者一个空的特性元素)到客户端来响应:
<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>
SASL要求必备的压型(profiling)要求协议的定义提供以下信息:
服务名称:
"xmpp"
初始顺序:
在初始实体发送了一个开的XML流header且接收实体也这样回应之后,接收实体给出一个可接受的认证方法的列表。初始实体从列表中选择一个方法,把它作为<auth/>元素的‘mechanism’属性的值发送给接收实体 ,可选的包含一个初始响应以避免往返的传送(round trip)。
交换顺序:
召唤和响应通过接收实体到初始实体的<challenge/>元素和初始实体到接收实体的< response/>元素的交换携带。接收实体通过发送<failure/>元素报告错误,发送<success/> 元素报告成功;初始实体通过发送<abort/>元素中断交换。成功的协商后,双方认为初始XML流已经关闭,两个实体发送新的XML流 header。
安全层协商:
安全层在给接受实体发送了<success/>元素的闭字符“>”后立即生效,也在给初始实体发送了<success/>元素的闭字符“>”后立即生效。层的次序是先TCP,然后TLS,接着SASL,再是XMPP。
使用认证标识符:
认证 标识符可能被XMPP用于指示一个客户端的非默认<node@domain>,或一个服务器发送的<domain>。
6.4. SASL错误
以下定义了SASL相关的错误因素:
* <aborted/> -- 接收实体肯定应答由初始实体发来的<abort/>元素;给<abort/>元素发送响应。
* <incorrect-encoding/> -- 初始实体提供的数据由于BASE64编码错误而处理不了(如,编码不符合BASE64的规范);给一个<response/>元素或一个 <auth/>元素发送带有初始响应数据的回复。
* <invalid-authzid/> -- 初始实体提供的的authzid无效,或者因为它被错误的格式化或者因为初始实体没有权限授权此ID;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <invalid-mechanism/> -- 初始实体未提供机制或请求到一个不被接受实体支持的机制;发送回复给<auth/>元素。
* <mechanism-too-weak/> - 初始实体请求的机制比服务器策略允许的弱;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <not-authorized/> -- 由于初始实体未提供有效凭证(包含但不局限于未知用户名的情况),认证失败;给一个<response/>元素或一个<auth/>元素发送带有初始响应数据的回复。
* <temporary-auth-failure/> -- 由于接受实体内临时性的错误因素使得认证失败;给一个<response/>元素或一个<auth/>元素发送回复。
6.5. C/S 的例子
下面的例子展示了一个客户端与一个服务器用SASL认证的数据流,通常在成功的TLS协商后(注意:下面交叉的步骤用于阐述失败情况下的协议;它们不是很详尽,且不是必需是例子中传送的数据引发的)。
Step 1: 客户端向服务器初始化流:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 2: 服务器响应,通过发送一个流标识客户端:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_234'
from='example.com'
version='1.0'>
Step 3: 服务器告知客户端可用的认证机制:
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Step 4: 客户端选择一个认证机制:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='DIGEST-MD5'/>
Step 5: 服务器发送一个以BASE64编码的召唤给客户端:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
</challenge>
解码后的召唤是:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\
qop="auth",charset=utf-8,algorithm=md5-sess
Step 5 (alt): 服务器返回错误到客户端:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<incorrect-encoding/>
</failure>
</stream:stream>
Step 6: 客户端发送以BASE64编码的响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
YXJzZXQ9dXRmLTgK
</response>
解码后的响应是:
username="somenode",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop=auth,digest-uri="xmpp/example.com",\
response=d388dad90d4bb*760*152321*2143*f7,charset=utf-8
Step 7: 服务器发送又一个以BASE64编码的召唤给客户端:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
</challenge>
解码后的召唤是:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Step 7 (alt): 服务器返回错误到客户端:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 8: 客户端发送响应给召唤:
<respon** *mlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9: 服务器告知客户端认证成功:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Step 9 (alt): 服务器告知客户端认证失败:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
Step 10: 客户端初始化一个新的流到服务器:
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>
Step 11: 服务器通过发送一个流header,连同任何附加特性(或者一个空的特性元素)到客户端来响应:
<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>