a ‚oe¸Wã@s dZddlZddlZddlZddlZddlZddlZddlmZddlm Z ddlm Z ddlm Z ddlm Z ddlm Z dd lmZdd lmZdd lmZdd lmZddlZdd lmZddlmZddlZddlmZddlmZe e¡Zeddd�ZGdd„dej ƒZ!Gdd„dej ƒZ"Gdd„de!ƒZ#Gdd„de!ƒZ$Gdd„de"ƒZ%Gdd„de$ej&d�Z'e"j(Gd d!„d!e%ƒƒZ)e!j(Gd"d#„d#e'ƒƒZ*e"j(Gd$d%„d%e%ƒƒZ+e!j(Gd&d'„d'e'ƒƒZ,e"j(Gd(d)„d)e%ƒƒZ-e!j(Gd*d+„d+e'ƒƒZ.e!j(Gd,d-„d-e$ƒƒZ/e"j(Gd.d/„d/e"ƒƒZ0dS)0z&ACME Identifier Validation Challenges.éN)ÚAny)Úcast)ÚDict)ÚMapping)ÚOptional)ÚTuple)ÚType)ÚTypeVar)ÚUnion)Úhashes)Úcrypto)ÚSSL)Ú crypto_util)ÚerrorsÚGenericChallengeÚ Challenge)Úboundcs\eZdZUdZiZeeedfed<e ee e ee fe e dfdœ‡fdd„ ƒZ‡ZS)rzACME challenge.ÚTYPESÚUnrecognizedChallenge)ÚclsÚjobjÚreturnc sTztttƒ |¡ƒWStjyN}z t |¡t |¡WYd}~Sd}~00dS©N) rrÚsuperÚ from_jsonÚjoseZUnrecognizedTypeErrorÚloggerÚdebugr)rrÚerror©Ú __class__©ú0C:\Program Files\Certbot\pkgs\acme\challenges.pyr%s  zChallenge.from_json)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrÚstrrÚ__annotations__Ú classmethodrrrr rÚ __classcell__r!r!rr"r s ÿcsHeZdZUdZiZeeedfed<eee fdœ‡fdd„ Z ‡Z S)ÚChallengeResponsezACME challenge response.r©rcstƒ ¡}| |jd¡|Sr)rÚto_partial_jsonÚpopZtype_field_name©Úselfrrr!r"r-4s z!ChallengeResponse.to_partial_json) r#r$r%r&rrr'rr(rr-r*r!r!rr"r+/s r+csteZdZUdZeeefed<eeefddœ‡fdd„ Z eeefdœdd „Z e eeefddœd d „ƒZ ‡Z S) ralUnrecognized challenge. ACME specification defines a generic framework for challenges and defines some standard challenges that are implemented in this module. However, other implementations (including peers) might define additional challenge types, which should be ignored if unrecognized. :ivar jobj: Original JSON decoded object. rN)rrcstƒ ¡t |d|¡dS)Nr)rÚ__init__ÚobjectÚ __setattr__r/rr!r"r1Js zUnrecognizedChallenge.__init__r,cCs|jSr)r©r0r!r!r"r-Nsz%UnrecognizedChallenge.to_partial_jsoncCs||ƒSrr!)rrr!r!r"rQszUnrecognizedChallenge.from_json)r#r$r%r&rr'rr(rr1r-r)rr*r!r!rr"r<s  rc@sPeZdZUdZdZejdejej ej edd�d�Z e e d<eedœdd „ƒZd S) Ú_TokenChallengez3Challenge with token. :ivar bytes token: g0@ÚtokenT)ÚsizeZminimum)ÚencoderÚdecoderr,cCsd|jvod|jvS)zÅIs `token` good? .. todo:: acme-spec wants "It MUST NOT contain any non-ASCII characters", but it should also warrant that it doesn't contain ".." or "/"... s..ó/)r6r4r!r!r"Ú good_tokenes z_TokenChallenge.good_tokenN)r#r$r%r&Z TOKEN_SIZErÚfieldZencode_b64joseÚ functoolsÚpartialZdecode_b64joser6Úbytesr(ÚpropertyÚboolr;r!r!r!r"r5Vs  ÿÿr5cs\eZdZUdZe d¡Zeed<e j Z dej e dœdd„Zeeefdœ‡fd d „ Z‡ZS) Ú!KeyAuthorizationChallengeResponsez[Response to Challenges based on Key Authorization. :param str key_authorization: ÚkeyAuthorizationÚkey_authorizationÚKeyAuthorizationChallenge©ÚchallÚaccount_public_keyrcCs–|j d¡}t|ƒdkr*t d|j¡dS|d| d¡krXt d|d| d¡¡dSt |j|j d�¡  ¡}|d |kr’t d |d|¡dSd S) a%Verify the key authorization. :param KeyAuthorization chall: Challenge that corresponds to this response. :param JWK account_public_key: :return: ``True`` iff verification of the key authorization was successful. :rtype: bool Ú.éz)Key authorization (%r) is not well formedFrr6z8Mismatching token in key authorization: %r instead of %r©Z hash_functionéz=Mismatching thumbprint in key authorization: %r instead of %rT) rDÚsplitÚlenrrÚencoderÚ b64encodeÚ thumbprintÚthumbprint_hash_functionÚdecode)r0rGrHÚpartsrQr!r!r"Úverify}s(  ÿÿÿ  ÿz(KeyAuthorizationChallengeResponse.verifyr,cstƒ ¡}| dd¡|S)NrC)rr-r.r/rr!r"r-�s  z1KeyAuthorizationChallengeResponse.to_partial_json)r#r$r%r&rr<rDr'r(r ZSHA256rRÚJWKrArUrrr-r*r!r!rr"rBts  rBc@s�eZdZUdZeZeed<eZe e ed<e j Z e j edœdd„Ze j e dœdd„Zeje j eed œd d „ƒZe j eeee efd œd d„ZdS)rEzÒChallenge based on Key Authorization. :param response_cls: Subclass of `KeyAuthorizationChallengeResponse` that will be used to generate ``response``. :param str typ: type of the challenge ÚtypÚ response_cls)Ú account_keyrcCs&| d¡dt |j|jd�¡ ¡S)zZGenerate Key Authorization. :param JWK account_key: :rtype str: r6rIrK)rOrrPrQrRrS©r0rYr!r!r"rD²s ÿÿz+KeyAuthorizationChallenge.key_authorizationcCs|j| |¡d�S)zËGenerate response to the challenge. :param JWK account_key: :returns: Response (initialized `response_cls`) to the challenge. :rtype: KeyAuthorizationChallengeResponse ©rD)rXrDrZr!r!r"Úresponse½s ÿz"KeyAuthorizationChallenge.response©rYÚkwargsrcKs tƒ‚dS)aˆGenerate validation for the challenge. Subclasses must implement this method, but they are likely to return completely different data structures, depending on what's necessary to complete the challenge. Interpretation of that return value must be known to the caller. :param JWK account_key: :returns: Challenge-specific validation. N)ÚNotImplementedError©r0rYr^r!r!r"Ú validationÉs z$KeyAuthorizationChallenge.validation)rYÚargsr^rcOs"| |¡|j|g|¢Ri|¤ŽfS)z¼Generate response and validation. Convenience function that return results of `response` and `validation`. :param JWK account_key: :rtype: tuple )r\ra)r0rYrbr^r!r!r"Úresponse_and_validationØs ÿz1KeyAuthorizationChallenge.response_and_validationN)r#r$r%r&ÚNotImplementedrWr'r(rXrrBrRrrVrDr\ÚabcÚabstractmethodrrarrcr!r!r!r"rE¦s  ÿ   ÿrE)Ú metaclassc@s*eZdZdZdZdeejedœdd„Z dS)Ú DNS01ResponsezACME dns-01 challenge response.zdns-01ÚDNS01)rGÚdomainrHrcCs| ||¡}|st d¡|S)aìSimple verify. This method no longer checks DNS records and is a simple wrapper around `KeyAuthorizationChallengeResponse.verify`. :param challenges.DNS01 chall: Corresponding challenge. :param str domain: Domain name being verified. :param JWK account_public_key: Public key for the key pair being authorized. :return: ``True`` iff verification of the key authorization was successful. :rtype: bool ú4Verification of key authorization in response failed)rUrr)r0rGrjrHZverifiedr!r!r"Ú simple_verifyìs  zDNS01Response.simple_verifyN) r#r$r%r&rWr'rrVrArlr!r!r!r"rhçsrhc@sBeZdZdZeZejZdZej e e dœdd„Z e e dœdd„Z d S) rizACME dns-01 challenge.ú_acme-challenge©rYÚ unused_kwargsrcKs$t t | |¡ d¡¡ ¡¡ ¡S)úSGenerate validation. :param JWK account_key: :rtype: str úutf-8)rrPÚhashlibÚsha256rDrOÚdigestrS©r0rYror!r!r"ra s  ÿÿzDNS01.validation©ÚnamercCs|j›d|›�S)z{Domain name for TXT validation record. :param str name: Domain name being validated. :rtype: str rI)ÚLABEL©r0rwr!r!r"Úvalidation_domain_nameszDNS01.validation_domain_nameN)r#r$r%r&rhrXrWrxrrVrr'rarzr!r!r!r"ris  ric@s<eZdZdZdZdZdZd deej e e e e dœd d „Z dS) ÚHTTP01Responsez ACME http-01 challenge response.zhttp-01éPz NéÚHTTP01)rGrjrHÚportÚtimeoutrc Csú| ||¡st d¡dS|durF||jkrFt d|¡|d |¡7}| |¡}t d|j|¡ztj |d|d�}Wn8tj j y¬}zt  d||¡WYd}~dSd}~00d |_ t d ||j|j¡|j |j¡} |j| k�röt d |j| ¡dSd S) aêSimple verify. :param challenges.SimpleHTTP chall: Corresponding challenge. :param str domain: Domain name being verified. :param JWK account_public_key: Public key for the key pair being authorized. :param int port: Port used in the validation. :param int timeout: Timeout in seconds. :returns: ``True`` iff validation with the files currently served by the HTTP server is successful. :rtype: bool rkFNz4Using non-standard port for http-01 verification: %sz:{0}zVerifying %s at %s...)rUr€zUnable to reach %s: %sÚasciizReceived %s: %s. Headers: %szEKey authorization from response (%r) doesn't match HTTP response (%r)T)rUrrÚPORTZwarningÚformatÚurirWÚrequestsÚgetÚ exceptionsZRequestExceptionrÚencodingÚtextZheadersÚrstripÚWHITESPACE_CUTSETrD) r0rGrjrHrr€r„Z http_responserZchallenge_responser!r!r"rl/s6  ÿ  ÿ þzHTTP01Response.simple_verify)Nr})r#r$r%r&rWr‚r‹r'rrVrÚintrArlr!r!r!r"r{sÿ  ÿr{c@sTeZdZdZeZejZdZee dœdd„ƒZ e e dœdd„Z e j ee d œd d „Zd S) r~zACME http-01 challenge.z.well-known/acme-challenger,cCsd|jd| d¡S)zQPath (starting with '/') for provisioned resource. :rtype: str ú/r6)Ú URI_ROOT_PATHrOr4r!r!r"Úpathqsz HTTP01.path)rjrcCsd||jS)zïCreate an URI to the provisioned resource. Forms an URI to the HTTPS server provisioned resource (containing :attr:`~SimpleHTTP.token`). :param str domain: Domain name being verified. :rtype: str zhttp://)r�)r0rjr!r!r"r„zs z HTTP01.urirncKs | |¡S)rpr[rur!r!r"ra†szHTTP01.validationN)r#r$r%r&r{rXrWrŽr@r'r�r„rrVrrar!r!r!r"r~hs r~c @sºeZdZdZdZdZdZdZee dœdd„ƒZ de e e jeee je jfd œd d „Zde e e e ee jdœdd„Ze e jedœdd„Zdde eje e je e e eedœdd„Zd S)ÚTLSALPN01Responsez$ACME tls-alpn-01 challenge response.z tls-alpn-01i»s1.3.6.1.5.5.7.1.30.1s acme-tls/1r,cCst |j d¡¡ ¡S)z*Hash value stored in challenge certificaterq)rrrsrDrOrtr4r!r!r"Úh szTLSALPN01Response.hNé)rjÚkeyÚbitsrcCs\|durt ¡}| tj|¡dt |jd¡}tj|jd|d�}t j ||gd|gd�|fS)a©Generate tls-alpn-01 certificate. :param str domain: Domain verified by the challenge. :param OpenSSL.crypto.PKey key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :param int bits: Number of bits for newly generated key. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` NsDER:ÚhexT)ZcriticalÚvalue)Z force_sanÚ extensions) r ÚPKeyZ generate_keyZTYPE_RSAÚcodecsrOr‘Z X509ExtensionÚID_PE_ACME_IDENTIFIER_V1rZ gen_ss_cert)r0rjr“r”Z der_valueZacme_extensionr!r!r"Úgen_cert¥s ÿ ÿÿzTLSALPN01Response.gen_cert)rjÚhostrrcCsL|dur t |¡}t d||¡|dur.|j}tj| ¡|| ¡|jgd�S)zðProbe tls-alpn-01 challenge certificate. :param str domain: domain being validated, required. :param str host: IP address used to probe the certificate. :param int port: Port used to probe the certificate. Nz%s resolved to %s)rœrrwZalpn_protocols) ÚsocketZ gethostbynamerrr‚rZ probe_snirOÚACME_TLS_1_PROTOCOL)r0rjrœrr!r!r"Ú probe_cert½s  ÿzTLSALPN01Response.probe_cert)rjÚcertrcCs„t |¡}t d| d¡|¡t|ƒdks>|d ¡| ¡krBdSt| ¡ƒD]0}|  |¡}|  ¡dkrN|  ¡}||j kSqNdS)aVerify tls-alpn-01 challenge certificate. :param str domain: Domain name being validated. :param OpensSSL.crypto.X509 cert: Challenge certificate. :returns: Whether the certificate was successfully verified. :rtype: bool zCertificate %s. SANs: %srsrLrFsUNDEF) rZ _pyopenssl_cert_or_req_all_namesrrrtrNÚlowerÚrangeZget_extension_countZ get_extensionZget_short_nameÚget_datar‘)r0rjr ÚnamesÚiÚextÚdatar!r!r"Ú verify_certÏs  ÿ   zTLSALPN01Response.verify_certÚ TLSALPN01)rGrjrHr rœrrc Cs~| ||¡st d¡dS|durrz|j|||d�}Wn:tjyp}z tjt|ƒdd�WYd}~dSd}~00| ||¡S)aäSimple verify. Verify ``validation`` using ``account_public_key``, optionally probe tls-alpn-01 certificate and check using `verify_cert`. :param .challenges.TLSALPN01 chall: Corresponding challenge. :param str domain: Domain name being validated. :param JWK account_public_key: :param OpenSSL.crypto.X509 cert: Optional certificate. If not provided (``None``) certificate will be retrieved using `probe_cert`. :param string host: IP address used to probe the certificate. :param int port: Port used to probe the certificate. :returns: ``True`` if and only if client's control of the domain has been verified. :rtype: bool rkFN)rjrœrT)Úexc_info)rUrrrŸrÚErrorr'r¨)r0rGrjrHr rœrrr!r!r"rlís  zTLSALPN01Response.simple_verify)Nr’)NN)NNN)r#r$r%r&rWr‚ršržr@r?r‘r'rr r˜rŒrÚX509r›rŸrAr¨rrVrlr!r!r!r"r��s,ÿ ÿ  ÿ þ þr�c@sLeZdZdZeZejZeje e e j e j fdœdd„Zeedœdd„ƒZdS) r©zACME tls-alpn-01 challenge.r]cKs,tt| |¡ƒj| d¡tt| d¡ƒd�S)a€Generate validation. :param JWK account_key: :param str domain: Domain verified by the challenge. :param OpenSSL.crypto.PKey cert_key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` Zcert_keyrj)r“rj)rr�r\r›r†r'r`r!r!r"ras þzTLSALPN01.validationr,cCsttjdƒottjdƒS)ai Check if TLS-ALPN-01 challenge is supported on this machine. This implies that a recent version of OpenSSL is installed (>= 1.0.2), or a recent cryptography version shipped with the OpenSSL library is installed. :returns: ``True`` if TLS-ALPN-01 is supported on this machine, ``False`` otherwise. :rtype: bool Zset_alpn_protosZset_alpn_select_callback)Úhasattrr Z ConnectionZContextr!r!r!r"Ú is_supported(s  ÿzTLSALPN01.is_supportedN)r#r$r%r&r�rXrWrrVrrr r¬r˜raÚ staticmethodrAr®r!r!r!r"r©s  r©c@sreZdZdZdZdZejfejej e ej dœdd„Z ej eje dœdd „Zeje d d œd d „Zeedœdd„ZdS)ÚDNSzACME "dns" challenge.Údnsrm)rYÚalgr^rcKs(tjjf|jdd� d¡||dœ|¤ŽS)z·Generate validation. :param .JWK account_key: Private account key. :param .JWA alg: :returns: This challenge wrapped in `.JWS` :rtype: .JWS T)Z sort_keysrq)Úpayloadr“r²)rÚJWSÚsignZ json_dumpsrO)r0rYr²r^r!r!r"Úgen_validation?s þþzDNS.gen_validation)rarHrc Csb|j|d�sdSz|| |j d¡¡kWStjy\}zt d|¡WYd}~dSd}~00dS)zwCheck validation. :param JWS validation: :param JWK account_public_key: :rtype: bool )r“Frqz&Checking validation for DNS failed: %sN)rUZ json_loadsr³rSrZDeserializationErrorrr)r0rarHrr!r!r"Úcheck_validationNs  ÿ zDNS.check_validationÚ DNSResponser]cKst|j|fi|¤Žd�S)z‰Generate response. :param .JWK account_key: Private account key. :param .JWA alg: :rtype: DNSResponse )ra)r¸r¶r`r!r!r"Ú gen_response_s zDNS.gen_responservcCsd |j|¡S)zgDomain name for TXT validation record. :param str name: Domain name being validated. z{0}.{1})rƒrxryr!r!r"rzjszDNS.validation_domain_nameN)r#r$r%r&rWrxrZRS256rVZ JWASignaturerr´r¶rAr·r¹r'rzr!r!r!r"r°7sÿ  r°c@sFeZdZUdZdZejdejjd�Z eje d<dej e dœdd„Z d S) r¸z@ACME "dns" challenge response. :param JWS validation: r±ra)r9r°rFcCs| |j|¡S)z~Check validation. :param challenges.DNS chall: :param JWK account_public_key: :rtype: bool )r·ra)r0rGrHr!r!r"r·~s zDNSResponse.check_validationN)r#r$r%r&rWrr<r´rrar(rVrAr·r!r!r!r"r¸ss r¸)1r&rer™r=rrZloggingr�Útypingrrrrrrrr r Zcryptography.hazmat.primitivesr ZjosepyrZOpenSSLr r r…ZacmerrZ getLoggerr#rrZTypedJSONObjectWithFieldsrr+rr5rBÚABCMetarEÚregisterrhrir{r~r�r©r°r¸r!r!r!r"Ús^                 2AH'%;