a }|g"z@sJdZddlZddlZddlmZddlmZddlZddl Z ddl Z ddl m Z ddl m Z ddl mZddl mZddl mZdd l mZdd l mZdd l mZdd lmZddlZddlZddlZdd lmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#e$e%Z&dZ'GdddZ(GdddZ)dS)zACME client API.N) parsedate_tz)Any)cast)List)Mapping)Optional)Set)Tuple)Union)x509) HTTPAdapter)parse_header_links) challenges) crypto_util)errors)jws)messages-c@seZdZdZejdddddZejejddd Z ejejd d d Z dNeje ej ejd ddZ dOejeejdddZeejdddZejeejejfdddZdPeje ejejdddZejejejdddZejejdd 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%d0d1d2Z'e(e%dejd3d4d5Z)e(dSeje e%e e%ejd6d7d8Z*ejej ejd9d:d;Z+e#e#ejd-dd?Z-ejejdd@dAZ.dTeje ej/e e%ejdBdCdDZ0ej1e2j3ej4dEdFdGZ5e(eje ejdHdIdJZ6eje e%ddKdLdMZ7dS)UClientV2zuACME client for a v2 API. :ivar messages.Directory directory: :ivar .ClientNetwork net: Client network. ClientNetworkN) directorynetreturncCs||_||_dS)zInitialize. :param .messages.Directory directory: Directory Resource :param .ClientNetwork net: Client network. N)rr)selfrrr//usr/lib/python3.9/site-packages/acme/client.py__init__,szClientV2.__init__) new_accountrcCsL||jd|}|jdkr6d|jvr6t|jd||}||j_|S)zRegister. :param .NewRegistration new_account: :raises .ConflictError: in case the account already exists :returns: Registration Resource. :rtype: `.RegistrationResource` newAccountLocation) _postr status_codeheadersr ConflictError_regr_from_responseraccount)rrresponseregrrrrr5s  zClientV2.new_account)r(rcCs||d|j_|jjS)zQuery server about registration. :param messages.RegistrationResource regr: Existing Registration Resource. T)_get_v2_accountrr&rr(rrrquery_registrationHszClientV2.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` Nbody)r)r.rZUpdateRegistrationdict_send_recv_regrrr&)rr(r,r.Z updated_regrrrrupdate_registrationTs  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_jsonjson)rr(r2Zonly_existing_regr'Z updated_uriZnew_regrrrrr)js zClientV2._get_v2_account)csr_pemrcCst|}t|j|j}z|jtj}WntjyDg}Yn0|j tj }g}|D]}| t jt j|dq\|D]}| t jt jt|dq|t j|d} ||jd| } t j| } g} | jD]} | |j|| | dqt j| | jd| |dS)zRequest a new Order object from the server. :param bytes csr_pem: A CSR in PEM format. :returns: The newly created order. :rtype: OrderResource )typvalue) identifiersZnewOrderr4r )r.r4authorizationsr8)r Zload_pem_x509_csrrZ%get_names_from_subject_and_extensionsZsubject extensionsZget_extension_for_classZSubjectAlternativeNameZExtensionNotFoundr:Zget_values_for_typeZ IPAddressappendr IdentifierZIDENTIFIER_FQDNZ IDENTIFIER_IPstrZNewOrderr!rOrderr6r7r=_authzr_from_response _post_as_get OrderResourcer#get)rr8csrZdnsNamesZsan_extZipNamesr;nameiporderr'r.r=urlrrr new_ordervs8         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`) )rDr4rCr. identifier)rrMr'Zupdated_authzrrrrpolls  z ClientV2.poll)orderrdeadlinercCs6|durtjtjdd}|||}|||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 NZseconds)datetimenow timedeltapoll_authorizationsfinalize_order)rrPrQrrrpoll_and_finalizes zClientV2.poll_and_finalizecCsg}|jjD]L}tj|kr |j|||d}|jjtjkrL| |q t dqq t |t |jjkrvt g}|D]4}|jjtjkr~|jjD]}|jdur| |qq~|rt ||j|dS)zPoll Order Resource for status.r<N)r=)r.r=rUrVrCrDstatusrZSTATUS_PENDINGr?timesleeplenr TimeoutError STATUS_VALIDrerrorZValidationErrorr,)rrPrQZ responsesrKrMZfailedZchallrrrrXs&     zClientV2.poll_authorizations)rPrcCsRtjtjj|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 )rGr-)OpenSSLZcryptoZload_certificate_requestZ FILETYPE_PEMr8rZCertificateRequestjoseComparableX509r!r.finalizer,rBr6r7)rrPrGZ wrapped_csrresrrrbegin_finalizations  zClientV2.begin_finalization)rPrQfetch_alternative_chainsrc stj|krtd|j}tj| }|j tj krb|j durVt |j t dq|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_pem alternatecsg|]}|jqSr)rDtext).0rKrrr z.ClientV2.poll_finalization..)Zalternative_fullchains_pem)rUrVr]r^rDr4rrBr6r7r\ZSTATUS_INVALIDrbrZ IssuanceErrorErrorra certificater,rk _get_linksr`) rrPrQrir'r.Zcertificate_responseZalt_chains_urlsZ alt_chainsrrmrpoll_finalizations&         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 )rhrs)rrPrQrirrrrY s zClientV2.finalize_order)certrsnrcCs||||jddS)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)rrtrurrrrevokes zClientV2.revokercCs$t|jdo"t|jjdo"|jjjS)zGChecks if ACME server requires External Account Binding authentication.metaexternal_account_required)hasattrrryrzrmrrrrz's   z"ClientV2.external_account_requiredargskwargsrcOs,|ddd|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_argsrrrrD-szClientV2._post_as_get)r' relation_typercs.d|jvrgSt|jd}fdd|DS)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|dkr|dqS)relrKr)rllrrrrnBsz'ClientV2._get_links..)r#r )rr'rlinksrrrrr7s 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 Directoryr6rFr7)clsrKrrrr get_directoryEs zClientV2.get_directory)r'r4terms_of_servicercCs>d|jvr|jdd}tjtj||jd||dS)Nzterms-of-servicerKr )r.r4r)rrRegistrationResourcer5r6r7r#rF)rr'r4rrrrr%Qs  zClientV2._regr_from_response)r(r.rcCs"||j|}|j||j|jdS)N)r4r)r!r4r%r)rr(r.r'rrrr0]s zClientV2._send_recv_regrcOs&|dt|jd|jj|i|S)zWrapper 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) setdefaultgetattrrrpostrr}r~rrrr!kszClientV2._postcCs||tjdddS)zDeactivate registration. :param messages.RegistrationResource regr: The Registration Resource to be deactivated. :returns: The Registration resource that was deactivated. :rtype: `.RegistrationResource` deactivatedN)r\Zcontact)r1rr5r6r*rrrdeactivate_registrationts z ClientV2.deactivate_registrationcCs.tjdd}||j|}|||jj|jS)aDeactivate authorization. :param messages.AuthorizationResource authzr: The Authorization resource to be deactivated. :returns: The Authorization resource that was deactivated. :rtype: `.AuthorizationResource` r)r\)rZUpdateAuthorizationr!r4rCr.rN)rrMr.r'rrrdeactivate_authorizations  z!ClientV2.deactivate_authorization)r'rNr4rcCsFtjtj||jd|d}|durB|jj|krBt ||S)Nr r3) rAuthorizationResourceZ Authorizationr6r7r#rFr.rNrUnexpectedUpdate)rr'rNr4rMrrrrCs  zClientV2._authzr_from_response)challbr'rcCst||j|}z|jdd}Wnty<tdYn0tj|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!r4rKeyErrorr ClientErrorrChallengeResource ChallengeBodyr6r7r)rrr'ZresprZchallrrrranswer_challenges   zClientV2.answer_challenge)r'defaultrc Cs|jdt|}z t|}Wnxtyt|}|durz:t|ddurV|dnd}tj|dd|WYSttfyYn0|}Yn0tj tj|dS)aCompute 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-AfterNrrS) r#rFrAint ValueErrorrrUrW OverflowErrorrV)rr'r retry_afterrTZwhenZtz_secsrrrrs   zClientV2.retry_after)rtrurKrcCs0||tj||d}|jtjkr,tddS)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. )rqreasonz0Successful revocation must return HTTP OK statusN)r!rZ Revocationr" http_clientZOKrr)rrtrurKr'rrrrvs  zClientV2._revoke)N)F)N)F)F)NN)NN)8__name__ __module__ __qualname____doc__rrrZNewRegistrationrrr+rr5r1boolr)bytesrErLrr requestsResponserOrUrZrXrhrsrYrdrerrwrzrrDrArrr classmethodrr%r0r!rrr@rCrrZChallengeResponserrrrvrrrrr%s    &     !             rc @s2eZdZdZdZdZdZdZdej dde fej e e jejeeedd d d Zdd d dZejeeedddZed)eje eejdddZeeeeejdddZeeejdddZefeeeejdddZejdddd Zeeed!d"d#Z eeejdd$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_agenttimeoutrcCs\||_||_||_||_t|_||_t|_ ||_ t }|j d||j d|dS)Nzhttp://zhttps://) rr&rrset_noncesrrZSessionsession_default_timeoutr Zmount)rrr&rrrrZadapterrrrrs zClientNetwork.__init__rxcCs&z|jWnty Yn0dSr)rclose Exceptionrmrrr__del__s zClientNetwork.__del__)objnoncerKrcCs~|r|jddnd}td||j||d}|jdurJ|jd|d<|j|d <tjj |fit t t t f|jddS) zWrap `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 )indentrozJWS payload: %s)rrrKNr4Zkidr)Z json_dumpsencodeloggerdebugrr&rrZJWSsignrrrAr)rrrrKjobjr~rrr _wrap_in_jwss    zClientNetwork._wrap_in_jws)r' content_typerc Cs$|jd}|r"|dd}z |}WntyDd}Yn0|jdkrdt|jdd|j s|dur||j krt d|zt j|Wqtjy}zt||fWYd}~qd}~00n t|nD|dur||jkrt d |||jkr |dur td ||S) aCheck 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;rNir zUNKNOWN-LOCATIONz/Ignoring wrong Content-Type (%r) for JSON Errorzsz.ClientNetwork._send_request..)rrrrrrrZrequestr exceptionsZRequestExceptionrematchrAgroupsrbase64Z b64encodeZcontentencodingrkr"joinr#items)rrrKr}r~r'eZ err_regexmhostpathZ_err_noerr_msgZ debug_contentrrr _send_requestqs<   . zClientNetwork._send_requestr|cOs|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)rrrrrheadszClientNetwork.head)rKrr~rcKs|j|jd|fi||dS)z$Send GET request and check response.ZGETr)rr)rrKrr~rrrrFszClientNetwork.get)r'rc Cs|j|jvr||j|j}ztjjd|}Wn2tjy`}zt ||WYd}~n d}~00t d||j |n t|dS)NrzStoring nonce: %s)REPLAY_NONCE_HEADERr#rZHeader_fieldsdecoderdrrZBadNoncerrraddZ MissingNonce)rr'rZ decoded_noncerbrrr _add_nonces  " zClientNetwork._add_nonce)rKrrcCsL|jsBtd|dur$||}n|j||dd}|||jS)NzRequesting fresh noncer)rrrrrrpop)rrKrr'rrr _get_nonces   zClientNetwork._get_noncec Osrz|j|i|WStjyl}z@|jdkrVtd||j|i|WYd}~SWYd}~n d}~00dS)zPOST 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_oncerrpcoderr)rr}r~rbrrrrs  zClientNetwork.post)rKrrr~rcKsf|dd}||||||}|dd|i|jd|fd|i|}|j||d}|||S)Nrr#rrrr)rrrrrrr)rrKrrr~rrr'rrrrs  zClientNetwork._post_once)N)#rrrrrZJOSE_CONTENT_TYPErrrdZRS256DEFAULT_NETWORK_TIMEOUTZJWKrrrZ JWASignaturerrArrrZJSONDeSerializablerrrrrrrrrFrrrrrrrrrs>   :G    r)*rrrUZ email.utilsrZ http.clientZclientrZloggingrr]typingrrrrrrr r Z cryptographyr ZjosepyrdrcrZrequests.adaptersr Zrequests.utilsr ZacmerrrrrZ getLoggerrrrrrrrrrsB                   N