a ‚oe¢yã@s>dZddlZddlZddlmZddlmZddlZddl Z ddl Z ddl m Z ddl m Z ddl mZddl mZddl mZdd l mZdd l mZdd l mZddlZddlZddlZdd lmZdd lmZddlmZddlmZddlmZddlm Z ddlm!Z!e "e#¡Z$dZ%Gdd„dƒZ&Gdd„dƒZ'dS)zACME client API.éN)Ú parsedate_tz)ÚAny)Úcast)ÚList)ÚMapping)ÚOptional)ÚSet)ÚTuple)ÚUnion)Ú HTTPAdapter)Úparse_header_links)Ú challenges)Ú crypto_util)Úerrors)Újws)Úmessagesé-c@s€eZdZdZejdddœdd„Zejejdœdd „Z ejejd œd d „Z dNeje ej ejd œdd„Z dOejeejdœdd„Zeejdœdd„Zejeejejfdœdd„ZdPeje ejejdœdd„Zejejejdœdd„Zejejdœd d!„ZdQejejeejd"œd#d$„ZdRejejeejd"œd%d&„Zeje dd'œd(d)„Z!ed*œd+d,„Z"e#e#ejd-œd.d/„Z$eje%e&e%d0œd1d2„Z'e(e%dejd3œd4d5„ƒZ)e(dSeje e%e e%ejd6œd7d8„ƒZ*ejej ejd9œd:d;„Z+e#e#ejd-œdd?„Z-ejejdœd@dA„Z.dTeje ej/e e%ejdBœdCdD„Z0ej1e2j3ej4dEœdFdG„Z5e(eje ejdHœdIdJ„ƒZ6eje e%ddKœdLdM„Z7dS)UÚClientV2zuACME client for a v2 API. :ivar messages.Directory directory: :ivar .ClientNetwork net: Client network. Ú ClientNetworkN)Ú directoryÚnetÚreturncCs||_||_dS)z‰Initialize. :param .messages.Directory directory: Directory Resource :param .ClientNetwork net: Client network. N)rr)Úselfrr©rú,C:\Program Files\Certbot\pkgs\acme\client.pyÚ__init__*szClientV2.__init__)Ú new_accountrcCsL| |jd|¡}|jdkr6d|jvr6t |jd¡‚| |¡}||j_|S)zÖRegister. :param .NewRegistration new_account: :raises .ConflictError: in case the account already exists :returns: Registration Resource. :rtype: `.RegistrationResource` Ú newAccountéÈÚLocation) Ú_postrÚ status_codeÚheadersrÚ ConflictErrorÚ_regr_from_responserÚaccount)rrÚresponseÚregrrrrr3s  zClientV2.new_account)r'rcCs| |d¡|j_|jjS)zŠQuery server about registration. :param messages.RegistrationResource regr: Existing Registration Resource. T)Ú_get_v2_accountrr%©rr'rrrÚquery_registrationFszClientV2.query_registration)r'ÚupdatercCsJ| |¡}|dur|jn|}tjfit|ƒ¤Ž}|j||d�}||j_|S)aKUpdate registration. :param messages.RegistrationResource regr: Registration Resource. :param messages.Registration update: Updated body of the resource. If not provided, body will be taken from `regr`. :returns: Updated Registration Resource. :rtype: `.RegistrationResource` N©Úbody)r(r-rZUpdateRegistrationÚdictÚ_send_recv_regrrr%)rr'r+r-Z updated_regrrrrÚupdate_registrationRs  zClientV2.update_registrationF)r'Ú update_bodyrcCsbd|j_|jjdd�}| |jd|¡}|jd}|j|rJtj  |  ¡¡n|j|d�}||j_|S)NT)Zonly_return_existingrr©r-Úuri) rr%r-r+r rr"rÚ RegistrationÚ from_jsonÚjson)rr'r1Zonly_existing_regr&Z updated_uriZnew_regrrrrr(hs ÿþzClientV2._get_v2_account)Úcsr_pemrc CsÜtj tjj|¡}t |¡}t |¡}g}|D]}| tj tj |d�¡q.|D]}| tj tj |d�¡qNtj |d�}|  |jd|¡} tj |  ¡¡} g} | jD]} |  |j| | ¡| d�¡q¢tj| | j d¡| |d�S)z²Request a new Order object from the server. :param bytes csr_pem: A CSR in PEM format. :returns: The newly created order. :rtype: OrderResource )ÚtypÚvalue)Ú identifiersZnewOrder©r3r)r-r3Úauthorizationsr7)ÚOpenSSLÚcryptoÚload_certificate_requestÚ FILETYPE_PEMrZ _pyopenssl_cert_or_req_all_namesZ_pyopenssl_cert_or_req_san_ipÚappendrÚ IdentifierZIDENTIFIER_FQDNZ IDENTIFIER_IPZNewOrderr rÚOrderr5r6r<Ú_authzr_from_responseÚ _post_as_getÚ OrderResourcer"Úget) rr7ÚcsrZdnsNamesZipNamesr:ÚnameZipsÚorderr&r-r<ÚurlrrrÚ new_orderts0   ÿ  ÿ    üzClientV2.new_order)ÚauthzrrcCs(| |j¡}| ||jj|j¡}||fS)aPoll Authorization Resource for status. :param authzr: Authorization Resource :type authzr: `.AuthorizationResource` :returns: Updated Authorization Resource and HTTP response. :rtype: (`.AuthorizationResource`, `requests.Response`) )rEr3rDr-Ú identifier)rrMr&Zupdated_authzrrrrÚpoll—s  ÿz ClientV2.poll)ÚorderrÚdeadlinercCs6|durtj ¡tjdd�}| ||¡}| ||¡S)adPoll authorizations and finalize the order. If no deadline is provided, this method will timeout after 90 seconds. :param messages.OrderResource orderr: order to finalize :param datetime.datetime deadline: when to stop polling and timeout :returns: finalized order :rtype: messages.OrderResource NéZ©Úseconds)ÚdatetimeÚnowÚ timedeltaÚpoll_authorizationsÚfinalize_order)rrPrQrrrÚpoll_and_finalize¨s zClientV2.poll_and_finalizecCsÎg}|jjD]L}tj ¡|kr |j| |¡|d�}|jjtjkrL|  |¡q t   d¡qq t |ƒt |jjƒkrvt  ¡‚g}|D]4}|jjtjkr~|jjD]}|jdur˜|  |¡q˜q~|rÂt  |¡‚|j|d�S)zPoll Order Resource for status.r;éN)r<)r-r<rUrVrDrEÚstatusrZSTATUS_PENDINGrAÚtimeÚsleepÚlenrÚ TimeoutErrorÚ STATUS_VALIDr ÚerrorZValidationErrorr+)rrPrQZ responsesrKrMZfailedZchallrrrrX»s&     zClientV2.poll_authorizations)rPrcCsRtj tjj|j¡}tjt |¡d�}|  |j j |¡}|j tj  | ¡¡d�}|S)aStart the process of finalizing an order. :param messages.OrderResource orderr: order to finalize :param datetime.datetime deadline: when to stop polling and timeout :returns: updated order :rtype: messages.OrderResource )rHr,)r=r>r?r@r7rZCertificateRequestÚjoseÚComparableX509r r-Úfinalizer+rCr5r6)rrPrHZ wrapped_csrÚresrrrÚbegin_finalizationÔs  ÿzClientV2.begin_finalization)rPrQÚfetch_alternative_chainsrc sÔtj ¡|krÈt d¡ˆ |j¡}tj |  ¡¡}|j tj krb|j durVt  |j ¡‚t  d¡‚q|j tjkr|jdurˆ |j¡}|j||jd�}|rˆ |d¡}‡fdd„|Dƒ}|j|d�}|Sqt  ¡‚dS) zÙ Poll an order that has been finalized for its status. If it becomes valid, obtain the certificate. :returns: finalized order (with certificate) :rtype: messages.OrderResource r[NzPThe certificate order failed. No further information was provided by the server.)r-Z fullchain_pemZ alternatecsg|]}ˆ |¡j‘qSr)rEÚtext)Ú.0rK©rrrÚ óz.ClientV2.poll_finalization..)Zalternative_fullchains_pem)rUrVr]r^rEr3rrCr5r6r\ZSTATUS_INVALIDrbrZ IssuanceErrorÚErrorraÚ certificater+riÚ _get_linksr`) rrPrQrhr&r-Zcertificate_responseZalt_chains_urlsZ alt_chainsrrkrÚpoll_finalizationås&      ÿ   zClientV2.poll_finalizationcCs| |¡| |||¡S)a{Finalize an order and obtain a certificate. :param messages.OrderResource orderr: order to finalize :param datetime.datetime deadline: when to stop polling and timeout :param bool fetch_alternative_chains: whether to also fetch alternative certificate chains :returns: finalized order :rtype: messages.OrderResource )rgrq)rrPrQrhrrrrYs zClientV2.finalize_order)ÚcertÚrsnrcCs| |||jd¡dS)aRevoke certificate. :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in `.ComparableX509` :param int rsn: Reason code for certificate revocation. :raises .ClientError: If revocation is unsuccessful. Z revokeCertN)Ú_revoker)rrrrsrrrÚrevokes zClientV2.revoke©rcCs$t|jdƒo"t|jjdƒo"|jjjS)zGChecks if ACME server requires External Account Binding authentication.ÚmetaÚexternal_account_required)Úhasattrrrwrxrkrrrrx"s   ÿþz"ClientV2.external_account_required©ÚargsÚkwargsrcOs,|dd…d|dd…}|j|i|¤ŽS)z Send GET request using the POST-as-GET protocol. :param args: :param kwargs: :return: Nr[©N)r )rr{r|Únew_argsrrrrE(szClientV2._post_as_get)r&Ú relation_typercs.d|jvrgSt|jdƒ}‡fdd„|DƒS)zÖ Retrieves all Link URIs of relation_type from the response. :param requests.Response response: The requests HTTP response. :param str relation_type: The relation type to filter by. ZLinkcs0g|](}d|vrd|vr|dˆkr|d‘qS)ÚrelrKr)rjÚl©rrrrl=sÿz'ClientV2._get_links..)r"r )rr&rÚlinksrr‚rrp2s zClientV2._get_links)rKrrcCstj | |¡ ¡¡S)aB Retrieves the ACME directory (RFC 8555 section 7.1.1) from the ACME server. :param str url: the URL where the ACME directory is available :param ClientNetwork net: the ClientNetwork to use to make the request :returns: the ACME directory object :rtype: messages.Directory )rÚ Directoryr5rGr6)ÚclsrKrrrrÚ get_directory@s zClientV2.get_directory)r&r3Úterms_of_servicercCs>d|jvr|jdd}tjtj | ¡¡|j d|¡|d�S)Nzterms-of-servicerKr)r-r3r‡)rƒrÚRegistrationResourcer4r5r6r"rG)r…r&r3r‡rrrr$Ls  ýzClientV2._regr_from_response)r'r-rcCs"| |j|¡}|j||j|jd�S)N)r3r‡)r r3r$r‡)rr'r-r&rrrr/Xs þzClientV2._send_recv_regrcOs&| dt|jdƒ¡|jj|i|¤ŽS)zŠWrapper around self.net.post that adds the newNonce URL. This is used to retry the request in case of a badNonce error. Ú new_nonce_urlZnewNonce)Ú setdefaultÚgetattrrrÚpost©rr{r|rrrr fszClientV2._postcCs| |tj dddœ¡¡S)zúDeactivate registration. :param messages.RegistrationResource regr: The Registration Resource to be deactivated. :returns: The Registration resource that was deactivated. :rtype: `.RegistrationResource` Ú deactivatedN)r\Zcontact)r0rr4r5r)rrrÚdeactivate_registrationos ÿz ClientV2.deactivate_registrationcCs.tjdd�}| |j|¡}| ||jj|j¡S)aDeactivate authorization. :param messages.AuthorizationResource authzr: The Authorization resource to be deactivated. :returns: The Authorization resource that was deactivated. :rtype: `.AuthorizationResource` rŽ)r\)rZUpdateAuthorizationr r3rDr-rN)rrMr-r&rrrÚdeactivate_authorization}s  ÿz!ClientV2.deactivate_authorization)r&rNr3rcCsFtjtj | ¡¡|j d|¡d�}|durB|jj|krBt   |¡‚|S)Nrr2) rÚAuthorizationResourceZ Authorizationr5r6r"rGr-rNrÚUnexpectedUpdate)rr&rNr3rMrrrrDŽs þ zClientV2._authzr_from_response)Úchallbr&rcCst| |j|¡}z|jdd}Wnty<t d¡‚Yn0tj|tj  |  ¡¡d�}|j|jkrpt  |j¡‚|S)ahAnswer challenge. :param challb: Challenge Resource body. :type challb: `.ChallengeBody` :param response: Corresponding Challenge response :type response: `.challenges.ChallengeResponse` :returns: Challenge Resource with updated body. :rtype: `.ChallengeResource` :raises .UnexpectedUpdate: ZuprKz"up" Link header missing)Ú authzr_urir-) r r3rƒÚKeyErrorrÚ ClientErrorrÚChallengeResourceÚ ChallengeBodyr5r6r’)rr“r&Zrespr”ZchallrrrrÚanswer_challenge˜s þ  zClientV2.answer_challenge)r&Údefaultrc Cs®|j dt|ƒ¡}z t|ƒ}Wnxty–t|ƒ}|durŽz:t |ddurV|dnd¡}tj|dd…Ž|WYSttfyŒYn0|}Yn0tj  ¡tj|d�S)aüCompute next `poll` time based on response ``Retry-After`` header. Handles integers and various datestring formats per https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.37 :param requests.Response response: Response from `poll`. :param int default: Default value (in seconds), used when ``Retry-After`` header is not present or invalid. :returns: Time point when next `poll` should be performed. :rtype: `datetime.datetime` z Retry-AfterNéÿÿÿÿrérS) r"rGÚstrÚintÚ ValueErrorrrUrWÚ OverflowErrorrV)r…r&ršÚ retry_afterrTZwhenZtz_secsrrrr¡µs   zClientV2.retry_after)rrrsrKrcCs0| |tj||d�¡}|jtjkr,t d¡‚dS)a.Revoke certificate. :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in `.ComparableX509` :param int rsn: Reason code for certificate revocation. :param str url: ACME URL to post to :raises .ClientError: If revocation is unsuccessful. )roÚreasonz0Successful revocation must return HTTP OK statusN)r rZ Revocationr!Ú http_clientZOKrr–)rrrrsrKr&rrrrtÕs þÿ ÿzClientV2._revoke)N)F)N)F)F)NN)NN)8Ú__name__Ú __module__Ú __qualname__Ú__doc__rr„rZNewRegistrationrˆrr*rr4r0Úboolr(ÚbytesrFrLr‘r ÚrequestsÚResponserOrUrZrXrgrqrYrcrdržrurxrrEr�rrpÚ classmethodr†r$r/r r�r�rBrDr˜r ZChallengeResponser—r™r¡rtrrrrr#s’ ÿ ÿþ ÿ #ÿ ÿ ÿ ÿ ÿ þý !ÿ ÿ    ÿ þ ÿ  ÿ þ þ þ ÿ rc @s2eZdZdZdZdZdZdZdej dde fej e e jejeeedd œd d „Zdd œd d„Zejeeedœdd„Zed)eje eejdœdd„ƒZeeeeejdœdd„Zeeejdœdd„Zefeeeejdœdd„Zejddœdd „Zeeed!œd"d#„Z eeejdœd$d%„Z!efeejeeejd&œd'd(„Z"dS)*rzvWrapper around requests that signs POSTs for authentication. Also adds user agent, and handles Content-Type. zapplication/jsonzapplication/jose+jsonzapplication/problem+jsonz Replay-NonceNTz acme-python)Úkeyr%ÚalgÚ verify_sslÚ user_agentÚtimeoutrcCs\||_||_||_||_tƒ|_||_t ¡|_ ||_ t ƒ}|j   d|¡|j   d|¡dS)Nzhttp://zhttps://) r­r%r®r¯ÚsetÚ_noncesr°rªZSessionÚsessionÚ_default_timeoutr Zmount)rr­r%r®r¯r°r±Zadapterrrrrs zClientNetwork.__init__rvcCs&z|j ¡Wnty Yn0dSr})r´ÚcloseÚ ExceptionrkrrrÚ__del__s zClientNetwork.__del__)ÚobjÚnoncerKrcCs~|r|jdd� ¡nd}t d|¡|j||dœ}|jdurJ|jd|d<|j|d <tjj |fit t t t f|ƒ¤Žjdd�S) zþWrap `JSONDeSerializable` object in JWS. .. todo:: Implement ``acmePath``. :param josepy.JSONDeSerializable obj: :param str url: The URL to which this object will be POSTed :param str nonce: :rtype: str é)ÚindentrmzJWS payload: %s)r®rºrKNr3Zkidr­)Z json_dumpsÚencodeÚloggerÚdebugr®r%r­rZJWSÚsignrrr�r)rr¹rºrKÚjobjr|rrrÚ _wrap_in_jwss  ý  zClientNetwork._wrap_in_jws)r&Ú content_typerc Cs$|j d¡}|r"| d¡d ¡}z | ¡}WntyDd}Yn0|jdkrdt |j dd¡¡‚|j sÜ|durÐ||j krˆt   d|¡zt j |¡‚WqÚtjyÌ}zt ||f¡‚WYd}~qÚd}~00n t |¡‚nD|durú||jkrút   d |¡||jk�r |du�r t d |›�¡‚|S) a¿Check response content and its type. .. note:: Checking is not strict: wrong server response ``Content-Type`` HTTP header is ignored if response is an expected JSON object (c.f. Boulder #56). :param str content_type: Expected Content-Type response header. If JSON is expected and not present in server response, this function will raise an error. Otherwise, wrong Content-Type is ignored, but logged. :raises .messages.Error: If server response body carries HTTP Problem (https://datatracker.ietf.org/doc/html/rfc7807). :raises .ClientError: In case of other networking errors. ú Content-Typeú;rNi™rzUNKNOWN-LOCATIONz/Ignoring wrong Content-Type (%r) for JSON Errorz®sÿz.ClientNetwork._send_request..)r¾r¿r¯rŠr°rµr´ZrequestrªÚ exceptionsZRequestExceptionÚreÚmatchr�ÚgroupsrŸÚbase64Z b64encodeZcontentÚencodingrir!Újoinr"Úitems)rrÍrKr{r|r&ÚeZ err_regexÚmÚhostÚpathZ_err_noÚerr_msgZ debug_contentrrrÚ _send_requestls<ÿ   . ÿüzClientNetwork._send_requestrzcOs|jdg|¢Ri|¤ŽS)aSend HEAD request without checking the response. Note, that `_check_response` is not called, as it is expected that status code other than successfully 2xx will be returned, or messages2.Error will be raised by the server. ZHEAD)rãr�rrrÚhead³szClientNetwork.head)rKrÃr|rcKs|j|jd|fi|¤Ž|d�S)z$Send GET request and check response.ZGET©rÃ)rÌrã)rrKrÃr|rrrrG½sÿzClientNetwork.get)r&rc CsŠ|j|jvr||j|j}ztjjd |¡}Wn2tjy`}zt  ||¡‚WYd}~n d}~00t   d|¡|j   |¡n t |¡‚dS)NrºzStoring nonce: %s)ÚREPLAY_NONCE_HEADERr"rZHeaderÚ_fieldsÚdecodercrÊrZBadNoncer¾r¿r³ÚaddZ MissingNonce)rr&rºZ decoded_noncerbrrrÚ _add_nonceÃs  " zClientNetwork._add_nonce)rKr‰rcCsL|jsBt d¡|dur$| |¡}n|j| |¡dd�}| |¡|j ¡S)NzRequesting fresh noncerå)r³r¾r¿rärÌrêÚpop)rrKr‰r&rrrÚ _get_nonceÏs   zClientNetwork._get_noncec Osrz|j|i|¤ŽWStjyl}z@|jdkrVt d|¡|j|i|¤ŽWYd}~S‚WYd}~n d}~00dS)z�POST object wrapped in `.JWS` and check response. If the server responded with a badNonce error, the request will be retried once. ZbadNoncez Retrying request after error: %sN)Ú _post_oncerrnÚcoder¾r¿)rr{r|rbrrrrŒÚs  zClientNetwork.post)rKr¹rÃr|rcKsf| dd¡}| || ||¡|¡}| dd|i¡|jd|fd|i|¤Ž}|j||d�}| |¡|S)Nr‰r"rÄrÎrÏrå)rërÂrìrŠrãrÌrê)rrKr¹rÃr|r‰rÏr&rrrríés  zClientNetwork._post_once)N)#r¤r¥r¦r§rËZJOSE_CONTENT_TYPErÉrærcZRS256ÚDEFAULT_NETWORK_TIMEOUTZJWKrrrˆZ JWASignaturer¨r�ržrr¸ZJSONDeSerializablerÂr¬rªr«rÌrrãrärGrêrìrŒrírrrrrës> þþ ÿ ÿ:G ÿ   ÿÿr)(r§rÚrUZ email.utilsrZ http.clientZclientr£Zloggingr×r]Útypingrrrrrrr r Zjosepyrcr=rªZrequests.adaptersr Zrequests.utilsr Zacmer rrrrZ getLoggerr¤r¾rïrrrrrrÚs@                  K