Pure Python Sasl client and server library.
pysasl的Python项目详细描述
pysasl
纯python sasl客户端和服务器库。图书馆的设计是 旨在不确定协议或网络库。
该库目前通过以下方式提供PLAIN
、LOGIN
和CRAM-MD5
机制
违约。特殊情况下,EXTERNAL
和XOAUTH2
机制也可用
情况。
目前还没有计划实现安全层协商支持。
API Documentation
安装
可在PyPi:
pip install pysasl
运行测试
安装到虚拟环境中:
virtualenv env
source env/bin/activate
python setup.py develop
pip install -r test/requirements.txt
运行测试并报告覆盖率指标:
py.test --cov=pysasl
用法
服务器端
服务器端sasl有三个基本要求:
- 必须公布支持的机制,
- 必须向客户端发出身份验证挑战并读取响应,
- 必须确定凭据是否被视为有效。
广告机制
实现可以决定要公布的任何机制子集。做这个
实例化^{
frompysaslimportSASLAuthauth1=SASLAuth()# or...auth2=SASLAuth([b'PLAIN',b'LOGIN'])
要获取所有可用机制的名称:
mechanisms=[mech.nameformechinauth1.server_mechanisms]mech=auth1.get(b'PLAIN')
发布挑战
一旦客户端选择了一个机制,就进入一个循环 对客户的挑战:
defserver_side_authentication(sock,mech):challenges=[]whileTrue:try:creds,_=mech.server_attempt(challenges)returncredsexceptServerChallengeaschal:challenges.append(chal)sock.send(chal.get_challenge()+b'\r\n')chal.set_response(sock.recv(1024).rstrip(b'\r\n'))
值得注意的是,实现并没有那么简单。大多数人会
期望所有传输都以base64编码,通常在
服务器挑战,如334
或+
。请参阅相应的RFC
协议,如RFC 4954 for SMTP或RFC 3501 for IMAP。
检查凭据
一旦挑战响应循环完成,我们就只剩下
一个^{
print('Authenticated as:',result.authcid)print('Authorization ID:',result.authzid)print('Assumed identity:',result.identity)# To compare to a known password...assertresult.check_secret('s3kr3t')# Or to compare hashes...assertpassword_hash==hash(result.secret)
某些机制(例如CRAM-MD5
,EXTERNAL
)不支持直接访问
秘密。在这种情况下,result.has_secret
将是False
,您应该
改用result.check_secret()
。
客户端
客户端身份验证的目标是在 身份验证尝试成功或失败。
选择机构
第一步是选择一个sasl机制。协议应该允许服务器 向客户宣传哪些机制可用:
frompysaslimportSASLAuthauth=SASLAuth(advertised_mechanism_names)mechanisms=[mech.nameformechinauth.client_mechanisms]mech=auth.get(b'PLAIN')
由此产生的机制将是 服务器和pysasl支持的服务器。
发布响应
一旦选择了一种机制,我们就进入一个响应服务器的循环 挑战:
frompysaslimportAuthenticationCredentialsdefclient_side_authentication(sock,mech,username,password):creds=AuthenticationCredentials(username,password)responses=[]whileTrue:resp=mech.client_attempt(creds,responses)sock.send(resp.get_response()+b'\r\n')data=sock.recv(1024).rstrip(b'\r\n')ifdata=='SUCCESS':returnTrueelifdata=='FAILURE':returnFalseresp.set_challenge(data)responses.append(resp)
如您所料,真正的协议可能不会返回SUCCESS
,或者
FAILURE
,这将完全取决于协议的细节。
支持初始响应
一些协议(如smtp)支持客户端发送初始 在第一个服务器质询之前响应,以获取支持它的机制。 一个完全有效的身份验证完全没有挑战:
AUTH PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk
235 2.7.0 Authentication successful
在这种情况下,客户端和服务器端身份验证都应该是 处理方式有点不同。例如服务器端:
exceptServerChallengeaschal:challenges.append(chal)ifinitial_response:chal.set_response(initial_response)initial_response=Noneelse:sock.send(chal.get_challenge()+b'\r\n')chal.set_response(sock.recv(1024).rstrip(b'\r\n'))
对于客户端,只需调用resp = mech.client_attempt(creds, [])
在开始传输之前获取初始响应。全部
机制应返回初始响应或空字符串
当为第二个参数提供空列表时。