Ë
    #ïàjÃ9  ã                   ój  — d 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Z	ddl	m
Z
mZ 	 e
j                  ZddlZddlmZmZ ddlmZmZ dd	lmZ  G d
„ d«      Z G d„ dee«      Z G d„ dee«      Z G d„ d«      Z G d„ de¬«      Z G d„ de«      Zy# e$ r e
j                  ZY Œqw xY w# e$ r dZ
Y Œ~w xY w)aá  
A library for integrating :doc:`pyOpenSSL <pyopenssl:index>` with Cheroot.

The :py:mod:`OpenSSL <pyopenssl:OpenSSL>` module must be importable
for SSL/TLS/HTTPS functionality.
You can obtain it from `here <https://github.com/pyca/pyopenssl>`_.

To use this module, set :py:attr:`HTTPServer.ssl_adapter
<cheroot.server.HTTPServer.ssl_adapter>` to an instance of
:py:class:`ssl.Adapter <cheroot.ssl.Adapter>`.
There are two ways to use :abbr:`TLS (Transport-Level Security)`:

Method One
----------

 * :py:attr:`ssl_adapter.context
   <cheroot.ssl.pyopenssl.pyOpenSSLAdapter.context>`: an instance of
   :py:class:`SSL.Context <pyopenssl:OpenSSL.SSL.Context>`.

If this is not None, it is assumed to be an :py:class:`SSL.Context
<pyopenssl:OpenSSL.SSL.Context>` instance, and will be passed to
:py:class:`SSL.Connection <pyopenssl:OpenSSL.SSL.Connection>` on bind().
The developer is responsible for forming a valid :py:class:`Context
<pyopenssl:OpenSSL.SSL.Context>` object. This
approach is to be preferred for more flexibility, e.g. if the cert and
key are streams instead of files, or need decryption, or
:py:data:`SSL.SSLv3_METHOD <pyopenssl:OpenSSL.SSL.SSLv3_METHOD>`
is desired instead of the default :py:data:`SSL.SSLv23_METHOD
<pyopenssl:OpenSSL.SSL.SSLv3_METHOD>`, etc. Consult
the :doc:`pyOpenSSL <pyopenssl:api/ssl>` documentation for
complete options.

Method Two (shortcut)
---------------------

 * :py:attr:`ssl_adapter.certificate
   <cheroot.ssl.pyopenssl.pyOpenSSLAdapter.certificate>`: the file name
   of the server's TLS certificate.
 * :py:attr:`ssl_adapter.private_key
   <cheroot.ssl.pyopenssl.pyOpenSSLAdapter.private_key>`: the file name
   of the server's private key file.

Both are :py:data:`None` by default. If :py:attr:`ssl_adapter.context
<cheroot.ssl.pyopenssl.pyOpenSSLAdapter.context>` is :py:data:`None`,
but ``.private_key`` and ``.certificate`` are both given and valid, they
will be read, and the context will be automatically created from them.

.. spelling::

   pyopenssl
é    N)Úwarn)ÚSSLÚcryptoé   )ÚerrorsÚserver)ÚStreamReaderÚStreamWriteré   )ÚAdapterc                   óP   ‡ — e Zd ZdZdZdZd„ Zˆ fd„Zd	ˆ fd„	Zˆ fd„Z	ˆ fd„Z
ˆ xZS )
ÚSSLFileobjectMixinz#Base mixin for a TLS socket stream.é   g{®Gáz„?c                 ó¦  — t        j                   «       }	 	  ||i |¤ŽS # t        j                  $ r# t        j                  | j                  «       Y �nDt        j
                  $ r# t        j                  | j                  «       Y �nt        j                  $ rX}|r|j                  dk(  rY d}~y|j                  d   }|r|t        j                  v rY d}~yt        j                  |«      ‚d}~wt        j                  $ r’}|r|j                  dk(  rY d}~yd}t        j                  t        «      5  |j                  d   d   d   }ddd«       n# 1 sw Y   nxY w|dk(  rt        j                   ‚t        j"                  |j                  Ž ‚d}~ww xY wt        j                   «       |z
  | j$                  kD  rt        j&                  d«      ‚�Œ½)zµWrap the given call with TLS error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        )éÿÿÿÿzUnexpected EOFNó    r   r   zhttp requestz	timed out)Útimer   ÚWantReadErrorÚsleepÚ	ssl_retryÚWantWriteErrorÚSysCallErrorÚargsr   Úsocket_errors_to_ignoreÚsocketÚerrorÚErrorÚ
