a
    mzfV                  
   @   s:  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	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mZmZ ddlmZmZmZ ddlmZmZmZ ddlmZmZ ddlmZm Z m!Z!m"Z"m#Z# dd	l$m%Z% e&e'd
Z(eode)dv Z*ej+,dZ-ej./ej.j0,dZ1ej2dd dkZ3ej4ej.j5ej6ej.j7ej8ej.j7ej.j9 iZ:ej;j<e#d ddZ=G dd de%Z>dd Z?ej@dd ZAej@dd ZBej@dd ZCej@dd ZDej@dd  ZEej@d!d" ZFd#d$ ZGej@d%d& ZHej;Id'd(d)d* ZJej;Id'd(ej;Id+d,ej;Id-ej4ej6ej8fej;jKeoTed.d/d0d1d2 ZLej;Id'ejMd3ej;jKeoe3d4d/d0d5d6fej;Id7ej4d/fej4d8fej6d/fej6d8fej8d8ffd9d: ZNej;Id;ee fd<d= ZOej;Id'd(ej;Id;eejMe e=d5fej;jPd>dd?d@dA ZQdS )BzTests for TLS support.    N   )btonntobntou)IS_ABOVE_OPENSSL10IS_CIIS_PYPY)IS_LINUXIS_MACOS
IS_WINDOWS)
HTTPServerget_ssl_adapter_class)ANY_INTERFACE_IPV4ANY_INTERFACE_IPV6EPHEMERAL_PORT_get_conn_data_probe_ipv6_sock)
Gateway_10ZGITHUB_WORKFLOWs(   Microsoft Windows Server 2016 Datacenter)Z
systeminfoZLibreSSLs   OpenSSL 1.0.)   
   z::1zYIPv6 is disabled (for example, under Travis CI which runs under GCE supporting only IPv4))reasonc                       s    e Zd ZdZ fddZ  ZS )HelloWorldGatewayz0Gateway responding with Hello World to root URI.c                    s   | j }t|j}|dkr4d|_|  |d dS |dkrd|_|  |  }|d |d t| |t	
|d dS tt|  S )	z$Respond with dummy content via HTTP./s   200 OKs   Hello world!N/envzwsgi.errorsz
wsgi.inpututf-8)reqr   uristatusZensure_headers_sentwriteZget_environpopprintjsondumpsencodesuperr   respond)selfr   Zreq_urienv	__class__ C/var/www/media/lib/python3.9/site-packages/cheroot/test/test_ssl.pyr%   F   s"    



zHelloWorldGateway.respond)__name__
__module____qualname____doc__r%   __classcell__r*   r*   r(   r+   r   C   s   r   c                 C   sF   t | td}||_tj|jd  |js6t	d q$|
|j |S )z7Create and start an HTTP server bound to ``bind_addr``.)	bind_addrZgateway)targetg?)r   r   ssl_adapter	threadingThreadZ
safe_startstartreadytimesleepZaddfinalizerstop)r1   r3   request
httpserverr*   r*   r+   make_tls_http_server\   s    r=   c                 C   s   t jt| dS )z(Provision a server creator as a fixture.r;   )	functoolspartialr=   r>   r*   r*   r+   tls_http_servero   s    rA   c                   C   s   t  S )z,Provide a certificate authority via fixture.)trustmeCAr*   r*   r*   r+   cau   s    rD   c                 c   s4   | j  }|V  W d   n1 s&0    Y  dS )z=Provide a certificate authority certificate file via fixture.N)cert_pemtempfile)rD   Zca_cert_pemr*   r*   r+   tls_ca_certificate_pem_path{   s    rG   c                 C   s   t t\}}}| t|S )z'Provide a leaf certificate via fixture.)r   r   
issue_certr   )rD   	interface_hostZ_portr*   r*   r+   tls_certificate   s    rK   c                 c   s4   | j  }|V  W d   n1 s&0    Y  dS )z6Provide a certificate chain PEM file path via fixture.N)private_key_and_cert_chain_pemrF   )rK   rE   r*   r*   r+   tls_certificate_chain_pem_path   s    rM   c                 c   s4   | j  }|V  W d   n1 s&0    Y  dS )z<Provide a certificate private key PEM file path via fixture.N)Zprivate_key_pemrF   )rK   Zcert_key_pemr*   r*   r+   $tls_certificate_private_key_pem_path   s    rN   c                 C   sB   t |jtrdS | |jt|jdt|j|j|j	f dS )z@Append uncaught exception ``args`` in threads to ``exceptions``.N )

issubclassexc_type
SystemExitappendstr	exc_valuejoin	tracebackformat_exceptionexc_traceback)
exceptionsargsr*   r*   r+   _thread_except_hook   s    r\   c                  c   sT   g } t tdd}|dur&tt| t_z| V  W |durP|t_n|durN|t_0 dS )zProvide a list of uncaught exceptions from threads via a fixture.

    Only catches exceptions on Python 3.8+.
    The list contains: ``(type, str(value), str(traceback))``
    
