o
    csu                     @   sJ  d Z ddlZddlZddlmZ ddlmZ ddlZddl	Z	ddl
Z
ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlZddlZddlZddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddlm!Z! ddlm"Z" e#e$Z%dZ&G dd dZ'G dd dZ(dS )zACME client API.    N)parsedate_tz)Any)cast)List)Mapping)Optional)Set)Text)Tuple)Union)HTTPAdapter)parse_header_links)
challenges)crypto_util)errors)jws)messages-   c                
   @   s  e Zd ZdZdejddddfddZd	ejdejfd
dZ	dejdejfddZ
	dNdejdeej dejfddZdOdejdedejfddZdedejfddZdejdeejejf fddZ	dNdejdeej dejfddZdejdejdejfd d!Z	dOdejdejd"edejfd#d$Zd%ejd&eddfd'd(Zdefd)d*Z d+e!d,e!dejfd-d.Z"d/ejd0e#de$e# fd1d2Z%e&d3e#dddejfd4d5Z'e&		dPd/ejd6ee# d7ee# dejfd8d9Z(dejd:ejdejfd;d<Z)d+e!d,e!dejfd=d>Z*dejdejfd?d@Z+dejdejfdAdBZ,		dPd/ejdCeej- d6ee# dejfdDdEZ.dFej/d/e0j1dej2fdGdHZ3e&d/ejdIedejfdJdKZ4d%ejd&ed3e#ddfdLdMZ5dS )QClientV2zuACME client for a v2 API.

    :ivar messages.Directory directory:
    :ivar .ClientNetwork net: Client network.
    	directorynetClientNetworkreturnNc                 C   s   || _ || _dS )zInitialize.

        :param .messages.Directory directory: Directory Resource
        :param .ClientNetwork net: Client network.
        N)r   r   )selfr   r    r   8/opt/certbot/lib/python3.10/site-packages/acme/client.py__init__+   s   
zClientV2.__init__new_accountc                 C   sL   |  | jd |}|jdkrd|jv rt|jd | |}|| j_|S )zRegister.

        :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)r   r   responseregrr   r   r   r   4   s   

zClientV2.new_accountr(   c                 C   s   |  |d| j_| jjS )zQuery server about registration.

        :param messages.RegistrationResource regr: Existing Registration
            Resource.

        T)_get_v2_accountr   r&   r   r(   r   r   r   query_registrationG   s   zClientV2.query_registrationupdatec                 C   sJ   |  |}|du r|jn|}tjdi t|}| j||d}|| j_|S )aK  Update 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)bodyr   )r)   r-   r   UpdateRegistrationdict_send_recv_regrr   r&   )r   r(   r,   r-   updated_regrr   r   r   update_registrationS   s   
zClientV2.update_registrationFupdate_bodyc                 C   sb   d | j _|jjdd}| | jd |}|jd }|j|r%tj	|
 n|j|d}|| j _|S )NT)only_return_existingr   r    r-   uri)r   r&   r-   r,   r!   r   r#   r   Registration	from_jsonjson)r   r(   r3   only_existing_regr'   updated_urinew_regrr   r   r   r)   i   s   
zClientV2._get_v2_accountcsr_pemc                 C   s   t jt jj|}t|}t|}g }|D ]}|tj	tj
|d q|D ]}|tj	tj|d q'tj|d}| | jd |}	tj|	 }
g }|
jD ]}|| j| ||d qQtj|
|	jd||dS )zRequest 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)identifiersnewOrderr6   r    )r-   r6   authorizationsr=   )OpenSSLcryptoload_certificate_requestFILETYPE_PEMr    _pyopenssl_cert_or_req_all_names_pyopenssl_cert_or_req_san_ipappendr   
IdentifierIDENTIFIER_FQDNIDENTIFIER_IPNewOrderr!   r   Orderr8   r9   rC   _authzr_from_response_post_as_getOrderResourcer#   get)r   r=   csrdnsNamesipNamesr@   nameipsorderr'   r-   rC   urlr   r   r   	new_orderu   s0   





zClientV2.new_orderauthzrc                 C   s(   |  |j}| ||jj|j}||fS )a  Poll Authorization Resource for status.

        :param authzr: Authorization Resource
        :type authzr: `.AuthorizationResource`

        :returns: Updated Authorization Resource and HTTP response.

        :rtype: (`.AuthorizationResource`, `requests.Response`)

        )rQ   r6   rP   r-   
