a oeF @svdZddlZddlZddlZddlZddlZddlZddlZddlm Z ddlm Z ddlm Z ddlm Z ddlm Z ddlmZdd lmZdd lmZdd lmZddlZdd lmZdd lmZddlmZeeZejZGdddZGdddZddeddfe e e!e!e!ee"e!fe ee ej#dddZ$d/e e eee"e e"fe%e e eej&ej'fe dddZ(eej#ej)fe e"dddZ*eej#ej)fe e"d d!d"Z+eej#ej)fe e"d d#d$Z,eej#ej)fe e"d d%d&Z-d0ej.e e e"e e!e!e%e e ej/e e eej&ej'fej#d)d*d+Z0ej1fee ej2e ej#fe!e d,d-d.Z3dS)1zCrypto utilities.N)Any)Callable)List)Mapping)Optional)Sequence)Set)Tuple)Union)crypto)SSL)errorsc@sPeZdZeeeejejffdddZ e j e eejejfdddZ dS)_DefaultCertSelectioncertscCs ||_dSNr)selfrr1C:\Program Files\Certbot\pkgs\acme\crypto_util.py__init__&sz_DefaultCertSelection.__init__ connectionreturncCs|}|r|j|dSdSr)get_servernamerget)rrZ server_namerrr__call__)sz_DefaultCertSelection.__call__N)__name__ __module__ __qualname__rbytesr r PKeyX509rr Connectionrrrrrrr%s"rc @seZdZdZdeddfejeeee e j e j ffe eeejeegefeeejgee e j e j ffddddZeedddZejdd d d ZGd d d Ze eefdddZdS) SSLSocketaSSL 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. N)sockrmethodalpn_selectioncert_selectionrcCsX||_||_||_|s"|s"td|r2|r2td|}|durNt|rH|ni}||_dS)Nz*Neither cert_selection or certs specified.z(Both cert_selection and certs specified.)r$r&r% ValueErrorrr')rr$rr%r&r'Zactual_cert_selectionrrrr=szSSLSocket.__init__namercCs t|j|Sr)getattrr$rr*rrr __getattr__TszSSLSocket.__getattr__rcCs||}|dur&td|dS|\}}t|j}|tj|tj | || ||j dur|| |j ||dS)aSNI 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` Nz=Certificate selection for server name %s failed, dropping SSL)r'loggerdebugrr Contextr% set_options OP_NO_SSLv2 OP_NO_SSLv3Zuse_privatekeyZuse_certificater&set_alpn_select_callbackZ set_context)rrZpairkeycertZ new_contextrrr_pick_certificate_cbWs        zSSLSocket._pick_certificate_cbc@sBeZdZdZejddddZeedddZ ee d d d Z dS) zSSLSocket.FakeConnectionzFake OpenSSL.SSL.Connection.NrcCs ||_dSr)_wrapped)rrrrrrwsz!SSLSocket.FakeConnection.__init__r)cCs t|j|Sr)r+r8r,rrrr-zsz$SSLSocket.FakeConnection.__getattr__) unused_argsrc GsBz |jWStjy<}zt|WYd}~n d}~00dSr)r8shutdownr Errorsocketerror)rr9r=rrrr:}s z!SSLSocket.FakeConnection.shutdown) rrr__doc__r r"rstrrr-boolr:rrrrFakeConnectionrsrA)rc Cs|j\}}zt|j}|tj|tj||j |j durV| |j | t ||}|td|z |Wn0tjy}zt|WYd}~n d}~00||fWS|Yn0dS)NzPerforming handshake with %s)r$acceptr r0r%r1r2r3Zset_tlsext_servername_callbackr7r&r4rAr"Zset_accept_stater.r/ do_handshaker;r<r=close)rr$ZaddrcontextZssl_sockr=rrrrBs&          zSSLSocket.accept)rrrr>_DEFAULT_SSL_METHODr<rrrr r r r!intrr r"rrr?rr-r7rArBrrrrr#0s(   r#ii,)r)r*hostporttimeoutr%source_addressalpn_protocolsrc CsRt|}||d|i}zJtd||t|rDd|d|dnd||f} tj| fi|} Wn0tj y} zt | WYd} ~ n d} ~ 00t | } t|| } | | ||dur| |z| | Wn2tj y} zt | WYd} ~ n d} ~ 00Wdn1s20Y| }|sNJ|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+. :param alpn_protocols: Protocols to request using ALPN. :type alpn_protocols: `Sequence` of `bytes` :raises acme.errors.Error: In case of any problems. :returns: SSL certificate presented by the server. :rtype: OpenSSL.crypto.X509 rLz!Attempting to connect to %s:%d%s.z from {0}:{1}rrHN)r r0Z set_timeoutr.r/anyformatr<Zcreate_connectionr=r r; contextlibclosingr"Zset_connect_stateZset_tlsext_host_nameZset_alpn_protosrCr:Zget_peer_certificate)r*rIrJrKr%rLrMrEZ socket_kwargsZ socket_tupler$r=ZclientZ client_sslr6rrr probe_snis>        @ rSF)private_key_pemdomains must_stapleipaddrsrc Csttj|}t}g}|dur&g}|dur2g}t|t|dkrNtd|D]}|d|qR|D]}|d|jqjd| d} tj dd | d g} |r| tj d d d d | | | || d||d ttj|S)aGenerate a CSR containing domains or IPs 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). :param list ipaddrs: List of IPaddress(type ipaddress.IPv4Address or ipaddress.IPv6Address) names to include in subbjectAltNames of CSR. params ordered this way for backward competablity when called by positional argument. :returns: buffer PEM-encoded Certificate Signing Request. NrzAAt least one of domains or ipaddrs parameter need to be not emptyDNS:IP:, asciisubjectAltNameFZcriticalvalues1.3.6.1.5.5.7.1.24sDER:30:03:02:01:05sha256)r Zload_privatekey FILETYPE_PEMX509Reqlenr(appendexplodedjoinencode X509Extensionadd_extensions set_pubkey set_versionsigndump_certificate_request) rTrUrVrWZ private_keyZcsrsanlistaddressips san_string extensionsrrrmake_csrsF    rr)loaded_cert_or_reqrcs6|jt|}dur|Sgfdd|DS)Ncsg|]}|kr|qSrr).0dZ common_namerr z4_pyopenssl_cert_or_req_all_names..) get_subjectCN_pyopenssl_cert_or_req_san)rsZsansrrvr _pyopenssl_cert_or_req_all_namess  r|) cert_or_reqrcs(ddt|}fdd|DS)aGet 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 that is DNS. :rtype: `list` of `str` :ZDNScs$g|]}|r|dqS)rN) startswithsplitrtpartpart_separatorprefixrrrw:s z._pyopenssl_cert_or_req_san.._pyopenssl_extract_san_list_raw)r} sans_partsrrrr{#s  r{cs&d}d|t|}fdd|DS)aeGet Subject Alternative Names IPs from certificate or CSR using pyOpenSSL. :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 that are IP Addresses. :rtype: `list` of `str`. note that this returns as string, not IPaddress object r~z IP Addresscs&g|]}|r|tdqSr)rrbrrrrrwOrxz1_pyopenssl_cert_or_req_san_ip..r)r}rrrrr_pyopenssl_cert_or_req_san_ip>s rcCsft|tjr"ttj|d}nttj|d}td|}d}|durRgn| d |}|S)aGet raw SAN string from cert or csr, parse it as UTF-8 and return. :param cert_or_req: Certificate or CSR. :type cert_or_req: `OpenSSL.crypto.X509` or `OpenSSL.crypto.X509Req`. :returns: raw san strings, parsed byte as utf-8 :rtype: `list` of `str` zutf-8z5X509v3 Subject Alternative Name:(?: critical)?\s*(.*)rZNrN) isinstancer r!dump_certificateZ FILETYPE_TEXTdecoderlresearchgroupr)r}textZraw_sanZparts_separatorrrrrrRs  r: T)r5rU not_beforevalidity force_sanrqrorc Csb|s|sJdt}|tttdd|d|durJg}|durVg}|durbg}| t dddt |dkr|d| _ || g}|D]} | d | q|D]} | d | jqd |d } |st |d kst |dkr| tj dd| d||||dur8dn|||||||d|S)atGenerate new self-signed certificate. :type domains: `list` of `str` :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` :type ips: `list` of (`ipaddress.IPv4Address` or `ipaddress.IPv6Address`) 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``. z7Must provide one or more hostnames or IPs for the cert.NsbasicConstraintsTsCA:TRUE, pathlen:0rrXrYrZr[rNr\Fr]r_)r r!Zset_serial_numberrGbinasciiZhexlifyosurandomrjrcrgrbryrzZ set_issuerrdrerfrhZgmtime_adj_notBeforeZgmtime_adj_notAfterrirk) r5rUrrrrqror6rmrnZiprprrr gen_ss_certqsH  "    r)chainfiletypercs8ttjtjftdfdd dfdd|DS)zDump 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 )r6rcs6t|tjr*t|jtjr$td|j}t|S)NzUnexpected CSR provided.) rjoseComparableX509wrappedr rar r;r)r6)rrr _dump_certs   z(dump_pyopenssl_chain.._dump_certrxc3s|]}|VqdSrr)rtr6)rrr rxz'dump_pyopenssl_chain..)r rrr r!rre)rrr)rrrdump_pyopenssl_chains r)NFN)NNrTNN)4r>rrQZ ipaddressZloggingrrr<typingrrrrrrrr r ZjosepyrZOpenSSLr r Zacmer Z getLoggerrr.Z SSLv23_METHODrFrr#rrGr?r!rSr@Z IPv4AddressZ IPv6Addressrrrar|r{rrr rgrr`rrrrrrsz              x   9 7     C