excepthookN)getattrr4   r?   r@   r\   r]   )rZ   Z	orig_hookr*   r*   r+   thread_exceptions   s    r_   adapter_type)builtin	pyopensslc                 C   s   t t\}}}	t|d}
|
||}|dkr4| |_||j |||	f|}t |j\}}}	tjdj	||	d| |d}|j
dksJ |jdksJ dS )	z;Test ability to connect to server via HTTPS using adapters.namerb   https://{host!s}:{port!s}/hostport)timeoutverify   Hello world!N)r   r   r   get_contextcontextconfigure_certr1   requestsgetformatstatus_codetext)http_request_timeoutrA   r`   rK   rM   rN   rG   rI   rJ   rh   tls_adapter_clstls_adaptertlshttpserverrespr*   r*   r+   test_ssl_adapters   s&    


rz   )is_trusted_certtls_client_identity))T	localhost)T	127.0.0.1)Tz*.localhost)TZnot_localhost)Fr}   tls_verify_modez)Fails under PyPy in CI for unknown reasonF)r   strictc              	      s^  |t jko|	 }tt\}}}|	r&|nt }|jjdt|
d  |	t
|
}~W d   n1 sh0    Y  |j }t|d}|||}|dkr| |_|jt| dd  n||j_||j ||j |||f|}t|j\}}}tjtjdj||d	| ||d
}|s| }|jdk}|sntrn|dkrn|t jkrn|
dkrn|	rntd |sxJ |j dksJ |!  W d   dS t"o|dko|t jk}|rtd tj#j$f}t%st&r|tj#j'f7 }t(|}| !  W d   n1 s0    Y  z|j)j*d j+j*d j*d  W n. t,yp   t%s^t&rjt-|j) n Y n0 t. t/rt-|j) t0rdndf}t"rt1r|dkrd}|t jt j2fv r|	s|
dkr|t%rdnt&rt3rdnd7 }t4r|d7 }t&rt%rt4r|d7 }t5 fdd|D s:J W d   n1 sP0    Y  dS )z8Verify that client TLS certificate auth works correctly.idna.core.ulabelZreturn_valueNrc   rb   c                 S   s   |S Nr*   conncerterrnodepthZpreverify_okr*   r*   r+   <lambda>-      z&test_tls_client_auth.<locals>.<lambda>re   rf   ri   rj   r   rk   ra   r}   z4OpenSSL 1.0 has problems with verifying client certsrl   zTest sometimes failsr   zsslv3 alert bad certificatetlsv1 alert unknown ca)r   )z3bad handshake: SysCallError(10054, 'WSAECONNRESET')z<('Connection aborted.', OSError("(10054, 'WSAECONNRESET')"))z=('Connection aborted.', OSError("(10054, 'WSAECONNRESET')",))z;('Connection aborted.', error("(10054, 'WSAECONNRESET')",))z('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))zf('Connection aborted.', error(10054, 'An existing connection was forcibly closed by the remote host')))z7('Connection aborted.', OSError("(104, 'ECONNRESET')"))z8('Connection aborted.', OSError("(104, 'ECONNRESET')",))z6('Connection aborted.', error("(104, 'ECONNRESET')",))zN('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))z?('Connection aborted.', error(104, 'Connection reset by peer')))z;('Connection aborted.', BrokenPipeError(32, 'Broken pipe')))zGSSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:)z\('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))c                 3   s   | ]}| v V  qd S r   r*   ).0eerr_textr*   r+   	<genexpr>  r   z'test_tls_client_auth.<locals>.<genexpr>)6ssl	CERT_NONEr   r   rB   rC   mock_modulepatchr   rH   r   rL   rF   r   rm   rn   
set_verify_stdlib_to_openssl_verifyverify_modeconfigure_trustro   r1   r?   r@   rp   rq   rr   rs   IS_PYOPENSSL_SSL_VERSION_1_0CERT_REQUIREDpytestxfailrt   closer
   rZ   SSLErrorr   IS_GITHUB_ACTIONS_WORKFLOWConnectionErrorraisesvaluer[   r   AttributeErrorrT   
isinstanceintIS_LIBRESSL_BACKENDr   CERT_OPTIONALr	   
PY310_PLUSany)ru   mockerrA   r`   rD   rK   rM   rN   rG   r{   r|   r   Ztest_cert_rejectionrI   rJ   rh   Zclient_cert_root_caclient_certcl_pemrv   rw   rx   Zmake_https_requestry   Zis_req_successfulZ	issue_237Zexpected_ssl_errorsssl_errZexpected_substringsr*   r   r+   test_tls_client_auth   s    +
 





*

$r   ra   zGUnclosed TLS resource warnings happen on macOS under Python 3.10 (#508))Zmarksrb   )r   use_client_certTc              	   C   s  t t\}}}|jjdtdd |td}W d   n1 sF0    Y  |j }t	|d}||	|
}|dkr|
 |_|jt| dd  n||j_||j ||j |||f|}t |j\}}}tjd	| d
 t| d |||r|ndd}t|jd}|d dks.J |d dks@J dD ]}||v sDJ qD|dkrtW d   dS dD ]}||v sxJ qx|tjks|s|d dks"J nn|d dksJ t|d&}|d | v sJ W d   n1 s0    Y  dD ]}||v sJ qW d   n1 s80    Y  trLdS |D ]J}t|jt sfqPt|j!}d|v rt"#d$d|f t"%| qP| D ]\}}}t&|t'j(d q| rJ d$| d d j)| d d  fdS )!z7Test the SSL environment generated by the SSL adapters.r   r~   r   Nrc   rb   c                 S   s   |S r   r*   r   r*   r*   r+   r     r   ztest_ssl_env.<locals>.<lambda>zhttps://:r   r   r   zwsgi.url_schemehttpsHTTPSon>   ZSSL_VERSION_INTERFACEZSSL_VERSION_LIBRARY>   ZSSL_PROTOCOLZ
SSL_CIPHERZSSL_CLIENT_VERIFYNONESUCCESSrtZSSL_CLIENT_CERT>   ZSSL_CLIENT_M_SERIALZSSL_CLIENT_I_DNZSSL_CLIENT_M_VERSIONZSSL_CLIENT_S_DNzsocket.socket
zASometimes this test fails due to a socket.socket ResourceWarning:)filez: r      )*r   r   r   r   r   rH   r   rL   rF   r   rm   rn   r   r   r   r   ro   r1   rp   rq   rT   r!   loadscontentdecoder   r   openreadr   rP   categoryResourceWarningmessager   r   rV   Zfailr    sysstderrr,   )r_   Zrecwarnr   ru   rA   r`   rD   r   rK   rM   rN   rG   r   rI   rJ   rh   r   r   rv   rw   Ztlswsgiserverry   r'   keyfwarnmsg_tracer*   r*   r+   test_ssl_env  s    &,