identifier)r   r\   r'   updated_authzrr   r   r   poll   s
   zClientV2.pollorderrdeadlinec                 C   s6   |du rt j  t jdd }| ||}| ||S )ad  Poll 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   seconds)datetimenow	timedeltapoll_authorizationsfinalize_order)r   r`   ra   r   r   r   poll_and_finalize   s   zClientV2.poll_and_finalizec                 C   s   g }|j jD ],}tj |k r2| j| ||d}|j jtjkr&|	| nt
d tj |k sqt|t|j jk rAt g }|D ]}|j jtjkr_|j jD ]}|jdur^|	| qRqE|rgt||j|dS )zPoll Order Resource for status.rB      N)rC   )r-   rC   re   rf   rP   rQ   statusr   STATUS_PENDINGrJ   timesleeplenr   TimeoutErrorSTATUS_VALIDr   errorValidationErrorr,   )r   r`   ra   	responsesrZ   r\   failedchallr   r   r   rh      s,   




zClientV2.poll_authorizationsfetch_alternative_chainsc                    s  t jt jj|j}tjt|d} 	|j
j| tj |k rtd  |j}tj| }|jtjkrK|jdurFt|jtd|jtjkr}|jdur} |j}|j||jd}|r{ |d}	 fdd|	D }
|j|
d	}|S tj |k s"t  )
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

        )rT   rk   NzPThe certificate order failed. No further information was provided by the server.)r-   fullchain_pem	alternatec                    s   g | ]}  |jqS r   )rQ   text).0rZ   r   r   r   
