3
]ð]CP  ã            6   @   s  d Z ddlZddlZddlZddlZddlZyddlmZ W n  ek
r\   ddl	mZ Y nX dZ
dZy2ddlZeeeejjdƒdd… ƒƒdQkr–dZW n: ek
rÒ   yddlZW n ek
rÌ   dZ
Y nX Y nX dd	lmZmZ dd
lmZ ddlmZ ddlmZmZmZ ddlmZ ddl m!Z!m"Z" ddl#m$Z$ e%dddddddgƒZ&G dd„ de'ƒZ(edddddddgƒZ)ed d!d"d#gƒZ*d$d%„ Z+e�r¨d&d'„ Z,ej-Z.ej/Z0n2dd(l1m2Z3m4Z5 d)d'„ Z,ee3fd*d+„Z.e5fd,d-„Z0ydd.l6m7Z8 W nF ek
�r0   ydd.lm7Z8 W n ek
�r*   d/d0„ Z8Y nX Y nX ydd1lm9Z9 W n> ek
�r€   e�rdd2d3„ Z:ne;fd4d3„Z:e:fd5d6„Z9Y nX d7d8„ Z<d9d:„ Z=d;d<„ Z>d=d>„ Z?d?d@„ Z@dAdB„ ZAdCdD„ ZBdEdF„ ZCdGdH„ ZDdIdJ„ ZEeBe@eDeCeAejFe=ddK�ejFe=ddK�eEdLœZGdMdN„ ZHdOdP„ ZIdS )RzAuthentication helpers.é    N)ÚquoteTFÚ.é   é   )Ústandard_b64decodeÚstandard_b64encode)Ú
namedtuple)ÚBinary)Ústring_typeÚ_unicodeÚPY3)ÚSON)ÚConfigurationErrorÚOperationFailure)ÚsaslprepÚGSSAPIz
MONGODB-CRzMONGODB-X509ÚPLAINzSCRAM-SHA-1zSCRAM-SHA-256ÚDEFAULTc               @   s8   e Zd ZdZed ƒZdd„ Zdd„ Zdd„ Zdd	„ Z	d
S )Ú_CacheÚdatac             C   s
   d | _ d S )N)r   )Úself© r   ú//tmp/pip-build-20mum3z4/pymongo/pymongo/auth.pyÚ__init__B   s    z_Cache.__init__c             C   s   t |tƒrdS tS )NT)Ú
isinstancer   ÚNotImplemented)r   Úotherr   r   r   Ú__eq__E   s    
z_Cache.__eq__c             C   s   t |tƒrdS tS )NF)r   r   r   )r   r   r   r   r   Ú__ne__K   s    
z_Cache.__ne__c             C   s   | j S )N)Ú	_hash_val)r   r   r   r   Ú__hash__P   s    z_Cache.__hash__N)r   )
Ú__name__Ú
__module__Ú__qualname__Ú	__slots__Úhashr   r   r   r   r    r   r   r   r   r   =   s   r   ÚMongoCredentialÚ	mechanismÚsourceÚusernameÚpasswordÚmechanism_propertiesÚcacheÚGSSAPIPropertiesÚservice_nameÚcanonicalize_host_nameÚservice_realmc             C   s.  | dkr|dkrt d| f ƒ‚| dkrŒ|dk	r>|dkr>tdƒ‚|jdi ƒ}|jdd	ƒ}|jd
dƒ}|jdƒ}	t|||	d�}
t| d|||
dƒS | dkrÎ|dk	r¤t dƒ‚|dk	r¼|dkr¼tdƒ‚t| d|dddƒS | dkrô|pà|pàd}t| |||ddƒS |�p|�pd}|dk�rt dƒ‚t| |||dtƒ ƒS dS )z=Build and return a mechanism specific credentials tuple.
    zMONGODB-X509Nz%s requires a username.r   z	$externalz:authentication source must be $external or None for GSSAPIZauthmechanismpropertiesZSERVICE_NAMEZmongodbZCANONICALIZE_HOST_NAMEFZSERVICE_REALM)r.   r/   r0   z+Passwords are not supported by MONGODB-X509z@authentication source must be $external or None for MONGODB-X509r   ZadminzA password is required.)r   Ú
