U
    ÓZjT+  ã                   @   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	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 e e¡ZejZG d
d„ deƒZddedfdd„Zddd„Zdd„ Zdd„ Zddd„Ze
jfdd„Z dS ) zCrypto utilities.é    N)Úcrypto)ÚSSL)Úerrors)ÚCallable)ÚOptional)ÚTuple)ÚUnionc                   @   sD   e Zd ZdZefdd„Zdd„ Zdd„ ZG dd	„ d	eƒZ	d
d„ Z
dS )Ú	SSLSocketzëSSL wrapper for sockets.

    :ivar socket sock: Original wrapped socket.
    :ivar dict certs: Mapping from domain names (`bytes`) to
        `OpenSSL.crypto.X509`.
    :ivar method: See `OpenSSL.SSL.Context` for allowed values.

    c                 C   s   || _ || _|| _d S ©N)ÚsockÚcertsÚmethod)Úselfr   r   r   © r   úS/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/acme/crypto_util.pyÚ__init__(   s    zSSLSocket.__init__c                 C   s   t | j|ƒS r
   )Úgetattrr   ©r   Únamer   r   r   Ú__getattr__-   s    zSSLSocket.__getattr__c                 C   s„   |  ¡ }z| j| \}}W n" tk
r<   t d|¡ Y dS X t | j¡}| tj	¡ | tj
¡ | |¡ | |¡ | |¡ dS )a�  SNI certificate callback.

        This method will set a new OpenSSL context object for this
        connection when an incoming connection provides an SNI name
        (in order to serve the appropriate certificate, if any).

        :param connection: The TLS connection object on which the SNI
            extension was received.
        :type connection: :class:`OpenSSL.Connection`

        z-Server name (%s) not recognized, dropping SSLN)Zget_servernamer   ÚKeyErrorÚloggerÚdebugr   ÚContextr   Úset_optionsÚOP_NO_SSLv2ÚOP_NO_SSLv3Zuse_privatekeyZuse_certificateZset_context)r   Ú
connectionZserver_nameÚkeyÚcertZnew_contextr   r   r   Ú_pick_certificate_cb0   s    ÿ

zSSLSocket._pick_certificate_cbc                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	zSSLSocket.FakeConnectionzFake OpenSSL.SSL.Connection.c                 C   s
   || _ d S r
   )Ú_wrapped)r   r   r   r   r   r   O   s    z!SSLSocket.FakeConnection.__init__c                 C   s   t | j|ƒS r
   )r   r!   r   r   r   r   r   R   s    z$SSLSocket.FakeConnection.__getattr__c                 G   s
   | j  ¡ S r
   )r!   Úshutdown)r   Zunused_argsr   r   r   r"   U   s    z!SSLSocket.FakeConnection.shutdownN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r"   r   r   r   r   ÚFakeConnectionJ   s   r'   c              
   C   s¨   | j  ¡ \}}t | j¡}| tj¡ | tj¡ | | j	¡ |  
t ||¡¡}| ¡  t d|¡ z| ¡  W n. tjk
rž } zt |¡‚W 5 d }~X Y nX ||fS )NzPerforming handshake with %s)r   Úacceptr   r   r   r   r   r   Zset_tlsext_servername_callbackr    r'   Ú
ConnectionZset_accept_stater   r   Údo_handshakeÚErrorÚsocketÚerror)r   r   ÚaddrÚcontextÚssl_sockr-   r   r   r   r(   Y   s    zSSLSocket.acceptN)r#   r$   r%   r&   Ú_DEFAULT_SSL_METHODr   r   r    Úobjectr'   r(   r   r   r   r   r	      s   r	   i»  i,  )Ú r   c                 C   s  t  |¡}| |¡ d|i}zBt d|||r@d |d |d ¡nd¡ ||f}tj|f|Ž}	W n. tjk
rŒ }
 zt	 