62


r   ip_addrc                 C   s   |  |tf}t|j\}}}ttj.}tj	
dj||ddd W d   n1 s^0    Y  trpdnd}||jjd v sJ dS )	z:Ensure that connecting over HTTPS to HTTP port is handled.z{interface}:{port})rI   rh   GETr   Nzwrong version numberzunknown protocol)sendr   r   r1   r   r   r   r   httpclientHTTPSConnectionrr   r;   r   r   r[   )Zhttp_serverr   r<   rI   rJ   rh   r   Zexpected_substringr*   r*   r+   test_https_over_http_errorE  s    	"r   r   )ZrerunsZreruns_delayc                 C   s  t o
|dk}|rtd t|d}	|	||}
|dkr@|
 |
_||
j t|\}}}|||f|
}t|j\}}}|}|t	u rdj
f i t }|dk}|rtjdj
||d| d}|jd	ksJ |jd
ksJ dS ttjj(}tjdj
||d| d W d   n1 s0    Y  tr0d\}}t r>d\}}trLd\}}|jjd jd }t|}|j|ksJ dj
f i t ||v sJ dS )z:Ensure that connecting over HTTP to HTTPS port is handled.ra   zTest fails in Travis-CIrc   rb   z[{fqdn}]zhttp://{host!s}:{port!s}/rf   )ri   i  zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.N)h   Connection reset by peer)6   r   )iF'  z=An existing connection was forcibly closed by the remote hostr   r   z,The underlying error is {underlying_error!r})r
   r   r   r   rm   rn   ro   r   r1   r   rr   localsrp   rq   rs   rt   r   rZ   r   r	   r   r   r[   rT   r   )ru   rA   r`   rD   r   rK   rM   rN   Z	issue_225rv   rw   rI   rJ   rh   rx   ZfqdnZ(expect_fallback_response_over_plain_httpry   r   Zexpected_error_codeZexpected_error_textZunderlying_errorr   r*   r*   r+   test_http_over_https_error^  sf    



&r   )Rr/   r?   r!   osr   
subprocessr   r4   r8   rW   http.clientr   ZOpenSSL.SSLZOpenSSLr   rp   rB   _compatr   r   r   r   r   r   r	   r
   r   serverr   r   Ztestingr   r   r   r   r   Zwsgir   boolgetenvr   check_outputZ
IS_WIN2016OPENSSL_VERSION
startswithr   ZSSLZSSLeay_versionZSSLEAY_VERSIONr   version_infor   r   ZVERIFY_NONEr   ZVERIFY_PEERr   ZVERIFY_FAIL_IF_NO_PEER_CERTr   markZskipifZmissing_ipv6r   r=   ZfixturerA   rD   rG   rK   rM   rN   r\   r_   Zparametrizerz   r   r   paramr   r   Zflakyr   r*   r*   r*   r+   <module>   s   

	







& 3	
u