ValueErrorÚgetr-   r&   r   )Zmechr(   ÚuserÚpasswdÚextraZdatabaseZ
propertiesr.   Zcanonicalizer0   ÚpropsZsource_databaser   r   r   Ú_build_credentials_tupleg   s<    

r7   c             C   s   dj dd„ t| |ƒD ƒƒS )z+XOR two byte strings together (python 3.x).ó    c             S   s   g | ]\}}t ||A gƒ‘qS r   )Úbytes)Ú.0ÚxÚyr   r   r   ú
<listcomp>‘   s    z_xor.<locals>.<listcomp>)ÚjoinÚzip)ÚfirÚsecr   r   r   Ú_xor�   s    rB   )ÚhexlifyÚ	unhexlifyc             C   s   dj dd„ t| |ƒD ƒƒS )z+XOR two byte strings together (python 2.x).r8   c             S   s$   g | ]\}}t t|ƒt|ƒA ƒ‘qS r   )ÚchrÚord)r:   r;   r<   r   r   r   r=   �   s    z_xor.<locals>.<listcomp>)r>   r?   )r@   rA   r   r   r   rB   ›   s    c             C   s   ||| ƒdƒS )z3An implementation of int.from_bytes for python 2.x.é   r   )ÚvalueÚdummyÚ_intÚ_hexlifyr   r   r   Ú_from_bytes    s    rL   c             C   s   dd| f }|||  ƒS )z1An implementation of int.to_bytes for python 2.x.z%%0%dxr   r   )rH   ÚlengthrI   Ú
_unhexlifyÚfmtr   r   r   Ú	_to_bytes¥   s    rP   )Úpbkdf2_hmacc             C   sx   t j|dtt| ƒƒ}|fdd„}t}t}||d ƒ}||dƒ}	x*t|d ƒD ]}
||ƒ}|	||dƒN }	qLW ||	|jdƒS )z'A simple implementation of PBKDF2-HMAC.Nc             S   s   |j ƒ }|j| ƒ |jƒ S )zGet a digest for msg.)ÚcopyÚupdateÚdigest)ÚmsgÚmacZ_macr   r   r   Ú_digest¸   s    
z_hi.<locals>._digests      Úbigé   )ÚhmacÚHMACÚgetattrÚhashlibrL   rP   ÚrangeÚdigest_size)Ú	hash_namer   ÚsaltÚ
iterationsrV   rW   Ú
from_bytesÚto_bytesZ_u1Z_uiÚ_r   r   r   Ú_hi´   s    
rf   )Úcompare_digestc             C   s   | |A S )Nr   )ÚaÚbr   r   r   Ú
_xor_bytesÌ   s    rj   c             C   s   || ƒ||ƒA S )Nr   )rh   ri   Ú_ordr   r   r   rj   Ï   s    c             C   sf   d }|}t | ƒt |ƒkr | }d}t | ƒt |ƒkr8|}d}x$t||ƒD ]\}}||||ƒO }qDW |dkS )Nr   rY   )Úlenr?   )rh   ri   rj   ÚleftÚrightÚresultr;   r<   r   r   r   rg   Ù   s    rg   c             C   s   t dd„ | jdƒD ƒƒS )z-Split a scram response into key, value pairs.c             s   s   | ]}|j d dƒV  qdS )ó   =rY   N)Úsplit)r:   Úitemr   r   r   ú	<genexpr>ê   s    z(_parse_scram_response.<locals>.<genexpr>ó   ,)Údictrq   )Úresponser   r   r   Ú_parse_scram_responseè   s    rw   c              C   sŒ  | j }|dkr*d}tj}t| jƒjdƒ}nd}tj}t|| jƒjdƒ}| j}| j	}t
j}	|jdƒjddƒjddƒ}
ttjd	ƒƒ}d
|
 d | }td$d|fdtd| ƒfd%gƒ}|j||ƒ}|d }t|ƒ}t|d ƒ}|dk rètdƒ‚|d }|d }|j|ƒ�stdƒ‚d| }|j�r,|j\}}}}nd&\}}}}| �sT||k�sT||k�r”t||t|ƒ|ƒ}|	|d|ƒjƒ }|	|d|ƒjƒ }||||f|_||ƒjƒ }dj|||fƒ}|	|||ƒjƒ }dtt||ƒƒ }dj||fƒ}t|	|||ƒjƒ ƒ}td'd|d fdt|ƒfgƒ}|j||ƒ}t|d ƒ}t|d |ƒ�sBtd ƒ‚|d! �sˆtd(d|d fdtd"ƒfgƒ}|j||ƒ}|d! �sˆtd#ƒ‚dS ))zAuthenticate using SCRAM.zSCRAM-SHA-256Úsha256zutf-8Úsha1rp   s   =3Drt   s   =2Cé    s   n=s   ,r=Ú	saslStartrY   r'   Úpayloads   n,,ÚautoAuthorizeó   ii   z+Server returned an invalid iteration count.ó   só   rz!Server returned an invalid nonce.s	   c=biws,r=Ns
   Client Keys
   Server Keys   p=ÚsaslContinueÚconversationIdó   vz%Server returned an invalid signature.Údoner8   z%SASL conversation failed to complete.)r{   rY   )r}   rY   )NNNN)r�   rY   )r�   rY   )r)   r]   rx   r   r*   Úencodery   Ú_password_digestr(   r,   rZ   r[   Úreplacer   ÚosÚurandomr   r	   Úcommandrw   Úintr   Ú
startswithr   rf   r   rT   r>   rB   rg   ) ÚcredentialsÚ	sock_infor'   r)   rT   Ú	digestmodr   r(   r,   Z_hmacr3   ÚnonceZ
first_bareÚcmdÚresZserver_firstÚparsedrb   ra   ZrnonceZwithout_proofZ
client_keyZ
server_keyZcsaltZciterationsZsalted_passZ
stored_keyZauth_msgZ
client_sigZclient_proofZclient_finalZ
server_sigr   r   r   Ú_authenticate_scramí   sv    



r”   c             C   sx   t |tƒstdtjf ƒ‚t|ƒdkr.tdƒ‚t | tƒsHtdtjf ƒ‚tjƒ }d| |f }|j|j	dƒƒ t
|jƒ ƒS )z5Get a password digest to use for authentication.
    z"password must be an instance of %sr   zpassword can't be emptyz#password must be an instance of  %sz%s:mongo:%szutf-8)r   r
   Ú	TypeErrorr!   rl   r1   r]   Úmd5rS   r…   r   Ú	hexdigest)r)   r*   Úmd5hashr   r   r   r   r†   >  s    