contextlibÚsuppressÚ
IndexErrorÚ
NoSSLErrorÚFatalSSLAlertÚssl_timeoutÚtimeout)	ÚselfÚ	is_readerÚcallr   ÚkwargsÚstartÚeÚerrnumÚthirdargs	            úD/srv/dav/.venv/lib/python3.12/site-packages/cheroot/ssl/pyopenssl.pyÚ
_safe_callzSSLFileobjectMixin._safe_callX   ss  € ô —	‘	“ˆØð4Ù˜TÐ, VÑ,Ð,øÜ×$Ñ$ò +ô —
‘
˜4Ÿ>™>×*Ü×%Ñ%ò +Ü—
‘
˜4Ÿ>™>×*Ü×#Ñ#ò +Ù §¡Ð+AÒ!AÜàŸ™ ™�Ù ¬6×+IÑ+IÑ!IÜÜ—l‘l 6Ó*Ð*ûÜ—9‘9ò 4Ù §¡Ð+AÒ!AÜà�Ü×(Ñ(¬Ó4ñ /Ø Ÿv™v a™y¨™|¨A™�H÷/÷ /ñ /úð ˜~Ò-ä ×+Ñ+Ð+ä×*Ñ*¨A¯F©FÐ3Ð3ûð4úô �y‰y‹{˜UÑ" T×%5Ñ%5Ò5Ü—n‘n [Ó1Ð1ñG sW   — Ÿ2FÁ1FÂFÂC-Â0#C-ÃC-Ã-FÄFÄFÄ4EÅ
	FÅE	Å8FÆFc                 óB   •— | j                  dt        t        | �  |«      S )z*Receive message of a size from the socket.T)r.   Úsuperr   Úrecv©r%   ÚsizeÚ	__class__s     €r-   r1   zSSLFileobjectMixin.recv„   s%   ø€ à�‰ØÜÔ$ dÑ0Øó
ð 	
r   c                 óB   •— | j                  dt        t        | �  |«      S )z¢Receive message of a size from the socket.

        Matches the following interface:
        https://docs.python.org/3/library/io.html#io.IOBase.readline
        T)r.   r0   r   Úreadliner2   s     €r-   r6   zSSLFileobjectMixin.readlineŒ   s'   ø€ ð �‰ØÜÔ$ dÑ4Øó
ð 	
r   c                 óJ   •—  | j                   dt        t        | �  g|¢­i |¤ŽS )z!Send whole message to the socket.F)r.   r0   r   Úsendall©r%   r   r(   r4   s      €r-   r8   zSSLFileobjectMixin.sendall˜   s8   ø€ àˆt�‰ØÜÔ$ dÑ3ð
ð ò
ð ñ	
ð 	
r   c                 óJ   •—  | j                   dt        t        | �  g|¢­i |¤ŽS )z(Send some part of message to the socket.F)r.   r0   r   Úsendr9   s      €r-   r;   zSSLFileobjectMixin.send¡   s8   ø€ àˆt�‰ØÜÔ$ dÑ0ð
ð ò
ð ñ	
ð 	
r   )r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r#   r   r.   r1   r6   r8   r;   Ú__classcell__©r4   s   @r-   r   r   Q   s/   ø„ Ù-à€KØ€Iò*2ôX
õ

