U
    d@                     @  s2  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mZ ddlmZ ddlmZmZmZmZmZmZ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% ddl&m'Z( ddl&m)Z* ddl+m,Z- ddl+m.Z. ddl/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z6 ddl4m7Z7 ddl8m9Z9 er6ddlm:Z: ddlm;Z; edZ<zddl=Z=dZ>W n e?k
rh   dZ>Y nX ej@ZAejBZBejCZCejDZDeEeddZFdZGdZHejIZJejKejLejMejNejOejNejPB iZQdd eQR D ZSdddd d!ZTejUejVejWfZXd"dd#d$d%ZYG d&d' d'ejZZ[G d(d) d)Z\G d*d+ d+Z]dS ),zMA CPython compatible SSLContext implementation wrapping PyOpenSSL's
context.
    )annotationsN)EINTR)
ip_address)TYPE_CHECKINGAnyCallableListOptionalTypeVarUnion)load_der_x509_certificate)SSL)crypto)CertificateError)VerificationError)verify_hostname)verify_ip_address)ConfigurationError)_CertificateError)
_OCSPCache)_load_trusted_ca_certs_ocsp_callback)SocketChecker)_errno_from_exception)validate_boolean)
VerifyMode)Certificate_TTFOP_NO_RENEGOTIATIONc                 C  s   i | ]\}}||qS  r   ).0keyvaluer   r   =/tmp/pip-unpacked-wheel-oblwsawz/pymongo/pyopenssl_context.py
<dictcomp>P   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_addressU   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    r0   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_checkerr4   super__init__)selfr2   r3   r4   	__class__r   r#   r9   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rd|r\t | |kr\tdtdt|t	j
rzd}d}nt|t	jrd}d}nd}d}| j| ||| |rt | |krt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WantWriteErrorr7   select)	r:   r=   r/   r>   rE   startr-   Z	want_readZ
want_writer   r   r#   _callr   s,    

z_sslConn._callNone)r/   r>   r'   c                   s   | j t jf||S r5   )rM   r8   do_handshake)r:   r/   r>   r;   r   r#   rO      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    )rM   r8   recvrH   SysCallErrorr4   r0   r:   r/   r>   r-   r;   r   r#   rR      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   )rM   r8   	recv_intorH   rS   r4   r0   rT   r;   r   r#   rW      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lenrM   r8   sendOSErrorr   _EINTR)r:   rX   rY   viewtotal_length
total_sentsentr-   r;   r   r#   sendall   s    z_sslConn.sendall)r   )
__name__
__module____qualname__r9   rM   rO   rR   rW   rc   __classcell__r   r   r;   r#   r1   j   s   		r1   c                   @  s   e Zd ZdZddddZdS )_CallbackDataz0Data class which is passed to the OCSP callback.rN   r'   c                 C  s   d | _ d | _t | _d S r5   )trusted_ca_certscheck_ocsp_endpointr   Zocsp_response_cacher:   r   r   r#   r9      s    z_CallbackData.__init__N)rd   re   rf   __doc__r9   r   r   r   r#   rh      s   rh   c                	   @  sT  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d S )?
SSLContextzUA CPython compatible SSLContext implementation wrapping PyOpenSSL's
    context.
    )	_protocol_ctx_callback_data_check_hostnamerU   )protocolc                 C  s@   || _ t| j | _t | _d| _d| j_| jjt	| jd d S )NT)callbackdata)
ro   rH   Contextrp   rh   rq   rr   rk   Zset_ocsp_client_callbackr   )r:   rs   r   r   r#   r9      s    zSSLContext.__init__ri   c                 C  s   | j S )zhThe protocol version chosen when constructing the context.
        This attribute is read-only.
        )ro   rl   r   r   r#   rs      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_MAPrp   Zget_verify_moderl   r   r   r#   Z__get_verify_mode   s    zSSLContext.__get_verify_moderN   )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.X509rU   r%   )connobjx509objerrnumerrdepthretcoder'   c                 S  s   t |S r5   )r%   )rx   ry   rz   r{   r|   r   r   r#   _cb   s    z)SSLContext.__set_verify_mode.<locals>._cbN)rp   Z
