U
    ~fhlJ                     @  s  d Z ddlmZ ddlZddlZddlZddlZ	ddl
ZddlmZ ddlmZ ddlmZmZmZmZmZmZ ddlmZ ddlZddlmZ ddlmZ  dd	l!m"Z# dd
l!m$Z$ ddl%m&Z& ddl'm(Z(m)Z) ddl*m+Z, ddl*m-Z- ddl.m/Z/ erddlm0Z0 edZ1zddl2Z2dZ3W n e4k
r8   dZ3Y nX ej5Z6ej7Z7ej8Z8ej9Z9e:eddZ;dZ<dZ=ej>Z?ej@ejAejBejCejDejCejEB iZFdd eFG D ZHdddddZIejJejKejLfZMejJZNejKZOejLZPdddddZQG d d! d!ejRZSG d"d# d#ZTG d$d% d%ZUdS )&zMA CPython compatible SSLContext implementation wrapping PyOpenSSL's
context.
    )annotationsN)EINTR)
ip_address)TYPE_CHECKINGAnyCallableOptionalTypeVarUnion)SSL)crypto)ConfigurationError)_CertificateError)
_OCSPCache)_load_trusted_ca_certs_ocsp_callback)SocketChecker)_errno_from_exception)validate_boolean)
VerifyMode_TTFOP_NO_RENEGOTIATIONc                 C  s   i | ]\}}||qS  r   ).0keyvaluer   r   =/tmp/pip-unpacked-wheel-36gvocj8/pymongo/pyopenssl_context.py
<dictcomp>M   s      r   r   bool)addressreturnc              	   C  s.   zt |  W dS  ttfk
r(   Y dS X d S )NTF)_ip_address
ValueErrorUnicodeError)r   r   r   r   _is_ip_addressR   s
    r$   BaseException)excr    c                 C  s
   | j dkS )z<Return True if the OpenSSL.SSL.SysCallError is a ragged EOF.)zUnexpected EOF)args)r&   r   r   r   _ragged_eofb   s    r)   c                      s   e Zd Zdddd fddZdddd	d
ddZdddd fddZdddd fddZdddd fddZddddd fddZ  Z	S )_sslConnz_SSL.ContextzOptional[_socket.socket]r   )ctxsocksuppress_ragged_eofsc                   s    t  | _|| _t || d S N)_SocketCheckersocket_checkerr-   super__init__)selfr+   r,   r-   	__class__r   r   r2   k   s    z_sslConn.__init__zCallable[..., _T]r   r   )callr(   kwargsr    c           	   
   O  s   |   }|rt }z|||W S  tk
r } z|  dkrh|r^t | |kr^tdd tdd t|t	j
r~d}d}nt|t	jrd}d}nd}d}| j| ||| |rt | |krtdd W Y qW 5 d }~X Y qX qd S )Nr'   z	timed outz!Underlying socket has been closedTF)
gettimeout_time	monotonicBLOCKING_IO_ERRORSfileno_sockettimeoutSSLError
isinstance_SSLWantReadErrorWantWriteErrorr0   select)	r3   r6   r(   r7   r>   startr&   Z	want_readZ
want_writer   r   r   _callr   s,    
z_sslConn._callNone)r(   r7   r    c                   s   | j t jf||S r.   )rF   r1   do_handshake)r3   r(   r7   r4   r   r   rH      s    z_sslConn.do_handshakebytesc              
     s\   z| j t jf||W S  tjk
rV } z| jrDt|rDW Y 
dS  W 5 d }~X Y nX d S )N    )rF   r1   recvrA   SysCallErrorr-   r)   r3   r(   r7   r&   r4   r   r   rK      s    
z_sslConn.recvintc              
     s\   z| j t jf||W S  tjk
rV } z| jrDt|rDW Y 
dS  W 5 d }~X Y nX d S Nr   )rF   r1   	recv_intorA   rL   r-   r)   rM   r4   r   r   rP      s    
z_sslConn.recv_intor   )bufflagsr    c              
     s   t |}t|}d}||k rz| t j||d  |}W n8 tk