|
¡‚W 5 d}
~
X Y nX t |	¡�h}t  ||¡}| ¡  | | ¡ z| ¡  | ¡  W n. t j
k
rú }
 zt	 
|
¡‚W 5 d}
~
X Y nX W 5 Q R X | ¡ S )a�  Probe SNI server for SSL certificate.

    :param bytes name: Byte string to send as the server name in the
        client hello message.
    :param bytes host: Host to connect to.
    :param int port: Port to connect to.
    :param int timeout: Timeout in seconds.
    :param method: See `OpenSSL.SSL.Context` for allowed values.
    :param tuple source_address: Enables multi-path probing (selection
        of source interface). See `socket.creation_connection` for more
        info. Available only in Python 2.7+.

    :raises acme.errors.Error: In case of any problems.

    :returns: SSL certificate presented by the server.
    :rtype: OpenSSL.crypto.X509

    Úsource_addressz!Attempting to connect to %s:%d%s.z from {0}:{1}r   é   r3   N)r   r   Zset_timeoutr   r   Úformatr,   Úcreate_connectionr-   r   r+   Ú
contextlibÚclosingr)   Zset_connect_stateZset_tlsext_host_namer*   r"   Zget_peer_certificate)r   ÚhostÚportÚtimeoutr   r4   r/   Zsocket_kwargsZsocket_tupler   r-   ÚclientZ
client_sslr   r   r   Ú	probe_snio   s:    

  ýþû
&r>   Fc                 C   s�   t  t j| ¡}t  ¡ }t jddd dd„ |D ƒ¡ d¡d�g}|rX| t jddd	d�¡ | |¡ | 	|¡ | 
d
¡ | |d¡ t  t j|¡S )a©  Generate a CSR containing a list of domains as subjectAltNames.

    :param buffer private_key_pem: Private key, in PEM PKCS#8 format.
    :param list domains: List of DNS names to include in subjectAltNames of CSR.
    :param bool must_staple: Whether to include the TLS Feature extension (aka
        OCSP Must Staple: https://tools.ietf.org/html/rfc7633).
    :returns: buffer PEM-encoded Certificate Signing Request.
    ó   subjectAltNameFú, c                 s   s   | ]}d | V  qdS )zDNS:Nr   ©Ú.0Údr   r   r   Ú	<genexpr>°   s     zmake_csr.<locals>.<genexpr>Úascii©ÚcriticalÚvalues   1.3.6.1.5.5.7.1.24s   DER:30:03:02:01:05é   Úsha256)r   Zload_privatekeyÚFILETYPE_PEMZX509ReqÚX509ExtensionÚjoinÚencodeÚappendÚadd_extensionsÚ
set_pubkeyÚset_versionÚsignÚdump_certificate_request)Zprivate_key_pemÚdomainsZmust_stapleZprivate_keyZcsrÚ
extensionsr   r   r   Úmake_csr    s2    	 ÿýÿý


 ÿrW   c                    s6   |   ¡ j‰ t| ƒ}ˆ d kr|S ˆ g‡ fdd„|D ƒ S )Nc                    s   g | ]}|ˆ kr|‘qS r   r   rA   ©Zcommon_namer   r   Ú
<listcomp>Å   s      z4_pyopenssl_cert_or_req_all_names.<locals>.<listcomp>)Úget_subjectÚCNÚ_pyopenssl_cert_or_req_san)Zloaded_cert_or_reqÚsansr   rX   r   Ú _pyopenssl_cert_or_req_all_names¿   s
    
