3 گau@sdZddlZddlZddlZddlmZddlZddljZ ddl Z ddl Z ddl Z ddl Z ddlmZddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlZddlZddlZddl Z ddl!m"Z"ddl#m$Z$ddl%m&Z&ddl'm(Z(ddl'm)Z)ddl'm*Z*ddl'm+Z+ddl,m-Z-e j.e/Z0dZ1dZ2GdddZ3Gddde3Z4Gddde3Z5Gd d!d!Z6Gd"d#d#Z7Gd$d%d%Z8eee8e j9e/e j9e/<dS)&zACME client API.N) parsedate_tz) ModuleType)Any)Callable)cast)Dict)Iterable)List)Optional)Set)Text)Tuple)Union) HTTPAdapter)parse_header_links)SourceAddressAdapter) crypto_util)errors)jws)messages)VersionedLEACMEMixin-zapplication/pkix-certc@s*eZdZdZejdeddddZed%e j e e e e ej ddd Zej ejej d d d Zeee j d ddZd&ej e ejej dddZej ej dddZejejdddZd'e j e eje e ejdddZeje j ejdddZee j eejdd d!Zejee dd"d#d$Z dS)( ClientBasezACME client base object. :ivar messages.Directory directory: :ivar .ClientNetwork net: Client network. :ivar int acme_version: ACME protocol version. 1 or 2. ClientNetworkN) directorynet acme_versionreturncCs||_||_||_dS)zInitialize. :param .messages.Directory directory: Directory Resource :param .ClientNetwork net: Client network. :param int acme_version: ACME protocol version. 1 or 2. N)rrr)selfrrrr/usr/lib/python3.6/client.py__init__8szClientBase.__init__)responseuriterms_of_servicercCs>d|jkr|jdd}tjtjj|j|jjd||dS)Nzterms-of-serviceurlLocation)bodyr#r$)linksrRegistrationResource Registration from_jsonjsonheadersget)clsr"r#r$rrr _regr_from_responseDs   zClientBase._regr_from_response)regrr'rcCs"|j|j|}|j||j|jdS)N)r#r$)_postr#r0r$)rr1r'r"rrr _send_recv_regrPszClientBase._send_recv_regr)argskwargsrcOs<|jd|jt|jdr.|jdt|jd|jj||S)zBWrapper around self.net.post that adds the acme_version. rnewNonce new_nonce_url) setdefaultrhasattrrgetattrrpost)rr4r5rrr r2^s zClientBase._post)r1updatercCs<|dkr|jn|}tjft|}|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)r')r'rUpdateRegistrationdictr3raccount)rr1r<r'Z updated_regrrrr update_registrationgs zClientBase.update_registration)r1rcCs|j|tjjdddS)zDeactivate registration. :param messages.RegistrationResource regr: The Registration Resource to be deactivated. :returns: The Registration resource that was deactivated. :rtype: `.RegistrationResource` deactivatedN)statusZcontact)r@rr*r+)rr1rrr deactivate_registrationzs z"ClientBase.deactivate_registration)authzrrcCs.tjdd}|j|j|}|j||jj|jS)aDeactivate authorization. :param messages.AuthorizationResource authzr: The Authorization resource to be deactivated. :returns: The Authorization resource that was deactivated. :rtype: `.AuthorizationResource` rA)rB)rZUpdateAuthorizationr2r#_authzr_from_responser' identifier)rrDr'r"rrr deactivate_authorizations z#ClientBase.deactivate_authorization)r"rFr#rcCsFtjtjj|j|jjd|d}|dk rB|jj|krBt j ||S)Nr&)r'r#) rAuthorizationResourceZ Authorizationr+r,r-r.r'rFrUnexpectedUpdate)rr"rFr#rDrrr rEs  z ClientBase._authzr_from_response)challbr"rc Csv|j|j|}y|jdd}Wntk r>tjdYnXtj|tjj |j d}|j|jkrrtj |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: upr%z"up" Link header missing) authzr_urir') r2r#r(KeyErrorr ClientErrorrChallengeResource ChallengeBodyr+r,rI)rrJr"rLZchallrrrr answer_challenges  zClientBase.answer_challenge)r"defaultrcCs|jjdt|}y t|}Wnvtk rt|}|dk ry4tj|ddk rX|dnd}tj|dd|Sttfk rYnX|}YnXtjj 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-AfterNr)secondsrV) r-r.strint ValueErrorrdatetime timedelta OverflowErrornow)r/r"rR retry_afterrUwhenZtz_secsrrr r^s  zClientBase.retry_after)certrsnr%rcCs0|j|tj||d}|jtjkr,tjddS)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. ) certificatereasonz0Successful revocation must return HTTP OK statusN)r2r Revocation status_code http_clientZOKrrN)rr`rar%r"rrr _revokes   zClientBase._revoke)NN)N)NN)!__name__ __module__ __qualname____doc__r DirectoryrXr! classmethodrequestsResponser rWr)r0r*r3rr2r@rCrHrG IdentifierrErPrOrQrZr^joseComparableX509rgrrrr r1s.    $rc seZdZdZejddfejejej e e dddfdd Z d0e ej ejdd d Zejejd d d Zejejd ddZd1eje eejdddZd2ee eejdddZejeejejdddZejeejejfdddZd3ejeejeeeejeejdffdd d!Z eeejejfd"d#d$Z!ejejd%d&d'Z"ejejd%d(d)Z#d4ejee$ejd*d+d,Z%ejedd-d.d/Z&Z'S)5ClientaFACME client for a v1 API. .. deprecated:: 1.18.0 Use :class:`ClientV2` instead. .. todo:: Clean up raised error types hierarchy, document, and handle (wrap) instances of `.DeserializationError` raised in `from_json()`. :ivar messages.Directory directory: :ivar key: `josepy.JWK` (private) :ivar alg: `josepy.JWASignature` :ivar bool verify_ssl: Verify SSL certificates? :ivar .ClientNetwork net: Client network. Useful for testing. If not supplied, it will be initialized using `key`, `alg` and `verify_ssl`. TNr)rkeyalg verify_sslrrcsR||_|dkrt|||d}t|trsz4Client.poll_and_request_issuance..cSsi|] }||qSrr)rrDrrr sz4Client.poll_and_request_issuance..zSleeping for %d secondsrS)rRcss|]}|jjtjkVqdS)N)r'rBrSTATUS_INVALID)rrDrrr sz3Client.poll_and_request_issuance..c3s|]}|VqdS)Nr)rrD)updatedrr rs)r} collections defaultdictrXset enumerateheapqheapifyheappoprZr]rUrrtimesleeprr'rBr STATUS_VALIDrheappushr^addanyvaluesrZ PollErrortupler)rrrrrZattemptsZ exhaustedZwaitingr_rrDr]rUrr"Zupdated_authzrsr)rr poll_and_request_issuances8           z Client.poll_and_request_issuance)r#rcCs8t}|jj|d|i|d}|tjtjjtjj|j fS)zReturns certificate from URI. :param str uri: URI of certificate :returns: tuple of the form (response, :class:`josepy.util.ComparableX509`) :rtype: tuple r)r-r) rrr.rqrrrrrrr)rr#rr"rrr _get_certs  zClient._get_cert)certrrcCsL|j|j\}}d|jkr$tjd|jd|jkr@tj|j|j|dS)zCheck for new cert. :param certr: Certificate Resource :type certr: `.CertificateResource` :returns: Updated Certificate Resource. :rtype: `.CertificateResource` r&zLocation header missing)r')rr#r-rrNrItextr<)rrr"r`rrr check_certs    zClient.check_certcCs |j|S)zRefresh certificate. :param certr: Certificate Resource :type certr: `.CertificateResource` :returns: Updated Certificate Resource. :rtype: `.CertificateResource` )r)rrrrr refresh"s zClient.refresh)r max_lengthrcCslg}|j}xD|dk rNt||krN|j|\}}|jjdijd}|j|q W|dk rhtjdj||S)aFetch chain for certificate. :param .CertificateResource certr: Certificate Resource :param int max_length: Maximum allowed length of the chain. Note that each element in the certificate requires new ``HTTP GET`` request, and the length of the chain is controlled by the ACME CA. :raises errors.Error: if recursion exceeds `max_length` :returns: Certificate chain for the Certificate Resource. It is a list ordered so that the first element is a signer of the certificate from Certificate Resource. Will be empty if ``cert_chain_uri`` is ``None``. :rtype: `list` of `OpenSSL.crypto.X509` wrapped in `.ComparableX509` NrKr%z'Recursion limit reached. Didn't get {0}) rlenrr(r.appendrErrorformat)rrrchainr#r"r`rrr fetch_chain1s zClient.fetch_chain)r`rarcCs |j|||jtttjdS)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. N)rgrrrWrrd)rr`rarrr revokeOs z Client.revoke)N)N)N)rr)r)(rhrirjrkrqRS256rrlJWK JWASignatureboolr r!r{r)r~rrrprWrHrrrrrrrr rnrorrXrrrrr rr __classcell__rr)ryr rss2*   %JrscsZeZdZdZejdddfdd Zejejddd Z ejejd d d Z d-eje ej ejd fdd Z ejejd ddZeejdddZejeejejfdddZd.eje ejejdddZejejejdddZd/ejejeejddd Zejedd!d"d#Zed$d%d&Z e!e!ejd'd(d)Z"eje#e$e#d*d+d,Z%Z&S)0ClientV2zuACME client for a v2 API. :ivar messages.Directory directory: :ivar .ClientNetwork net: Client network. rN)rrrcstj||dddS)zInitialize. :param .messages.Directory directory: Directory Resource :param .ClientNetwork net: Client network. )rrrN)rxr!)rrr)ryrr r!dszClientV2.__init__) new_accountrcCsL|j|jd|}|jdkr6d|jkr6tj|jd|j|}||j_|S)zRegister. :param .NewRegistration new_account: :raises .ConflictError: in case the account already exists :returns: Registration Resource. :rtype: `.RegistrationResource` newAccountr&) r2rrer-r ConflictErrorr0rr?)rrr"r1rrr rls  zClientV2.new_account)r1rcCs6||j_|j|jd}|j||j|jd|j_|jjS)zQuery server about registration. :param messages.RegistrationResource regr: Existing Registration Resource. N)r#r$)rr?r2r#r0r$)rr1r"rrr rs  zClientV2.query_registration)r1r<rcs|j|}tj||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` )_get_v2_accountrxr@)rr1r<new_regr)ryrr r@s zClientV2.update_registrationcCsJd|j_|jjdd}|j|jd|}|jd}|j|d}||j_|S)NT)Zonly_return_existingrr&)r#)rr?r'r<r2rr-)rr1Zonly_existing_regr"Z updated_urirrrr rs  zClientV2._get_v2_account)csr_pemrc Cstjjtjj|}tj|}tj|}g}x"|D]}|jtj tj |dq0Wx"|D]}|jtj tj |dqTWtj |d}|j |jd|} tjj| j} g} x(| jD]} | j|j|j| | dqWtj| | jjd| |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 )rr) identifiersZnewOrder)r#r&)r'r#authorizationsr)rrload_certificate_request FILETYPE_PEMr _pyopenssl_cert_or_req_all_namesZ_pyopenssl_cert_or_req_san_iprrrprZ IDENTIFIER_IPZNewOrderr2rOrderr+r,rrE _post_as_get OrderResourcer-r.) rrrdnsNamesZipNamesrnameZipsorderr"r'rr%rrr new_orders*         zClientV2.new_order)rDrcCs(|j|j}|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`) )rr#rEr'rF)rrDr"rrrr rs z ClientV2.poll)orderrdeadlinercCs6|dkrtjjtjdd}|j||}|j||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 NZ)rU)rZr]r[poll_authorizationsfinalize_order)rrrrrr poll_and_finalizes zClientV2.poll_and_finalizecCsg}x\|jjD]P}xJtjj|kr\|j|j||d}|jjtjkrP|j |Pt j dqWqWt |t |jjkr~t jg}x@|D]8}|jjtjkrx$|jjD]}|jdk r|j |qWqW|rt j||j|dS)zPoll Order Resource for status.)r#rSN)r)r'rrZr]rErrBrZSTATUS_PENDINGrrrrr TimeoutErrorrZ challengeserrorZValidationErrorr<)rrrZ responsesr%rDZfailedZchallrrr rs&    zClientV2.poll_authorizationsF)rrfetch_alternative_chainsrc stjjtjj|j}tjtj|d}j |j j |xt j j |krtjdj|j}tjj|j}|jdk rtj|j|jdk r8j|j}|j||jd}|rֈj|d} fdd| D} |j| d}|Sq8WtjdS) 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 )rrSN)r' fullchain_pemZ alternatecsg|]}j|jqSr)rr)rr%)rrr r%sz+ClientV2.finalize_order..)Zalternative_fullchains_pem)rrrrrrrrqrrr2r'finalizerZr]rrrr#rr+r,rrZ IssuanceErrorrbr<r _get_linksr) rrrrrZ wrapped_csrr"r'Zcertificate_responseZalt_chains_urlsZ alt_chainsr)rr r s&         zClientV2.finalize_order)r`rarcCs|j|||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)rgr)rr`rarrr r*s zClientV2.revoke)rcCst|jdo|jjjS)zGChecks if ACME server requires External Account Binding authentication.meta)r9rrexternal_account_required)rrrr r7sz"ClientV2.external_account_required)r4r5rcOs(|ddd|dd}|j||S)z Send GET request using the POST-as-GET protocol. :param args: :param kwargs: :return: NrS)N)r2)rr4r5Znew_argsrrr r;szClientV2._post_as_get)r" relation_typercs.d|jkrgSt|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|krd|kr|dkr|dqS)Zrelr%r)rl)rrr rPsz'ClientV2._get_links..)r-r)rr"rr(r)rr rEs zClientV2._get_links)N)N)F)'rhrirjrkrrlr!r{r)rrr r*r@rbytesrrrHr rnrorrZrrrrrqrrrXrrrrrWr rrrr)ryr r]s& #   rc@seZdZdZdejeddddZeeddd Z de j e e egdfe jd d d Zee jd ddZde jejee jdddZejeddddZe jedddZedddZdS)BackwardsCompatibleClientV2aACME client wrapper that tends towards V2-style calls, but supports V1 servers. .. deprecated:: 1.18.0 Use :class:`ClientV2` instead. .. note:: While this class handles the majority of the differences between versions of the ACME protocol, if you need to support an ACME server based on version 3 or older of the IETF ACME draft that uses combinations in authorizations (or lack thereof) to signal that the client needs to complete something other than any single challenge in the authorization to make it valid, the user of this class needs to understand and handle these differences themselves. This does not apply to either of Let's Encrypt's endpoints where successfully completing any challenge in an authorization will make it valid. :ivar int acme_version: 1 or 2, corresponding to the Let's Encrypt endpoint :ivar .ClientBase client: either Client or ClientV2 rN)rrtserverrcCsTtjj|j|j}|j||_||jdkrBt|||d|_nt ||d|_dS)NrS)rtr)r) rrlr+r.r,_acme_version_from_directoryrrsclientr)rrrtrrrrr r!js   z$BackwardsCompatibleClientV2.__init__)rrcCs t|j|S)N)r:r)rrrrr __getattr__ssz'BackwardsCompatibleClientV2.__getattr__)r1 check_tos_cbrcstddfdd }|jdkrVtt|j}|j|}|jdk rR||j|j|S|Stt|j}d|j j kr||j j j|j dd}|j |SdS) zCombined register and agree_tos for V1, new_account for V2 :param .NewRegistration regr: :param callable check_tos_cb: callback that raises an error if the check does not work N)tosrcsdk r|dS)Nr)r)rrr _assess_tosszDBackwardsCompatibleClientV2.new_account_and_tos.._assess_tosrSr$T)Zterms_of_service_agreed) rWrrrsrr~r$rrrrr<r)rr1rr client_v1Z client_v2r)rr new_account_and_tosvs          z/BackwardsCompatibleClientV2.new_account_and_tos)rrcCst|jdkrbtt|j}tjjtjj|}tj |}g}x|D]}|j |j |q.)rrrvr8rrrZrequestrn exceptionsZRequestExceptionrematchrWgroupsrYrr-r.rbase64Z b64encoderencodingrrejoinitems)rrr%r4r5r"eZ err_regexmhostpathZ_err_noZerr_msgZ debug_contentrrr _send_request{s8  $  zClientNetwork._send_request)r4r5rcOs|jd||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. HEAD)r()r')rr4r5rrr headszClientNetwork.head)r%rr5rcKs|j|jd|f||dS)z$Send GET request and check response.ZGET)r)rr')rr%rr5rrr r.szClientNetwork.get)r"rcCs|j|jkrz|j|j}ytjjdj|}Wn0tjk r^}ztj ||WYdd}~XnXt j d||j j |n tj|dS)NrzStoring nonce: %s)REPLAY_NONCE_HEADERr-rZHeader_fieldsrrqrrZBadNoncerrrrZ MissingNonce)rr"rZ decoded_noncerrrr _add_nonces   zClientNetwork._add_nonce)r%r7rcCsL|jsBtjd|dkr$|j|}n|j|j|dd}|j||jjS)NzRequesting fresh nonce)r)rrrr)rr,pop)rr%r7r"rrr _get_nonces   zClientNetwork._get_noncecOsZy |j||Stjk rT}z*|jdkrBtjd||j||SWYdd}~XnXdS)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_oncerrcoderr)rr4r5rrrr r;s    zClientNetwork.postrS)r%rrrr5rc Ksh|jdd}|j||j||||}|jdd|i|jd|fd|i|}|j||d}|j||S)Nr7r-z Content-Typerr)r)r-r r.r8r'rr,) rr%rrrr5r7rr"rrr r/s  zClientNetwork._post_once)N)&rhrirjrkrZJOSE_CONTENT_TYPErr*rqrDEFAULT_NETWORK_TIMEOUTrr rr)rrrWrXrr r!rZJSONDeSerializabler r rmrnrorrr'r)r.r,r.r;r/rrrr rs.>:K   rc@sdeZdZdZeddddZeedddZeedd d d Z eddd d Z e edddZ dS)_ClientDeprecationModulez Internal class delegating to a module, and displaying warnings when attributes related to deprecated attributes in the acme.client module. N)modulercCs||jd<dS)N_module)__dict__)rr3rrr r!sz!_ClientDeprecationModule.__init__)attrrcCs*|dkrtjdj|tddt|j|S)NrsrzHThe {0} attribute in acme.client is deprecated and will be removed soon.r) stacklevel)rsr)warningswarnrDeprecationWarningr:r4)rr6rrr rs  z$_ClientDeprecationModule.__getattr__)r6rrcCst|j||dS)N)setattrr4)rr6rrrr __setattr__sz$_ClientDeprecationModule.__setattr__cCst|j|dS)N)delattrr4)rr6rrr __delattr__sz$_ClientDeprecationModule.__delattr__)rcCsdgt|jS)Nr4)dirr4)rrrr __dir__ sz _ClientDeprecationModule.__dir__) rhrirjrkrr!rWrrr<r>r r@rrrr r2 s r2):rkrrrZZ email.utilsrrZ http.clientrrfZloggingrsysrtypesrZtypingrrrrrr r r r r rr8ZjosepyrqrrnZrequests.adaptersrZrequests.utilsrZ!requests_toolbelt.adapters.sourcerZacmerrrrZ acme.mixinsrZ getLoggerrhrr1rrrsrrrr2modulesrrrr sf                       Fix