rr } zt|tkr`W Y q W 5 d }~X Y nX |dkrtd||7 }qd S )Nr   zconnection closed)
memoryviewlenrF   r1   sendOSErrorr   _EINTR)r3   rQ   rR   viewtotal_length
total_sentsentr&   r4   r   r   sendall   s    z_sslConn.sendall)r   )
__name__
__module____qualname__r2   rF   rH   rK   rP   r\   __classcell__r   r   r4   r   r*   j   s   		r*   c                   @  s   e Zd ZdZddddZdS )_CallbackDataz0Data class which is passed to the OCSP callback.rG   r    c                 C  s   d | _ d | _t | _d S r.   )trusted_ca_certscheck_ocsp_endpointr   Zocsp_response_cacher3   r   r   r   r2      s    z_CallbackData.__init__N)r]   r^   r_   __doc__r2   r   r   r   r   ra      s   ra   c                	   @  sp  e Zd ZdZdZddddZedddd	Zd
dddZd
ddddZ	eee	Z
ddddZdddddZeeeZddddZdddddZeeeZddddZdddddZeeeZd>d!d"d#dd$d%d&Zd?d#d#dd'd(d)Zddd*d+Zd,dd-d.d/Zddd0d1Zddd2d3Zd@d6dddd#d7d8d9d:d;ZdAd6dddd#d7d8d9d<d=Zd S )B
SSLContextzUA CPython compatible SSLContext implementation wrapping PyOpenSSL's
    context.
    )	_protocol_ctx_callback_data_check_hostnamerN   )protocolc                 C  s@   || _ t| j | _t | _d| _d| j_| jjt	| jd d S )NT)callbackdata)
rh   rA   Contextri   ra   rj   rk   rd   Zset_ocsp_client_callbackr   )r3   rl   r   r   r   r2      s    zSSLContext.__init__rb   c                 C  s   | j S )zhThe protocol version chosen when constructing the context.
        This attribute is read-only.
        )rh   re   r   r   r   rl      s    zSSLContext.protocolr   c                 C  s   t | j  S )zWhether to try to verify other peers' certificates and how to
        behave if verification fails. This attribute must be one of
        ssl.CERT_NONE, ssl.CERT_OPTIONAL or ssl.CERT_REQUIRED.
        )_REVERSE_VERIFY_MAPri   Zget_verify_modere   r   r   r   Z__get_verify_mode   s    zSSLContext.__get_verify_moderG   )r   r    c                 C  s.   ddddddddd}| j t| | dS )	zSetter for verify_mode.z_SSL.Connectionz_crypto.X509rN   r   )_connobj_x509obj_errnum	_errdepthretcoder    c                 S  s   t |S r.   )r   )rq   rr   rs   rt   ru   r   r   r   _cb   s    z)SSLContext.__set_verify_mode.<locals>._cbN)ri   Z
set_verify_VERIFY_MAP)r3   r   rv   r   r   r   Z__set_verify_mode   s    zSSLContext.__set_verify_moder   c                 C  s   | j S r.   )rk   re   r   r   r   Z__get_check_hostname   s    zSSLContext.__get_check_hostnamer   c                 C  s   t d| || _d S )Ncheck_hostname)r   rk   r3   r   r   r   r   Z__set_check_hostname   s    
zSSLContext.__set_check_hostnamezOptional[bool]c                 C  s   | j jS r.   )rj   rd   re   r   r   r   Z__get_check_ocsp_endpoint  s    z$SSLContext.__get_check_ocsp_endpointc                 C  s   t d| || j_d S )NZ
check_ocsp)r   rj   rd   ry   r   r   r   Z__set_check_ocsp_endpoint  s    
z$SSLContext.__set_check_ocsp_endpointc                 C  s   | j dS rO   )ri   set_optionsre   r   r   r   Z__get_options
  s    zSSLContext.__get_optionsc                 C  s   | j t| d S r.   )ri   rz   rN   ry   r   r   r   Z__set_options  s    zSSLContext.__set_optionsNzUnion[str, bytes]zUnion[str, bytes, None]zOptional[str])certfilekeyfilepasswordr    c                   sR    r(ddddd fdd}| j | | j | | j |p@| | j   dS )	a  Load a private key and the corresponding certificate. The certfile
        string must be the path to a single file in PEM format containing the
        certificate as well as any number of CA certificates needed to
        establish the certificate's authenticity. The keyfile string, if
        present, must point to a file containing the private key. Otherwise
        the private key will be taken from certfile as well.
        rN   r   zOptional[bytes]rI   )_max_length_prompt_twice
_user_datar    c                   s    d k	st  dS )Nzutf-8)AssertionErrorencode)r~   r   r   r}   r   r   _pwcb*  s    z)SSLContext.load_cert_chain.<locals>._pwcbN)ri   Zset_passwd_cbZuse_certificate_chain_fileZuse_privatekey_fileZcheck_privatekey)r3   r{   r|   r}   r   r   r   r   load_cert_chain  s    zSSLContext.load_cert_chain)cafilecapathr    c                 C  s6   | j || ttjds2|dk	s&tt|| j_dS )zLoad a set of "certification authority"(CA) certificates used to
        validate other peers' certificates when `~verify_mode` is other than
        ssl.CERT_NONE.
        Zget_verified_chainN)	ri   load_verify_locationshasattrrA   
Connectionr   r   rj   rc   )r3   r   r   r   r   r   r   6  s    z SSLContext.load_verify_locationsc                 C  s    t r| t  ntddS )z&Attempt to load CA certs from certifi.ztlsAllowInvalidCertificates is False but no system CA certificates could be loaded. Please install the certifi package, or provide a path to a CA file using the tlsCAFile optionN)_HAVE_CERTIFIr   certifiwhere_ConfigurationErrorre   r   r   r   _load_certifiC  s
    zSSLContext._load_certifistr)storer    c                 C  sj   | j  }|dk	sttjjj}t|D ]:\}}}|dkr*|dksL||kr*|t	j
t| q*dS )z2Attempt to load CA certs from Windows trust store.Nx509_asnT)ri   Zget_cert_storer   
_stdlibsslPurposeSERVER_AUTHoidenum_certificatesZadd_cert_cryptoZX509Zfrom_cryptographyx509Zload_der_x509_certificate)r3   r   Z
cert_storer   certencodingtrustr   r   r   _load_wincertsO  s    

zSSLContext._load_wincertsc                 C  sb   t jdkrBzdD ]}| | qW qT tk
r>   |   Y qTX nt jdkrT|   | j  dS )z7A PyOpenSSL version of load_default_certs from CPython.win32)CAROOTdarwinN)_sysplatformr   PermissionErrorr   ri   set_default_verify_paths)r3   	storenamer   r   r   load_default_certs\  s    

zSSLContext.load_default_certsc                 C  s   | j   dS )zmSpecify that the platform provided CA certificates are to be used
        for verification purposes.
        N)ri   r   re   r   r   r   r   l  s    z#SSLContext.set_default_verify_pathsFTz_socket.socketzOptional[_SSL.Session]r*   )r,   server_sidedo_handshake_on_connectr-   server_hostnamesessionr    c              
     s  t | j||}t }|r$|| |dkr6|  nD|rRt|sR||d | j	t
jkrr|d|jI dH  |  |r|d|jI dH  | jr|dk	rddlm}	 z&t|r|	|| n|	|| W n: tjtjfk
r }
 ztt|
dW 5 d}
~
X Y nX |S zZWrap an existing Python socket connection and return a TLS socket
        object.
        TidnaNr   )	pyopenssl)r*   ri   asyncioZget_running_loopset_sessionset_accept_stater$   set_tlsext_host_namer   verify_moder   	CERT_NONEZrun_in_executorrequest_ocspset_connect_staterH   rx   service_identityr   verify_ip_addressverify_hostnameSICertificateErrorSIVerificationErrorr   r   )r3   r,   r   r   r-   r   r   ssl_connZloopr   r&   r   r   r   a_wrap_sockett  s2    

 zSSLContext.a_wrap_socketc           
   
   C  s   t | j||}|r|| |dkr.|  n8|rJt|sJ||d | jtj	kr^|
  |  |r|  | jr|dk	rddlm} z&t|r||| n||| W n8 tjtjfk
r }	 ztt|	dW 5 d}	~	X Y nX |S r   )r*   ri   r   r   r$   r   r   r   r   r   r   r   rH   rx   r   r   r   r   r   r   r   r   )
r3   r,   r   r   r-   r   r   r   r   r&   r   r   r   wrap_socket  s0    

 zSSLContext.wrap_socket)NN)NN)FTTNN)FTTNN)r]   r^   r_   rf   	__slots__r2   propertyrl   Z_SSLContext__get_verify_modeZ_SSLContext__set_verify_moder   Z_SSLContext__get_check_hostnameZ_SSLContext__set_check_hostnamerx   Z$_SSLContext__get_check_ocsp_endpointZ$_SSLContext__set_check_ocsp_endpointrd   Z_SSLContext__get_optionsZ_SSLContext__set_optionsoptionsr   r   r   r   r   r   r   r   r   r   r   r   rg      sN   



          7     rg   )Vrf   
__future__r   r   socketr=   sslr   sysr   timer9   errnor   rW   	ipaddressr   r!   typingr   r   r   r   r	   r
   Zcryptography.x509r   r   ZOpenSSLr   rA   r   r   Zpymongo.errorsr   r   r   Zpymongo.ocsp_cacher   Zpymongo.ocsp_supportr   r   Zpymongo.socket_checkerr   r/   r   Zpymongo.write_concernr   r   r   r   r   ImportErrorZSSLv23_METHODPROTOCOL_SSLv23OP_NO_SSLv2OP_NO_SSLv3OP_NO_COMPRESSIONgetattrr   HAS_SNIIS_PYOPENSSLErrorr?   r   ZVERIFY_NONECERT_OPTIONALZVERIFY_PEERCERT_REQUIREDZVERIFY_FAIL_IF_NO_PEER_CERTrw   itemsrp   r$   rB   rC   ZWantX509LookupErrorr;   ZBLOCKING_IO_READ_ERRORZBLOCKING_IO_WRITE_ERRORZBLOCKING_IO_LOOKUP_ERRORr)   r   r*   ra   rg   r   r   r   r   <module>   sj    
   

M	