r^   c                    sx   d‰ d}dˆ  ‰t | tjƒr$tj}ntj}|tj| ƒ d¡}t d|¡}|dkrTg n| 	d¡ 
|¡}‡ ‡fdd	„|D ƒS )
a¡  Get Subject Alternative Names from certificate or CSR using pyOpenSSL.

    .. todo:: Implement directly in PyOpenSSL!

    .. note:: Although this is `acme` internal API, it is used by
        `letsencrypt`.

    :param cert_or_req: Certificate or CSR.
    :type cert_or_req: `OpenSSL.crypto.X509` or `OpenSSL.crypto.X509Req`.

    :returns: A list of Subject Alternative Names.
    :rtype: `list` of `unicode`

    ú:r@   ÚDNSzutf-8z5X509v3 Subject Alternative Name:(?: critical)?\s*(.*)Nr5   c                    s$   g | ]}|  ˆ¡r| ˆ ¡d  ‘qS )r5   )Ú
startswithÚsplit)rB   Úpart©Zpart_separatorÚprefixr   r   rY   î   s    
ÿz._pyopenssl_cert_or_req_san.<locals>.<listcomp>)Ú
isinstancer   ÚX509Údump_certificaterT   ZFILETYPE_TEXTÚdecodeÚreÚsearchÚgrouprb   )Zcert_or_reqZparts_separatorÚfuncÚtextÚmatchZ
sans_partsr   rd   r   r\   Ç   s    ÿr\   é€:	 Tc              	   C   sà   |st dƒ‚t ¡ }| tt t d¡¡dƒ¡ | 	d¡ t 
ddd¡g}|d | ¡ _| | ¡ ¡ |svt|ƒdkrœ| tj
d	d
d dd„ |D ƒ¡d�¡ | |¡ | |dkr¶dn|¡ | |¡ | | ¡ | | d¡ |S )až  Generate new self-signed certificate.

    :type domains: `list` of `unicode`
    :param OpenSSL.crypto.PKey key:
    :param bool force_san:

    If more than one domain is provided, all of the domains are put into
    ``subjectAltName`` X.509 extension and first domain is set as the
    subject CN. If only one domain is provided no ``subjectAltName``
    extension is used, unless `force_san` is ``True``.

    z0Must provide one or more hostnames for the cert.é   rI   s   basicConstraintsTs   CA:TRUE, pathlen:0r   r5   r?   Fs   , c                 s   s   | ]}d |  ¡  V  qdS )s   DNS:N)rN   rA   r   r   r   rD     s     zgen_ss_cert.<locals>.<genexpr>rF   NrJ   )ÚAssertionErrorr   rg   Zset_serial_numberÚintÚbinasciiÚhexlifyÚosÚurandomrR   rL   rZ   r[   Z
set_issuerÚlenrO   rM   rP   Zgmtime_adj_notBeforeZgmtime_adj_notAfterrQ   rS   )r   rU   Z
not_beforeZvalidityZ	force_sanr   rV   r   r   r   Úgen_ss_certò   s0    
  ÿÿý


ry   c                    s$   ‡fdd„‰ d  ‡ fdd„| D ƒ¡S )zØDump certificate chain into a bundle.

    :param list chain: List of `OpenSSL.crypto.X509` (or wrapped in
        :class:`josepy.util.ComparableX509`).

    :returns: certificate chain bundle
    :rtype: bytes

    c                    s   t | tjƒr| j} t ˆ | ¡S r
   )rf   ÚjoseZComparableX509Úwrappedr   rh   )r   )Úfiletyper   r   Ú
_dump_cert+  s    z(dump_pyopenssl_chain.<locals>._dump_certó    c                 3   s   | ]}ˆ |ƒV  qd S r
   r   )rB   r   )r}   r   r   rD   3  s     z'dump_pyopenssl_chain.<locals>.<genexpr>)rM   )Úchainr|   r   )r}   r|   r   Údump_pyopenssl_chain  s    r€   )F)Nrp   T)!r&   rt   r8   Úloggingrv   rj   r,   Zjosepyrz   ZOpenSSLr   r   Zacmer   Zacme.magic_typingr   r   r   r   Ú	getLoggerr#   r   ZSSLv23_METHODr1   r2   r	   r>   rW   r^   r\   ry   rK   r€   r   r   r   r   Ú<module>   s:   
	P ÿ
1
+    ÿ
,