r†   c             C   s<   t ||ƒ}tjƒ }d| ||f }|j|jdƒƒ t|jƒ ƒS )z/Get an auth key to use for authentication.
    z%s%s%szutf-8)r†   r]   r–   rS   r…   r   r—   )r�   r)   r*   rT   r˜   r   r   r   r   Ú	_auth_keyP  s
    
r™   c             C   s�  t stdƒ‚�yJ| j}| j}| j}|jd }|jr<tj|ƒ}|j	d | }|j
dk	rb|d |j
 }|dk	rÜtrœdjt|ƒt|ƒfƒ}tj||tjd�\}}	qðd|kr¶|jddƒ\}
}n
|d }
}tj|tj|
||d�\}}	ntj|tjd�\}}	|tjk�rtd	ƒ‚�zBtj|	d
ƒdk�r"tdƒ‚tj|	ƒ}tddd|fdgƒ}|jd|ƒ}x„tdƒD ]p}tj|	t|d ƒƒ}|dk�r€tdƒ‚tj|	ƒ�pŽd
}tdd|d fd|fgƒ}|jd|ƒ}|tjk�rVP �qVW tdƒ‚tj|	t|d ƒƒdk�rôtdƒ‚tj|	tj|	ƒ|ƒdk�rtdƒ‚tj|	ƒ}tdd|d fd|fgƒ}|jd|ƒ W dtj|	ƒ X W n2 tjk
�rŠ } ztt|ƒƒ‚W Y dd}~X nX dS )zAuthenticate using GSSAPI.
    zEThe "kerberos" module must be installed to use GSSAPI authentication.r   ú@Nú:)ÚgssflagsrY   )rœ   r3   Údomainr*   z&Kerberos context failed to initialize.Ú z*Unknown kerberos failure in step function.r{   r'   r   r|   r}   z	$externalé
   r�   r‚   z+Kerberos authentication failed to complete.z0Unknown kerberos failure during GSS_Unwrap step.z.Unknown kerberos failure during GSS_Wrap step.)r{   rY   )r'   r   )r}   rY   éÿÿÿÿ)r�   rY   )r�   rY   )ÚHAVE_KERBEROSr   r)   r*   r+   Úaddressr/   ÚsocketÚgetfqdnr.   r0   Ú_USE_PRINCIPALr>   r   ÚkerberosZauthGSSClientInitZGSS_C_MUTUAL_FLAGrq   ZAUTH_GSS_COMPLETEr   ZauthGSSClientStepZauthGSSClientResponser   rŠ   r^   ÚstrZauthGSSClientUnwrapZauthGSSClientWrapZauthGSSClientCleanZKrbError)r�   rŽ   r)   r*   r6   ÚhostZserviceZ	principalro   Úctxr3   r�   r|   r‘   rv   re   Úexcr   r   r   Ú_authenticate_gssapiZ  s€    








