a ‚oeƒFã @svdZddlZddlZddlZddlZddlZddlZddlZddlm Z ddlm Z ddlm Z ddlm Z ddlm Z ddlmZdd lmZdd lmZdd lmZddlZdd lmZdd lmZddlmZe e¡ZejZGdd„dƒZGdd„dƒZddeddfe e e!e!e!ee"e!fe ee ej#dœdd„Z$d/e e eee"e e"fe%e e eej&ej'fe dœdd„Z(eej#ej)fe e"dœdd„Z*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@sPeZdZeeeejejffdœdd„Z e j e eejejfdœdd„Z dS)Ú_DefaultCertSelection©ÚcertscCs ||_dS©Nr)Úselfr©rú1C:\Program Files\Certbot\pkgs\acme\crypto_util.pyÚ__init__&sz_DefaultCertSelection.__init__©Ú connectionÚreturncCs| ¡}|r|j |d¡SdSr)Úget_servernamerÚget)rrZ server_namerrrÚ__call__)sz_DefaultCertSelection.__call__N)Ú__name__Ú __module__Ú __qualname__rÚbytesr r ÚPKeyÚX509rr Ú Connectionrrrrrrr%s"rc @sÈeZdZdZdeddfejeeee e j e j ffe eeejeegefeeejgee e j e j ffddœdd„Zeedœdd„Zejdd œd d „ZGd d „d ƒZe eefdœdd„ZdS)Ú SSLSocketaÝ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. N)ÚsockrÚmethodÚalpn_selectionÚcert_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=sýzSSLSocket.__init__©ÚnamercCs t|j|ƒSr)Úgetattrr$©rr*rrrÚ __getattr__TszSSLSocket.__getattr__rcCsŠ| |¡}|dur&t d| ¡¡dS|\}}t |j¡}| tj¡| tj ¡|  |¡|  |¡|j dur||  |j ¡| |¡dS)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` Nz=Certificate selection for server name %s failed, dropping SSL)r'ÚloggerÚdebugrr ÚContextr%Ú set_optionsÚ OP_NO_SSLv2Ú OP_NO_SSLv3Zuse_privatekeyZuse_certificater&Úset_alpn_select_callbackZ set_context)rrZpairÚkeyÚcertZ new_contextrrrÚ_pick_certificate_cbWs ÿ       zSSLSocket._pick_certificate_cbc@sBeZdZdZejddœdd„Zeedœdd„Z 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 |j ¡WStjy<}zt |¡‚WYd}~n d}~00dSr)r8Úshutdownr ÚErrorÚsocketÚerror)rr9r=rrrr:}s z!SSLSocket.FakeConnection.shutdown) rrrÚ__doc__r r"rÚstrrr-Úboolr:rrrrÚFakeConnectionrsrA)rc CsÞ|j ¡\}}z´t |j¡}| tj¡| tj¡| |j ¡|j durV|  |j ¡|  t  ||¡¡}| ¡t d|¡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$ZaddrÚcontextZssl_sockr=rrrrBˆs&          zSSLSocket.accept)rrrr>Ú_DEFAULT_SSL_METHODr<rrrr r r r!Úintrr r"rrr?rr-r7rArBrrrrr#0s( ú ÿÿù r#i»i,)Úr)r*ÚhostÚportÚtimeoutr%Úsource_addressÚalpn_protocolsrc CsRt |¡}| |¡d|i}zJt d||t|ƒrDd |d|d¡nd¡||f} tj| fi|¤Ž} Wn0tj y–} zt   | ¡‚WYd} ~ n d} ~ 00t   | ¡�ˆ} t || ¡} |  ¡|  |¡|durÔ|  |¡z|  ¡|  ¡Wn2tj �y} zt   | ¡‚WYd} ~ n d} ~ 00Wdƒn1�s20Y|  ¡}|�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}rérHN)r r0Z set_timeoutr.r/ÚanyÚformatr<Zcreate_connectionr=r r;Ú contextlibÚclosingr"Zset_connect_stateZset_tlsext_host_nameZset_alpn_protosrCr:Zget_peer_certificate)r*rIrJrKr%rLrMrEZ socket_kwargsZ socket_tupler$r=ZclientZ client_sslr6rrrÚ probe_sni¨s>  ýþû      @ rSF)Úprivate_key_pemÚdomainsÚ must_stapleÚipaddrsrc Csôt tj|¡}t ¡}g}|dur&g}|dur2g}t|ƒt|ƒdkrNtdƒ‚|D]}| d|¡qR|D]}| d|j¡qjd |¡  d¡} tj dd | d �g} |r¼|  tj d d d d �¡|  | ¡|  |¡|  d¡| |d ¡t tj|¡S)a‘Generate 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 emptyúDNS:úIP:ú, ÚasciiósubjectAltNameF©ZcriticalÚvalues1.3.6.1.5.5.7.1.24sDER:30:03:02:01:05Úsha256)r Zload_privatekeyÚ FILETYPE_PEMÚX509ReqÚlenr(ÚappendÚexplodedÚjoinÚencodeÚ X509ExtensionÚadd_extensionsÚ set_pubkeyÚ set_versionÚsignÚdump_certificate_request) rTrUrVrWZ private_keyZcsrÚsanlistÚaddressÚipsÚ san_stringÚ extensionsrrrÚmake_csrásFÿýÿý    ÿrr)Úloaded_cert_or_reqrcs6| ¡j‰t|ƒ}ˆdur|Sˆg‡fdd„|DƒS)Ncsg|]}|ˆkr|‘qSrr)Ú.0Úd©Z common_namerrÚ óz4_pyopenssl_cert_or_req_all_names..)Ú get_subjectÚCNÚ_pyopenssl_cert_or_req_san)rsZsansrrvrÚ _pyopenssl_cert_or_req_all_namess  r|)Ú cert_or_reqrcs(d‰dˆ‰t|ƒ}‡‡fdd„|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 that is DNS. :rtype: `list` of `str` ú:ZDNScs$g|]}| ˆ¡r| ˆ¡d‘qS)rN)Ú startswithÚsplit©rtÚpart©Úpart_separatorÚprefixrrrw:s ÿz._pyopenssl_cert_or_req_san..©Ú_pyopenssl_extract_san_list_raw)r}Ú sans_partsrrƒrr{#s  ÿr{cs&d}d|‰t|ƒ}‡fdd„|DƒS)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|tˆƒd…‘qSr)rrbr�©r…rrrwOrxz1_pyopenssl_cert_or_req_san_ip..r†)r}r„rˆrr‰rÚ_pyopenssl_cert_or_req_san_ip>s rŠcCsft|tjƒr"t tj|¡ d¡}nt tj|¡ d¡}t d|¡}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_TEXTÚdecoderlÚreÚsearchÚgroupr€)r}ÚtextZraw_sanZparts_separatorrˆrrrr‡Rs  r‡é€: T)r5rUÚ not_beforeÚvalidityÚ force_sanrqrorc Csb|s|sJdƒ‚t ¡}| tt t d¡¡dƒ¡| d¡|durJg}|durVg}|durbg}|  t  ddd¡¡t |ƒdkr�|d|  ¡_ | |  ¡¡g}|D]} |  d | ¡q¦|D]} |  d | j¡q¾d  |¡ d ¡} |�st |ƒd k�st |ƒdk�r|  tj dd| d�¡| |¡| |du�r8dn|¡| |¡| |¡| |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_numberrGÚbinasciiZhexlifyÚosÚurandomrjrcrgrbryrzZ set_issuerrdrerfrhZgmtime_adj_notBeforeZgmtime_adj_notAfterrirk) r5rUr“r”r•rqror6rmrnZiprprrrÚ gen_ss_certqsH ÿÿ "ý    r›)ÚchainÚfiletypercs8ttjtjftdœ‡fdd„ ‰d ‡fdd„|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 )r6rcs6t|tjƒr*t|jtjƒr$t d¡‚|j}t ˆ|¡S)NzUnexpected CSR provided.) r‹ÚjoseÚComparableX509Úwrappedr rar r;rŒ)r6)r�rrÚ _dump_certÁs   z(dump_pyopenssl_chain.._dump_certrxc3s|]}ˆ|ƒVqdSrr)rtr6)r¡rrÚ Êrxz'dump_pyopenssl_chain..)r ržrŸr r!rre)rœr�r)r¡r�rÚdump_pyopenssl_chain³s r£)NFN)NNr’TNN)4r>r˜rQZ ipaddressZloggingr™rŽr<Útypingrrrrrrrr r ZjosepyržZOpenSSLr r Zacmer Z getLoggerrr.Z SSLv23_METHODrFrr#rrGr?r!rSr@Z IPv4AddressZ IPv6Addressrrrar|r{rŠr‡r rgr›r`rŸr£rrrrÚsz              xþ  þ 9þý 7ÿ   ü û Cÿÿ