ô
÷
ð 
r   r   c                   ó   — e Zd ZdZy)ÚSSLFileobjectStreamReaderú,SSL file object attached to a socket object.N©r<   r=   r>   r?   © r   r-   rC   rC   «   ó   „ Ú6r   rC   c                   ó   — e Zd ZdZy)ÚSSLFileobjectStreamWriterrD   NrE   rF   r   r-   rI   rI   ¯   rG   r   rI   c                   ó   — e Zd ZdZd„ Zy)ÚSSLConnectionProxyMetaz2Metaclass for generating a bunch of proxy methods.c                 ó–   ‡
— d}dŠ
d}ˆ
fd„}|D ]  } ||«      ||<   |||   _         Œ d„ }|D ]  }	 ||	«      ||	<   Œ t        |||«      S )z.Attach a list of proxy methods to a new class.)"Úget_contextÚpendingr;   Úwriter1   ÚreadÚrenegotiateÚbindÚlistenÚconnectÚacceptÚsetblockingÚfilenoÚcloseÚget_cipher_listÚgetpeernameÚgetsocknameÚ
getsockoptÚ
setsockoptÚmakefileÚget_app_dataÚset_app_dataÚstate_stringÚsock_shutdownÚget_peer_certificateÚ	want_readÚ
want_writeÚset_connect_stateÚset_accept_stateÚ
connect_exr8   Ú
settimeoutÚ
gettimeoutÚshutdown)rk   )Úfamilyc                 ó   •‡ — ˆ ˆfd„}|S )ú&Create a proxy method for a new class.c                 óô   •— | j                   j                  «        	 ‰‰vr|d d  ng } t        | j                  ‰«      |Ž | j                   j	                  «        S # | j                   j	                  «        w xY w©N)Ú_lockÚacquireÚgetattrÚ	_ssl_connÚrelease)r%   r   Únew_argsÚmethodÚproxy_methods_no_argss      €€r-   Úproxy_wrapperzMSSLConnectionProxyMeta.__new__.<locals>.lock_decorator.<locals>.proxy_wrapperã   sf   ø€ Ø—
‘
×"Ñ"Ô$ð)à#)Ð1FÑ#F˜™Q™ÈBð ð ;œ7 4§>¡>°6Ó:¸HÐEà—J‘J×&Ñ&Õ(ø�D—J‘J×&Ñ&Õ(ús   �#A ÁA7rF   )rw   ry   rx   s   ` €r-   Úlock_decoratorz6SSLConnectionProxyMeta.__new__.<locals>.lock_decoratorà   s   ù€ õ)ð !Ð r   c                 ó2   ‡ — ˆ fd„}‰ |_         t        |«      S )rn   c                 ó0   •— t        | j                  ‰«      S rp   )rs   rt   )r%   Ú	property_s    €r-   Úproxy_prop_wrapperzQSSLConnectionProxyMeta.__new__.<locals>.make_property.<locals>.proxy_prop_wrapperö   s   ø€ Ü˜tŸ~™~¨yÓ9Ð9r   )r<   Úproperty)r}   r~   s   ` r-   Úmake_propertyz5SSLConnectionProxyMeta.__new__.<locals>.make_propertyó   s   ø€ ô:ð +4ÐÔ'ÜÐ.Ó/Ð/r   )r<   Útype)ÚmclÚnameÚbasesÚnmspcÚproxy_methodsÚproxy_propsrz   Úmr€   Úprx   s             @r-   Ú__new__zSSLConnectionProxyMeta.__new__¶   s}   ø€ ð#
ˆðH !.Ðà!ˆô	!ð ò 	"ˆAÙ% aÓ(ˆE�!‰HØ !ˆE�!‰HÕð	"ò	0ð ò 	(ˆAÙ$ QÓ'ˆE�!ŠHð	(ô
 �D˜% Ó'Ð'r   N)r<   r=   r>   r?   rŠ   rF   r   r-   rK   rK   ³   s   „ Ù<óK(r   rK   c                   ó   — e Zd ZdZd„ Zy)ÚSSLConnectionzêA thread-safe wrapper for an ``SSL.Connection``.

    :param tuple args: the arguments to create the wrapped \
                        :py:class:`SSL.Connection(*args) \
                        <pyopenssl:OpenSSL.SSL.Connection>`
    c                 ód   — t        j                  |Ž | _        t        j                  «       | _        y)z"Initialize SSLConnection instance.N)r   Ú