r«   c             C   sL   | j }| j}| j}d||f jdƒ}td
ddt|ƒfdgƒ}|j||ƒ d	S )z-Authenticate using SASL PLAIN (RFC 4616)
    z %s %szutf-8r{   rY   r'   r   r|   r}   N)r{   rY   )r'   r   )r}   rY   )r(   r)   r*   r…   r   r	   rŠ   )r�   rŽ   r(   r)   r*   r|   r‘   r   r   r   Ú_authenticate_plainÈ  s    
r¬   c       
      C   s®   | j }| j}| j}t||ƒ}tdddtdƒfdgƒ}|j||ƒ}tj|j	dƒt
jd	�}|j|d ƒ |j	dƒd
 |jƒ j	dƒ }	tdd|d fdt|	ƒfgƒ}|j||ƒ dS )z+Authenticate using CRAM-MD5 (RFC 2195)
    r{   rY   r'   úCRAM-MD5r|   r8   r}   zutf-8)Úkeyr�   ó    r�   r‚   N)r{   rY   )r'   r­   )r}   rY   )r�   rY   )r(   r)   r*   r†   r   r	   rŠ   rZ   r[   r…   r]   r–   rS   r—   )
r�   rŽ   r(   r)   r*   r4   r‘   rv   rV   Ú	challenger   r   r   Ú_authenticate_cram_md5Ö  s     


r±   c             C   sD   t d
dgƒ}| jdk	r"| j|d< n|jdk r4tdƒ‚|jd	|ƒ dS )z%Authenticate using MONGODB-X509.
    ÚauthenticaterY   r'   úMONGODB-X509Nr3   r   ziA username is required for MONGODB-X509 authentication when connected to MongoDB versions older than 3.4.z	$external)r²   rY   )r'   r³   )r   r)   Úmax_wire_versionr   rŠ   )r�   rŽ   Úqueryr   r   r   Ú_authenticate_x509ï  s    

r¶   c       	      C   sb   | j }| j}| j}|j|ddiƒ}|d }t|||ƒ}tdd|fd|fd|fgƒ}|j||ƒ dS )	z#Authenticate using MONGODB-CR.
    ZgetnoncerY   r�   r²   r3   r®   N)r²   rY   )r(   r)   r*   rŠ   r™   r   )	r�   rŽ   r(   r)   r*   rv   r�   r®   rµ   r   r   r   Ú_authenticate_mongo_crý  s    r·   c             C   sˆ   |j dkrd| j}tdd|d | j fgƒ}|j||dd�jdg ƒ}d|krVt| |dƒS t| |d	ƒS n |j d
krzt| |d	ƒS t| |ƒS d S )Né   ÚismasterrY   ZsaslSupportedMechsr   F)Zpublish_eventszSCRAM-SHA-256zSCRAM-SHA-1é   )r¹   rY   )r´   r(   r   r)   rŠ   r2   r”   r·   )r�   rŽ   r(   r‘   Zmechsr   r   r   Ú_authenticate_default  s    

r»   )r'   )zCRAM-MD5r   z
MONGODB-CRzMONGODB-X509r   zSCRAM-SHA-1zSCRAM-SHA-256r   c             C   s   | j }tj|ƒ}|| |ƒ dS )zAuthenticate sock_info.N)r'   Ú	_AUTH_MAPr2   )r�   rŽ   r'   Z	auth_funcr   r   r   r²   0  s    
r²   c             C   s   |j | ddiƒ dS )zLog out from a database.ÚlogoutrY   N)rŠ   )r(   rŽ   r   r   r   r½   7  s    r½   )r   r   )JÚ__doc__Ú	functoolsr]   rZ   rˆ   r£   Úurllibr   ÚImportErrorÚurllib.parser¡   r¥   Zwinkerberosr¦   ÚtupleÚmapr‹   Ú__version__rq   Úbase64r   r   Úcollectionsr   Zbson.binaryr	   Zbson.py3compatr
   r   r   Zbson.sonr   Zpymongo.errorsr   r   Zpymongo.saslprepr   Ú	frozensetZ
MECHANISMSÚobjectr   r&   r-   r7   rB   rc   rL   rd   rP   ÚbinasciirC   rK   rD   rN   Zbackports.pbkdf2rQ   rf   rg   rj   rF   rw   r”   r†   r™   r«   r¬   r±   r¶   r·   r»   Úpartialr¼   r²   r½   r   r   r   r   Ú<module>   sº   "'

Q
n