ó
Á£ô_c           @   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 e j e ƒ Z e j Z d	 e f d
 „  ƒ  YZ d e f d „  ƒ  YZ d d e d d d „ Z e d „ Z d „  Z d „  Z d d e  d d „ Z! e
 j" d „ Z# d S(   s   Crypto utilities.iÿÿÿÿN(   t   crypto(   t   SSL(   t   errors(   t   Callable(   t   Tuple(   t   Uniont   _DefaultCertSelectionc           B   s   e  Z d  „  Z d „  Z RS(   c         C   s   | |  _  d  S(   N(   t   certs(   t   selfR   (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   __init__   s    c         C   s   | j  ƒ  } |  j j | d  ƒ S(   N(   t   get_servernameR   t   gett   None(   R   t
   connectiont   server_name(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   __call__"   s    (   t   __name__t
   __module__R	   R   (    (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR      s   	t	   SSLSocketc           B   sT   e  Z d  Z d e d d 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.
    :ivar alpn_selection: Hook to select negotiated ALPN protocol for
        connection.
    :ivar cert_selection: Hook to select certificate for connection. If given,
        `certs` parameter would be ignored, and therefore must be empty.

    c         C   s{   | |  _  | |  _ | |  _ | r8 | r8 t d ƒ ‚ n  | rS | rS t d ƒ ‚ n  | d  k rn t | ƒ } n  | |  _ d  S(   Ns*   Neither cert_selection or certs specified.s(   Both cert_selection and certs specified.(   t   sockt   alpn_selectiont   methodt
   ValueErrorR   R   t   cert_selection(   R   R   R   R   R   R   (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR	   4   s    			c         C   s   t  |  j | ƒ S(   N(   t   getattrR   (   R   t   name(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   __getattr__B   s    c         C   sÀ   |  j  | ƒ } | d k r5 t j d | j ƒ  ƒ d S| \ } } t j |  j ƒ } | j t j	 ƒ | j t j
 ƒ | j | ƒ | j | ƒ |  j d k	 r¯ | j |  j ƒ n  | 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=   Certificate selection for server name %s failed, dropping SSLN(   R   R   t   loggert   debugR
   R   t   ContextR   t   set_optionst   OP_NO_SSLv2t   OP_NO_SSLv3t   use_privatekeyt   use_certificateR   t   set_alpn_select_callbackt   set_context(   R   R   t   pairt   keyt   certt   new_context(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   _pick_certificate_cbE   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/site-packages/acme/crypto_util.pyR	   e   s    c         C   s   t  |  j | ƒ S(   N(   R   R+   (   R   R   (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR   h   s    c         G   s   |  j  j ƒ  S(   N(   R+   t   shutdown(   R   t   unused_args(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR,   k   s    (   R   R   t   __doc__R	   R   R,   (    (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR*   `   s   		c         C   sî   |  j  j ƒ  \ } } t j |  j ƒ } | j t j ƒ | j t j ƒ | j |  j	 ƒ |  j
 d  k	 ry | j |  j
 ƒ n  |  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   R   R#   R*   t
   Connectiont   set_accept_stateR   R   t   do_handshaket   Errort   sockett   error(   R   R   t   addrt   contextt   ssl_sockR6   (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR/   o   s    
N(   R   R   R.   R   t   _DEFAULT_SSL_METHODR	   R   R)   t   objectR*   R/   (    (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyR   '   s   		i»  i,  t    i    c      	   C   sP  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 |
 ƒ Œ } t  j | | ƒ } | j ƒ  | j |  ƒ | d k	 r | j | ƒ n  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+.
    :param alpn_protocols: Protocols to request using ALPN.
    :type alpn_protocols: `list` of `bytes`

    :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   R<   N(   R   R   t   set_timeoutR   R   t   formatR5   t   create_connectionR6   R   R4   t
   contextlibt   closingR1   t   set_connect_statet   set_tlsext_host_nameR   t   set_alpn_protosR3   R,   t   get_peer_certificate(   R   t   hostt   portt   timeoutR   R=   t   alpn_protocolsR8   t   socket_kwargst   socket_tupleR   R6   t   clientt
   client_ssl(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt	   probe_sni‡   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/site-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/site-packages/acme/crypto_util.pyt   make_csr¾   s$    	(c         C   sU   |  j  ƒ  j } t |  ƒ } | d  k r+ | S| g g  | D] } | | k r8 | ^ q8 S(   N(   t   get_subjectt   CNt   _pyopenssl_cert_or_req_sanR   (   t   loaded_cert_or_reqt   common_namet   sansRT   (    (    s4   /usr/lib/python2.7/site-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_certificateRc   t   FILETYPE_TEXTt   decodet   ret   searchR   t   groupt   splitt
   startswith(	   t   cert_or_reqt   part_separatort   parts_separatort   prefixt   funct   textt   matcht
   sans_partst   part(    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyRm   ç   s    
	*i   i   i<   c      
   C   sB  t  j ƒ  } | j t t j t j d ƒ ƒ d ƒ ƒ | j d ƒ | d k rV g  } n  | j
 t  j d t d ƒ ƒ | 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:
    :param extensions: List of additional extensions to include in the cert.
    :type extensions: `list` of `OpenSSL.crypto.X509Extension`

    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``.

    i   i   t   basicConstraintss   CA:TRUE, pathlen:0i    i   RP   RQ   RR   s   , c         s   s   |  ] } d  | j  ƒ  Vq d S(   s   DNS:N(   R]   (   RS   RT   (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pys	   <genexpr>7  s    RV   N(   R    Ru   t   set_serial_numbert   intt   binasciit   hexlifyt   ost   urandomRa   R   R^   RZ   t   TrueRk   Rl   t
   set_issuert   lenR[   R\   R_   t   gmtime_adj_notBeforet   gmtime_adj_notAfterR`   Rb   (   R&   Re   t
   not_beforet   validityt	   force_sanRi   R'   (    (    s4   /usr/lib/python2.7/site-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(   Rt   t   joset   ComparableX509t   wrappedR    Rv   (   R'   (   t   filetype(    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt
   _dump_certQ  s    R<   c         3   s   |  ] } ˆ  | ƒ Vq d  S(   N(    (   RS   R'   (   R›   (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pys	   <genexpr>X  s    (   R\   (   t   chainRš   (    (   R›   Rš   s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   dump_pyopenssl_chainD  s    (   R<   i    i¨   i`'  i€:	 ($   R.   RŠ   RA   t   loggingRŒ   Ry   R5   t   josepyR—   t   OpenSSLR    R   t   acmeR   t   acme.magic_typingR   R   R   t	   getLoggerR   R   t   SSLv23_METHODR:   R;   R   R   R   RO   R[   Rj   Rq   Rm   RŽ   R–   RX   R   (    (    (    s4   /usr/lib/python2.7/site-packages/acme/crypto_util.pyt   <module>   s4   			`5 			+1