Connectionrt   Ú	threadingÚRLockrq   )r%   r   s     r-   Ú__init__zSSLConnection.__init__  s    € äŸ™¨Ð.ˆŒÜ—_‘_Ó&ˆ�
r   N)r<   r=   r>   r?   r‘   rF   r   r-   rŒ   rŒ     s   „ ñó'r   rŒ   )Ú	metaclassc                   óx   ‡ — e Zd ZdZdZ	 dZ	 dZ	 dZ	 dZ	 dZ		 	 	 dddœˆ fd„Z
d„ Zd„ Zd„ Zd„ Zd	„ Zdd
„Zˆ xZS )ÚpyOpenSSLAdapterz=A wrapper for integrating :doc:`pyOpenSSL <pyopenssl:index>`.N©Úprivate_key_passwordc                óf   •— t         €t        d«      ‚t        t        | �  |||||¬«       d| _        y)z$Initialize OpenSSL Adapter instance.Nz(You must install pyOpenSSL to use HTTPS.r•   )r   ÚImportErrorr0   r”   r‘   Ú_environ)r%   ÚcertificateÚprivate_keyÚcertificate_chainÚciphersr–   r4   s         €r-   r‘   zpyOpenSSLAdapter.__init__,  sC   ø€ ô ˆ;ÜÐHÓIÐIäÔ Ñ.ØØØØØ!5ð 	/ô 	
ð ˆ�r   c                 óž   — | j                   €| j                  «       | _         t        | j                   |«      }| j                  «       | _        |S )z!Wrap and return the given socket.)ÚcontextrM   rŒ   Úget_environr™   )r%   ÚsockÚconns      r-   rR   zpyOpenSSLAdapter.bindC  sA   € à�<‰<ÐØ×+Ñ+Ó-ˆDŒLÜ˜TŸ\™\¨4Ó0ˆØ×(Ñ(Ó*ˆŒØˆr   c                 ó:   — || j                   j                  «       fS )z<Wrap and return the given socket, plus WSGI environ entries.)r™   Úcopy)r%   r¡   s     r-   ÚwrapzpyOpenSSLAdapter.wrapK  s   € ð
 �T—]‘]×'Ñ'Ó)Ð)Ð)r   c                óÄ   — d}t        |t        «      r|j                  d«      }nt        |t        «      r|}t	        |«      }||kD  rt        d|› d|› d�t        d¬«       |S )z4Pass a passphrase to password protected private key.r   zutf-8zUser-provided password is zB bytes long and will be truncated since it exceeds the maximum of ú.r   )Ú
stacklevel)Ú
isinstanceÚstrÚencodeÚbytesÚlenÚ_warnÚUserWarning)r%   Úpassword_max_lengthÚ_verify_twiceÚpasswordÚ
b_passwordÚpassword_lengths         r-   Ú_password_callbackz#pyOpenSSLAdapter._password_callbackR  su   € ð ˆ
Ü�h¤Ô$Ø!Ÿ™¨Ó1‰JÜ˜¤%Ô(Ø!ˆJä˜j›/ˆØÐ0Ò0ÜØ,¨_Ð,=ð >@Ø@SÐ?TÐTUðWäØõ	ð Ðr   c                 óR  — t        j                  t         j                  «      }|j                  | j                  | j
                  «       |j                  | j                  «       | j                  r|j                  | j                  «       |j                  | j                  «       |S )z~Return an ``SSL.Context`` from self attributes.

        Ref: :py:class:`SSL.Context <pyopenssl:OpenSSL.SSL.Context>`
        )r   ÚContextÚSSLv23_METHODÚset_passwd_cbrµ   r–   Úuse_privatekey_filer›   rœ   Úload_verify_locationsÚuse_certificate_filerš   )r%   Úcs     r-   rM   zpyOpenSSLAdapter.get_contextk  s|   € ô �K‰Kœ×)Ñ)Ó*ˆØ	�‰˜×/Ñ/°×1JÑ1JÔKØ	×Ñ˜d×.Ñ.Ô/Ø×!Ò!Ø×#Ñ# D×$:Ñ$:Ô;Ø	×Ñ˜t×/Ñ/Ô0Øˆr   c           	      ó–  — ddt         j                  j                  ›dt        j                  j                  ›dt        j                  j
                  ›dt        j                  ›�t        j                  t        j                  «      j                  «       dœ}| j                  �rt        | j                  d«      5 }t        j                  t        j                  |j!                  «       «      }ddd«       |j#                  j%                  «       |j'                  «       d	œ«       d