<listcomp>   s    z+ClientV2.finalize_order.<locals>.<listcomp>)alternative_fullchains_pem)!rD   rE   rF   rG   r=   r   CertificateRequestjoseComparableX509r!   r-   finalizere   rf   rn   ro   rQ   r6   rO   r8   r9   rl   STATUS_INVALIDrs   r   IssuanceErrorErrorrr   certificater,   r{   
_get_linksrq   )r   r`   ra   rx   rT   wrapped_csrr'   r-   certificate_responsealt_chains_urls
alt_chainsr   r}   r   ri      s2   


zClientV2.finalize_ordercertrsnc                 C   s   |  ||| jd  dS )a  Revoke certificate.

        :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in
            `.ComparableX509`

        :param int rsn: Reason code for certificate revocation.

        :raises .ClientError: If revocation is unsuccessful.

        
revokeCertN)_revoker   )r   r   r   r   r   r   revoke   s   zClientV2.revokec                 C   s$   t | jdot | jjdo| jjjS )zGChecks if ACME server requires External Account Binding authentication.metaexternal_account_required)hasattrr   r   r   r}   r   r   r   r     s
   z"ClientV2.external_account_requiredargskwargsc                 O   s,   |dd d |dd  }| j |i |S )z
        Send GET request using the POST-as-GET protocol.
        :param args:
        :param kwargs:
        :return:
        Nrk   N)r!   )r   r   r   new_argsr   r   r   rQ     s   zClientV2._post_as_getr'   relation_typec                    s.   d|j vrg S t|j d } fdd|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.
        Linkc                    s0   g | ]}d |v rd|v r|d   kr|d qS )relrZ   r   )r|   lr   r   r   r~   "  s    
z'ClientV2._get_links.<locals>.<listcomp>)r#   r   )r   r'   r   linksr   r   r   r     s   
zClientV2._get_linksrZ   c                 C   s   t j|| 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   	Directoryr8   rS   r9   )clsrZ   r   r   r   r   get_directory%  s   
zClientV2.get_directoryr6   terms_of_servicec                 C   s>   d|j v r|j d d }tjtj| |jd||dS )Nzterms-of-servicerZ   r    )r-   r6   r   )r   r   RegistrationResourcer7   r8   r9   r#   rS   )r   r'   r6   r   r   r   r   r%   1  s   
zClientV2._regr_from_responser-   c                 C   s"   |  |j|}| j||j|jdS )N)r6   r   )r!   r6   r%   r   )r   r(   r-   r'   r   r   r   r0   =  s
   zClientV2._send_recv_regrc                 O   s&   | dt| jd | jj|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_urlnewNonce)
setdefaultgetattrr   r   postr   r   r   r   r   r   r!   K  s   zClientV2._postc                 C   s   |  |tjdddS )zDeactivate registration.

        :param messages.RegistrationResource regr: The Registration Resource
            to be deactivated.

        :returns: The Registration resource that was deactivated.
        :rtype: `.RegistrationResource`

        deactivatedN)rl   contact)r2   r   r7   r8   r*   r   r   r   deactivate_registrationT  s   z ClientV2.deactivate_registrationc                 C   s.   t jdd}| |j|}| ||jj|jS )a  Deactivate authorization.

        :param messages.AuthorizationResource authzr: The Authorization resource
            to be deactivated.

        :returns: The Authorization resource that was deactivated.
        :rtype: `.AuthorizationResource`

        r   )rl   )r   UpdateAuthorizationr!   r6   rP   r-   r]   )r   r\   r-   r'   r   r   r   deactivate_authorizationb  s
   
z!ClientV2.deactivate_authorizationr]   c                 C   sF   t jt j| |jd|d}|d ur!|jj|kr!t	
||S )Nr    r5   )r   AuthorizationResourceAuthorizationr8   r9   r#   rS   r-   r]   r   UnexpectedUpdate)r   r'   r]   r6   r\   r   r   r   rP   s  s   
zClientV2._authzr_from_responsechallbc                 C   sp   |  |j|}z	|jd d }W n ty   tdw tj|tj	|
 d}|j|jkr6t|j|S )ah  Answer 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:

        uprZ   z"up" Link header missing)
authzr_urir-   )r!   r6   r   KeyErrorr   ClientErrorr   ChallengeResourceChallengeBodyr8   r9   r   )r   r   r'   respr   challrr   r   r   answer_challenge}  s   
zClientV2.answer_challengedefaultc                 C   s   |j dt|}zt|}W n< tyK   t|}|durGzt|d dur+|d nd}tj|dd  | W  Y S  ttfyF   Y nw |}Y nw tj	 tj|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-AfterNr      rc   )
r#   rS   strint
ValueErrorr   re   rg   OverflowErrorrf   )r   r'   r   retry_afterrd   whentz_secsr   r   r   r     s   zClientV2.retry_afterc                 C   s0   |  |tj||d}|jtjkrtddS )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.

        )r   reasonz0Successful revocation must return HTTP OK statusN)r!   r   
Revocationr"   http_clientOKr   r   )r   r   r   rZ   r'   r   r   r   r     s   zClientV2._revoker   )F)NN)6__name__
__module____qualname____doc__r   r   r   NewRegistrationr   r   r+   r   r7   r2   boolr)   bytesrR   r[   r   r
   requestsResponser_   re   rj   rh   ri   r   r   r   r   r   r   rQ   r   r   r   classmethodr   r%   r0   r!   r   r   rK   rP   r   r   ChallengeResponser   r   r   r   r   r   r   r   r   $   s    	



#




%

	





 r   c                   @   sl  e Zd ZdZdZdZdZdZ	 dej	dde
fd	ejd
eej dejdedededdfddZd/ddZdejdededefddZe	d0dejdee dejfddZdededededejf
d d!Zdededejfd"d#Zefdedededejfd$d%Zdejddfd&d'Zded(edefd)d*Z dededejfd+d,Z!efdedejdededejf
d-d.Z"dS )1r   zvWrapper around requests that signs POSTs for authentication.

    Also adds user agent, and handles Content-Type.
    zapplication/jsonzapplication/jose+jsonzapplication/problem+jsonzReplay-NonceNTzacme-pythonkeyr&   alg
verify_ssl
user_agenttimeoutr   c                 C   s\   || _ || _|| _|| _t | _|| _t | _	|| _
t }| j	d| | j	d| d S )Nzhttp://zhttps://)r   r&   r   r   set_noncesr   r   Sessionsession_default_timeoutr   mount)r   r   r&   r   r   r   r   adapterr   r   r   r     s   
zClientNetwork.__init__c                 C   s&   z| j   W d S  ty   Y d S w r   )r   close	Exceptionr}   r   r   r   __del__  s
   zClientNetwork.__del__objnoncerZ   c                 C   s~   |r
|j dd nd}td| | j||d}| jdur%| jd |d< | j|d	< tjj	|fi t
tttf |j ddS )
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

           )indent    zJWS payload:
%s)r   r   rZ   Nr6   kidr   )
json_dumpsencodeloggerdebugr   r&   r   r   JWSsignr   r   r   r   )r   r   r   rZ   jobjr   r   r   r   _wrap_in_jws  s   

*zClientNetwork._wrap_in_jwsr'   content_typec              
   C   s  |j d}|r|dd  }z| }W n ty"   d}Y nw |jdkr2t|j dd|j	sd|dur_|| j
krDtd| ztj| tjy^ } zt||fd}~ww t||durs|| jkrstd	| || jkr|du rt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;r   Ni  r    zUNKNOWN-LOCATIONz/Ignoring wrong Content-Type (%r) for JSON Errorz<Ignoring wrong Content-Type (%r) for JSON decodable responsez"Unexpected response Content-Type: )r#   rS   splitstripr9   r   r"   r   r$   okJSON_ERROR_CONTENT_TYPEr   r   r   r   r8   r   DeserializationErrorr   JSON_CONTENT_TYPE)r   r'   r   response_ctr   rs   r   r   r   _check_response  s@   


zClientNetwork._check_responsemethodr   r   c              
   O   s8  |dkrt d||d  nt d|| | j|d< |di  |d d| j |d| j z| jj||g|R i |}W n2 tj	j
yr } z$	 d	}t|t|}|d
u rZ | \}	}
}}td|	 |
 d| d
}~ww d|d v rt|j}nd|_|j}t d|jddd |j D | |S )a  Send HTTP request.

        Makes sure that `verify_ssl` is respected. Logs request and
        response (with headers). For allowed parameters please see
        `requests.request`.

        :param str method: method for the new `requests.Request` object
        :param str url: URL for the new `requests.Request` object

        :raises requests.exceptions.RequestException: in case of any problems

        :returns: HTTP Response
        :rtype: `requests.Response`


        POSTzSending POST request to %s:
%sdatazSending %s request to %s.verifyr#   z
User-Agentr   zT.*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)NzRequesting :Acceptzutf-8z!Received response:
HTTP %d
%s

%s
c                 s   s     | ]\}}d  ||V  qdS )z{0}: {1}N)format)r|   kvr   r   r   	<genexpr>  s    z.ClientNetwork._send_request.<locals>.<genexpr>)r   r   r   r   r   r   r   requestr   
exceptionsRequestExceptionrematchr   groupsr   base64	b64encodecontentencodingr{   r"   joinr#   items)r   r   rZ   r   r   r'   e	err_regexmhostpath_err_noerr_msgdebug_contentr   r   r   _send_requestQ  sB   
 
zClientNetwork._send_requestc                 O   s   | j dg|R i |S )a  Send 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   r   r   r   head  s   zClientNetwork.headc                 K   s   | j | jd|fi ||dS )z$Send GET request and check response.GETr   )r   r  )r   rZ   r   r   r   r   r   rS     s   zClientNetwork.getc              
   C   s|   | j |jv r9|j| j  }ztjjd |}W n tjy* } zt	||d }~ww t
d| | j| d S t|)Nr   zStoring nonce: %s)REPLAY_NONCE_HEADERr#   r   Header_fieldsdecoder   r   r   BadNoncer   r   r   addMissingNonce)r   r'   r   decoded_noncers   r   r   r   
_add_nonce  s   
zClientNetwork._add_noncer   c                 C   sL   | j s!td |d u r| |}n
| j| |d d}| | | j  S )NzRequesting fresh noncer   )r   r   r   r  r   r)  pop)r   rZ   r   r'   r   r   r   
_get_nonce  s   


zClientNetwork._get_noncec              
   O   sb   z	| j |i |W S  tjy0 } z|jdkr+td| | j |i |W  Y d}~S  d}~ww )zPOST object wrapped in `.JWS` and check response.

        If the server responded with a badNonce error, the request will
        be retried once.

        badNoncez Retrying request after error:
%sN)
_post_oncer   r   coder   r   )r   r   r   rs   r   r   r   r     s   
zClientNetwork.postc                 K   sf   | dd }| || |||}|dd|i | jd|fd|i|}| j||d}| | |S )Nr   r#   r   r   r   r   )r*  r   r+  r   r  r   r)  )r   rZ   r   r   r   r   r   r'   r   r   r   r-    s   
zClientNetwork._post_once)r   Nr   )#r   r   r   r   r   JOSE_CONTENT_TYPEr   r!  r   RS256DEFAULT_NETWORK_TIMEOUTJWKr   r   r   JWASignaturer   r   r   r   r   JSONDeSerializabler   r   r   r   r   r   r  r  rS   r)  r+  r   r-  r   r   r   r   r     s`    


 :G

r   ))r   r  re   email.utilsr   http.clientclientr   loggingr  rn   typingr   r   r   r   r   r   r	   r
   r   josepyr   rD   r   requests.adaptersr   requests.utilsr   acmer   r   r   r   r   	getLoggerr   r   r1  r   r   r   r   r   r   <module>   sD    
   /