set_verify_VERIFY_MAP)r:   r"   r}   r   r   r#   Z__set_verify_mode   s    zSSLContext.__set_verify_moder%   c                 C  s   | j S r5   )rr   rl   r   r   r#   Z__get_check_hostname   s    zSSLContext.__get_check_hostnamer   c                 C  s   t d| || _d S )Ncheck_hostname)r   rr   r:   r"   r   r   r#   Z__set_check_hostname   s    
zSSLContext.__set_check_hostnamezOptional[bool]c                 C  s   | j jS r5   )rq   rk   rl   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   rq   rk   r   r   r   r#   Z__set_check_ocsp_endpoint  s    
z$SSLContext.__set_check_ocsp_endpointc                 C  s   | j dS rV   )rp   set_optionsrl   r   r   r#   Z__get_options
  s    zSSLContext.__get_optionsc                 C  s   | j t| d S r5   )rp   r   rU   r   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.
        rU   r%   rP   )
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)rp   Zset_passwd_cbZuse_certificate_chain_fileZuse_privatekey_fileZcheck_privatekey)r:   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)	rp   load_verify_locationshasattrrH   
Connectionr   r   rq   rj   )r:   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_ConfigurationErrorrl   r   r   r#   _load_certifiC  s
    zSSLContext._load_certifistr)storer'   c                 C  s\   | j  }tjjj}t|D ]8\}}}|dkr|dks@||kr|tj	
t| qdS )z2Attempt to load CA certs from Windows trust store.x509_asnTN)rp   Zget_cert_store
_stdlibsslPurposeSERVER_AUTHoidenum_certificatesZadd_cert_cryptoZX509Zfrom_cryptography_load_der_x509_certificate)r:   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   rp   set_default_verify_paths)r:   	storenamer   r   r#   load_default_certsZ  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)rp   r   rl   r   r   r#   r   j  s    z#SSLContext.set_default_verify_pathsFTz_socket.socketzOptional[_SSL.Session]r1   )r3   server_sidedo_handshake_on_connectr4   server_hostnamesessionr'   c           	   
   C  s   t | j||}|r|| |dkr.|  n8|rJt|sJ||d | jtj	kr^|
  |  |r|  | jr|dk	rz"t|rt|| n
t|| W n2 ttfk
r } ztt|W 5 d}~X Y nX |S )zZWrap an existing Python socket connection and return a TLS socket
        object.
        TidnaN)r1   rp   Zset_sessionZset_accept_stater+   Zset_tlsext_host_namer   verify_moder   	CERT_NONEZrequest_ocspZset_connect_staterO   r   _verify_ip_address_verify_hostname_SICertificateError_SIVerificationErrorr   r   )	r:   r3   r   r   r4   r   r   Zssl_connr-   r   r   r#   wrap_socketr  s(    

zSSLContext.wrap_socket)NN)NN)FTTNN)rd   re   rf   rm   	__slots__r9   propertyrs   Z_SSLContext__get_verify_modeZ_SSLContext__set_verify_moder   Z_SSLContext__get_check_hostnameZ_SSLContext__set_check_hostnamer   Z$_SSLContext__get_check_ocsp_endpointZ$_SSLContext__set_check_ocsp_endpointrk   Z_SSLContext__get_optionsZ_SSLContext__set_optionsoptionsr   r   r   r   r   r   r   r   r   r   r#   rn      sB   



          rn   )^rm   
__future__r   socketrD   sslr   sysr   timer@   errnor   r^   	ipaddressr   r(   typingr   r   r   r   r	   r
   r   Zcryptography.x509r   r   ZOpenSSLr   rH   r   r   Zservice_identityr   r   r   r   Zservice_identity.pyopensslr   r   r   r   Zpymongo.errorsr   r   r   Zpymongo.ocsp_cacher   Zpymongo.ocsp_supportr   r   Zpymongo.socket_checkerr   r6   r   Zpymongo.write_concernr   r   r   r   r   r   ImportErrorZSSLv23_METHODPROTOCOL_SSLv23OP_NO_SSLv2OP_NO_SSLv3OP_NO_COMPRESSIONgetattrr   HAS_SNIIS_PYOPENSSLErrorrF   r   ZVERIFY_NONECERT_OPTIONALZVERIFY_PEERCERT_REQUIREDZVERIFY_FAIL_IF_NO_PEER_CERTr~   itemsrw   r+   rI   rJ   ZWantX509LookupErrorrB   r0   r   r1   rh   rn   r   r   r   r#   <module>   sj   $
   

M	