|j)                  «       fd|j+                  «       ffD ]p  \  }}t-        |«      dd }d|z  }|||<   |sŒ!|j/                  d«      }|d| ||dz   d }	}|j/                  d«      }|d| ||dz   d }
}|
r|	rd|›d|
›�}|	||<   |rŒPŒr |S # 1 sw Y   ŒÒxY w)z;Return WSGI environ entries to be merged into each request.ÚhttpsÚonú ú/z Python/)zwsgi.url_schemeÚHTTPSÚSSL_VERSION_INTERFACEÚSSL_VERSION_LIBRARYÚrbN)ÚSSL_SERVER_M_VERSIONÚSSL_SERVER_M_SERIALÚIÚSé   éþÿÿÿzSSL_SERVER_%s_DNú=r   ÚSSL_SERVER_Ú_DN_)Úcheroot_serverÚ
HTTPServerÚversionÚOpenSSLÚ	__title__Ú__version__Úsysr   ÚSSLeay_versionÚSSLEAY_VERSIONÚdecoderš   Úopenr   Úload_certificateÚFILETYPE_PEMrP   ÚupdateÚget_versionÚget_serial_numberÚ
get_issuerÚget_subjectrª   Úrfind)r%   Ússl_environÚ	cert_fileÚcertÚprefixÚdnÚdnstrÚwsgikeyÚposÚvalueÚkeys              r-   r    zpyOpenSSLAdapter.get_environy  sÂ  € ð  'Øô ×)Ñ)×1Ó1Ü—‘×)Ó)Ü—‘×+Ó+Ü—’ð&ô $'×#5Ñ#5Ü×"Ñ"ó$ç‰f‹hñ
ˆð ×Óä�d×&Ñ&¨Ó-ð °Ü×.Ñ.Ü×'Ñ'Ø—N‘NÓ$ó�÷ð ×Ñà,0×,<Ñ,<Ó,>Ø+/×+AÑ+AÓ+Cñô	ð �d—o‘oÓ'Ð(Ø�d×&Ñ&Ó(Ð)ðò 5‘
�˜ô ˜B›  2˜�à,¨vÑ5�Ø',�˜GÑ$ò ØŸ+™+ cÓ*�CØ#(¨¨# ;°°c¸A±g°iÐ0@˜5�EØŸ+™+ cÓ*�CØ!& t¨ ¨e°C¸!±G°IÐ.>˜3�EÙšuÚ;AÁ3Ð"G˜Ø/4˜ GÑ,ó ð5ð. Ð÷Qð ús   Â;3F?Æ?Gc                 ó¾   — d|v rt         nt        }t        r1t        |t        «      r! ||||«      }|j                  «       |_        |S t        j                  |||«      S )zReturn socket file object.Úr)	rC   rI   r   r©   Ússl_conn_typerj   r#   rÐ   ÚCP_fileobject)r%   r¡   ÚmodeÚbufsizeÚclsÚwrapped_sockets         r-   r^   zpyOpenSSLAdapter.makefile¶  s`   € ð �d‰{õ &ä*ð 	õ
 ”:˜d¤MÔ2Ù   t¨WÓ5ˆNØ)-¯©Ó):ˆNÔ&Ø!Ð!ô ×+Ñ+¨D°$¸Ó@Ð@r   )NN)rî   r   )r<   r=   r>   r?   rš   r›   rœ   rŸ   r�   r–   r‘   rR   r¥   rµ   rM   r    r^   r@   rA   s   @r-   r”   r”     sw   ø„ ÙGà€KØ8à€KØ9àÐð>ð
 €Gðð €GØ"àÐØAð Øðð "öò.ò*òò2ò;÷zAr   r”   ) r?   r   rÖ   r�   r   Úwarningsr   r®   ÚOpenSSL.versionrÓ   r   r   rŽ   rï   ÚAttributeErrorÚConnectionTyper˜   r   Ú r   r   rÐ   r^   r	   r
   r   r   rC   rI   rK   rŒ   r”   rF   r   r-   ú<module>rú      sÌ   ðñ2óh Û 
Û Û Ý "ð	Ûß#ð+ØŸ™ˆó ÷÷ 2Ý ÷W
ñ W
ôt7Ð 2°Lô 7ô7Ð 2°Lô 7÷N(ñ N(ôb'Ð4õ 'ôqA�wõ qAøða ò +Ø×*Ñ*Šð+ûàò Ø
‚Cðús.   šB( §B ÂB%Â"B( Â$B%Â%B( Â(B2Â1B2