ó
¡\\c           @   s2  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 m Z d d l m	 Z	 d d l
 Z d d l m Z d d l m Z m Z m Z m Z e j e ƒ Z e	 j Z d e f d „  ƒ  YZ d	 d
 e d d „ Z e d „ Z d „  Z d „  Z d d e  d „ Z! e j" d „ Z# d S(   s   Crypto utilities.iÿÿÿÿN(   t   crypto(   t   SSL(   t   errors(   t   Callablet   Uniont   Tuplet   Optionalt	   SSLSocketc           B   sK   e  Z d  Z e d „ Z d „  Z d „  Z d e f d „  ƒ  YZ d „  Z	 RS(   së   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(   t   sockt   certst   method(   t   selfR   R	   R
   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   __init__+   s    		c         C   s   t  |  j | ƒ S(   N(   t   getattrR   (   R   t   name(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   __getattr__0   s    c         C   s¥   | j  ƒ  } y |  j | \ } } Wn" t k
 rG t j d | ƒ d SXt j |  j ƒ } | j t j	 ƒ | j t j
 ƒ | j | ƒ | j | ƒ | j | ƒ d S(   s  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`

        s-   Server name (%s) not recognized, dropping SSLN(   t   get_servernameR	   t   KeyErrort   loggert   debugR   t   ContextR
   t   set_optionst   OP_NO_SSLv2t   OP_NO_SSLv3t   use_privatekeyt   use_certificatet   set_context(   R   t
   connectiont   server_namet   keyt   certt   new_context(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   _pick_certificate_cb3   s    	t   FakeConnectionc           B   s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   s   Fake OpenSSL.SSL.Connection.c         C   s   | |  _  d  S(   N(   t   _wrapped(   R   R   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR   R   s    c         C   s   t  |  j | ƒ S(   N(   R   R"   (   R   R   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR   U   s    c         G   s   |  j  j ƒ  S(   N(   R"   t   shutdown(   R   t   unused_args(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR#   X   s    (   t   __name__t
   __module__t   __doc__R   R   R#   (    (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR!   M   s   		c         C   sÌ   |  j  j ƒ  \ } } t j |  j ƒ } | j t j ƒ | j t j ƒ | j |  j	 ƒ |  j
 t j | | ƒ ƒ } | j ƒ  t j d | ƒ y | j ƒ  Wn% t j k
 rÁ } t j | ƒ ‚ n X| | f S(   Ns   Performing handshake with %s(   R   t   acceptR   R   R
   R   R   R   t   set_tlsext_servername_callbackR    R!   t
   Connectiont   set_accept_stateR   R   t   do_handshaket   Errort   sockett   error(   R   R   t   addrt   contextt   ssl_sockR/   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR(   \   s    
(
   R%   R&   R'   t   _DEFAULT_TLSSNI01_SSL_METHODR   R   R    t   objectR!   R(   (    (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyR   "   s   		i»  i,  t    i    c      	   C   s4  t  j | ƒ } | j | ƒ i | d 6} yX t j d | | | r[ d j | d | d ƒ n d ƒ | | f } t j | |  }	 Wn% t j k
 r¨ }
 t	 j
 |
 ƒ ‚ n Xt j |	 ƒ p } t  j | | ƒ } | j ƒ  | j |  ƒ y | j ƒ  | j ƒ  Wn% t  j
 k
 r#}
 t	 j
 |
 ƒ ‚ n XWd QX| j ƒ  S(   s  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

    t   source_addresss!   Attempting to connect to %s:%d%s.s    from {0}:{1}i    i   R5   N(   R   R   t   set_timeoutR   R   t   formatR.   t   create_connectionR/   R   R-   t
   contextlibt   closingR*   t   set_connect_statet   set_tlsext_host_nameR,   R#   t   get_peer_certificate(   R   t   hostt   portt   timeoutR
   R6   R1   t   socket_kwargst   socket_tupleR   R/   t   clientt
   client_ssl(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt	   probe_snir   s*    	'

c         C   sÐ   t  j t  j |  ƒ } t  j ƒ  } t  j d d t d d j d „  | Dƒ ƒ j d ƒ ƒg } | r† | j t  j d d t d d ƒƒ n  | j	 | ƒ | j
 | ƒ | j d	 ƒ | j | d
 ƒ t  j t  j | ƒ S(   s©  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.
    t   subjectAltNamet   criticalt   values   , c         s   s   |  ] } d  | Vq d S(   s   DNS:N(    (   t   .0t   d(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pys	   <genexpr>´   s    t   asciis   1.3.6.1.5.5.7.1.24s   DER:30:03:02:01:05i   t   sha256(   R    t   load_privatekeyt   FILETYPE_PEMt   X509Reqt   X509Extensiont   Falset   joint   encodet   appendt   add_extensionst
   set_pubkeyt   set_versiont   signt   dump_certificate_request(   t   private_key_pemt   domainst   must_staplet   private_keyt   csrt
   extensions(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   make_csr¤   s$    	(c         C   sY   |  j  ƒ  j } t |  ƒ } | d  k r+ | S| g g  | D] } | | k r8 | ^ q8 Sd  S(   N(   t   get_subjectt   CNt   _pyopenssl_cert_or_req_sant   None(   t   loaded_cert_or_reqt   common_namet   sansRK   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt    _pyopenssl_cert_or_req_all_namesÃ   s
    c   	      C   sÇ   d } d } d | } t  |  t j ƒ r4 t j } n	 t j } | t j |  ƒ j d ƒ } t j d | ƒ } | d k r| g  n | j
 d ƒ j | ƒ } g  | D]( } | j | ƒ r› | j | ƒ d ^ q› S(   s¡  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`

    t   :s   , t   DNSs   utf-8s5   X509v3 Subject Alternative Name:(?: critical)?\s*(.*)i   N(   t
   isinstanceR    t   X509t   dump_certificateRZ   t   FILETYPE_TEXTt   decodet   ret   searchRe   t   groupt   splitt
   startswith(	   t   cert_or_reqt   part_separatort   parts_separatort   prefixt   funct   textt   matcht
   sans_partst   part(    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyRd   Ì   s    
	*i   i   i<   c      	   C   s;  | s t  d ƒ ‚ t j ƒ  } | j t t j t j d ƒ ƒ d ƒ ƒ | j	 d ƒ t j
 d t d ƒ g } | d | j ƒ  _ | j | j ƒ  ƒ | s© t | ƒ d k rá | j t j
 d d	 t d
 d j d „  | Dƒ ƒ ƒƒ n  | j | ƒ | j | d k rd n | ƒ | j | ƒ | j |  ƒ | j |  d ƒ | S(   sž  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``.

    s0   Must provide one or more hostnames for the cert.i   i   t   basicConstraintss   CA:TRUE, pathlen:0i    i   RG   RH   RI   s   , c         s   s   |  ] } d  | j  ƒ  Vq d S(   s   DNS:N(   RT   (   RJ   RK   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pys	   <genexpr>  s    RM   N(   t   AssertionErrorR    Rm   t   set_serial_numbert   intt   binasciit   hexlifyt   ost   urandomRX   RQ   t   TrueRb   Rc   t
   set_issuert   lenRU   RR   RS   RV   t   gmtime_adj_notBeforeRe   t   gmtime_adj_notAfterRW   RY   (   R   R\   t
   not_beforet   validityt	   force_sanR   R`   (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   gen_ss_cert÷   s&    ( c            s,   ‡ f d †  ‰  d j  ‡  f d †  |  Dƒ ƒ S(   sØ   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 }  n  t j ˆ  |  ƒ S(   N(   Rl   t   joset   ComparableX509t   wrappedR    Rn   (   R   (   t   filetype(    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt
   _dump_cert0  s    R5   c         3   s   |  ] } ˆ  | ƒ Vq d  S(   N(    (   RJ   R   (   R”   (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pys	   <genexpr>8  s    (   RS   (   t   chainR“   (    (   R”   R“   s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   dump_pyopenssl_chain#  s    (   R5   i    i¨   i`'  i€:	 ($   R'   Rƒ   R:   t   loggingR…   Rq   R.   t   OpenSSLR    R   t   josepyR   t   acmeR   t   acme.magic_typingR   R   R   R   t	   getLoggerR%   R   t   SSLv23_METHODR3   R4   R   RF   RR   Ra   Ri   Rd   Re   R‡   R   RO   R–   (    (    (    s4   /usr/lib/python2.7/dist-packages/acme/crypto_util.pyt   <module>   s,   "	P1			++