
\\S                 @   s  d  Z  d d l Z d d l 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 m Z m Z m Z m Z d d l m Z d d l m Z d d l m Z d d	 l m Z e j e  Z e j d
 d d g  Z Gd d   d e  Z d d   Z d d   Z d d   Z d d   Z d d   Z  d Z! d e! d d e! d d d d  d! d" e! d# d$ e! d% e! i Z" d& d'   Z# d( d)   Z$ d S)*zACME AuthHandler.    N)
challenges)messages)DefaultDictDictListSet
Collection)achallenges)errors)error_handler)
interfacesAnnotatedAuthzrauthzrachallsc               @   s   e  Z d  Z d Z d d   Z d d d  Z d d   Z d	 d
   Z d d   Z d d   Z	 d d   Z
 d d   Z d d d d  Z d d   Z d d   Z d d   Z d d d  Z d  d!   Z d" d#   Z d S)$AuthHandlera  ACME Authorization Handler for a client.

    :ivar auth: Authenticator capable of solving
        :class:`~acme.challenges.Challenge` types
    :type auth: :class:`certbot.interfaces.IAuthenticator`

    :ivar acme.client.BackwardsCompatibleClientV2 acme_client: ACME client API.

    :ivar account: Client's Account
    :type account: :class:`certbot.account.Account`

    :ivar list pref_challs: sorted user specified preferred challenges
        type strings with the most preferred challenge listed first

    c             C   s(   | |  _  | |  _ | |  _ | |  _ d  S)N)authacmeaccountpref_challs)selfr   Zacme_clientr   r    r   6/usr/lib/python3/dist-packages/certbot/auth_handler.py__init__+   s    			zAuthHandler.__init__Fc             C   s  d d   | j  D } |  j |  t j j t j  } t j j t j  j } xx |  j	 |  r t
 j |  j |  M |  j |  } t j d  | j r | d d d |  j | | |  Wd QRXqS W|  j |  d d   | D } | s t j d	   | S)
a  Retrieve all authorizations for challenges.

        :param acme.messages.OrderResource orderr: must have
            authorizations filled in
        :param bool best_effort: Whether or not all authorizations are
            required (this is useful in renewal)

        :returns: List of authorization resources
        :rtype: list

        :raises .AuthorizationError: If unable to retrieve all
            authorizations

        c             S   s   g  |  ] } t  | g    q Sr   )r   ).0r   r   r   r   
<listcomp>A   s   	z5AuthHandler.handle_authorizations.<locals>.<listcomp>zWaiting for verification...z\Challenges loaded. Press continue to submit to CA. Pass "-v" for more info about challenges.pauseTNc             S   s1   g  |  ]' } | j  j j t j k r | j   q Sr   )r   bodystatusr   STATUS_VALID)r   aauthzrr   r   r   r   X   s   	 z!Challenges failed for all domains)Zauthorizations_choose_challengeszope	component
getUtilityr   ZIConfigZIDisplayZnotification_has_challengesr   ZExitHandler_cleanup_challenges_solve_challengesloggerinfoZdebug_challenges_respondverify_authzr_completer
   AuthorizationError)r   Zorderrbest_effortaauthzrsconfigZnotifyrespZret_valr   r   r   handle_authorizations2   s&    				z!AuthHandler.handle_authorizationsc       	      C   s*  d d   | D } | r& t  j d  x | D] } | j j j } |  j j d k rf | j j j } n% t d d   t	 t
 |   D  } t | |  j | j j j j  |  } |  j | j |  } | j j |  q- WxH | D]@ } x7 | j D], } t | j t j  r t  j d  d Sq Wq Wd S)	z
        Retrieve necessary and pending challenges to satisfy server.
        NB: Necessary and already validated challenges are not retrieved,
        as they can be reused for a certificate issuance.
        c             S   s.   g  |  ]$ } | j  j j t j k r |  q Sr   )r   r   r   r   r   )r   r   r   r   r   r   g   s   	 z2AuthHandler._choose_challenges.<locals>.<listcomp>z$Performing the following challenges:   c             s   s   |  ] } | f Vq d  S)Nr   )r   ir   r   r   	<genexpr>p   s    z1AuthHandler._choose_challenges.<locals>.<genexpr>z5TLS-SNI-01 is deprecated, and will stop working soon.N)r'   r(   r   r   r   r   Zacme_versioncombinationstuplerangelengen_challenge_path_get_chall_pref
identifiervalue_challenge_factoryr   extend
isinstancechallZTLSSNI01warning)	r   r-   Zpending_authzrsr   Zaauthzr_challengesr4   pathZaauthzr_achallsachallr   r   r   r    a   s(    %	zAuthHandler._choose_challengesc             C   s   t  d d   | D  S)z%Do we have any challenges to perform?c             s   s   |  ] } | j  Vq d  S)N)r   )r   r   r   r   r   r3      s    z.AuthHandler._has_challenges.<locals>.<genexpr>)any)r   r-   r   r   r   r$      s    zAuthHandler._has_challengesc             C   s   g  } |  j  |  } y | r0 |  j j |  } Wn2 t j k
 re t j d  t j d    Yn Xt |  t |  k s t	  | S)z1Get Responses for challenges from authenticators.z!Failure in setting up challenges.z0Attempting to clean up outstanding challenges...)
_get_all_achallsr   Zperformr
   r+   r'   criticalr(   r7   AssertionError)r   r-   r/   all_achallsr   r   r   r&      s    zAuthHandler._solve_challengesc             C   s+   g  } x | D] } | j  | j  q W| S)zReturn all active challenges.)r=   r   )r   r-   rG   r   r   r   r   rD      s    zAuthHandler._get_all_achallsc             C   s3   t    } |  j | | |  |  j | | |  d S)z|Send/Receive confirmation of all challenges.

        .. note:: This method also cleans up the auth_handler state.

        N)dict_send_responses_poll_challenges)r   r-   r/   r,   chall_updater   r   r   r)      s    	zAuthHandler._respondc       
      C   s   g  } t  |  } x| t |  D]n \ } } x_ | j D]T } | j |  t |  }	 |	 r5 |  j j | j |	  | j | g   j |  q5 Wq W| S)a  Send responses and make sure errors are handled.

        :param aauthzrs: authorizations and the selected annotated challenges
            to try and perform
        :type aauthzrs: `list` of `AnnotatedAuthzr`
        :param resps: challenge responses from the authenticator where
            each response at index i corresponds to the annotated
            challenge at index i in the list returned by
            :func:`_get_all_achalls`
        :type resps: `collections.abc.Iterable` of
            :class:`~acme.challenges.ChallengeResponse` or `False` or
            `None`
        :param dict chall_update: parameter that is updated to hold
            aauthzr index to list of outstanding solved annotated challenges

        )	iter	enumerater   appendnextr   Zanswer_challengechallb
setdefault)
r   r-   ZrespsrK   Zactive_achallsZ
resps_iterr2   r   rB   r/   r   r   r   rI      s    !zAuthHandler._send_responses      c             C   sn  t  | j    } t    } d } xF| ri| | k  rit j |  t    }	 x | D] }
 |  j | |
 | |
  \ } } t |  t | |
  k r | j |
  qS | s xx | D] \ } } | |
 j |  q WqS | r| j |
  t j	 d | |
 j
 j j j  qS |	 j d d   | D  qS W|	 rHt |	  t j |	   | | 8} | j   | d 7} q$ Wd S)z0Wait for all challenge results to be determined.r   zChallenge failed for domain %sc             s   s   |  ] \ } } | Vq d  S)Nr   )r   _updatedr   r   r   r3      s    z/AuthHandler._poll_challenges.<locals>.<genexpr>r1   N)setkeystimeZsleep_handle_checkr7   addremover'   r@   r   r   r:   r;   update_report_failed_challsr
   ZFailedChallengesclear)r   r-   rK   r,   Z	min_sleepZ
max_roundsZindices_to_checkZcomp_indicesroundsZall_failed_achallsindexZcomp_achallsfailed_achallsrB   rT   r   r   r   rJ      s6    		


zAuthHandler._poll_challengesc             C   s   g  } g  } | | } |  j  j | j  \ } } t | | j  | | <| j j t j k rf | g  f Sxy | D]q }	 |	 j	 d |  j
 | |	   }
 |
 j t j k r | j |	 |
 f  qm |
 j t j k rm | j |	 |
 f  qm W| | f S)z)Returns tuple of ('completed', 'failed').rP   )r   Zpollr   r   r   r   r   r   r   r\   _find_updated_challbrN   STATUS_INVALID)r   r-   r`   r   Z	completedZfailedZoriginal_aauthzrZupdated_authzrrT   rB   Zupdated_achallr   r   r   rY      s    

zAuthHandler._handle_checkc             C   sO   x9 | j  j D]+ } t | j  t | j j  k r | Sq Wt j d   d S)a_  Find updated challenge body within Authorization Resource.

        .. warning:: This assumes only one instance of type of challenge in
            each challenge resource.

        :param .AuthorizationResource authzr: Authorization Resource
        :param .AnnotatedChallenge achall: Annotated challenge for which
            to get status

        z4Target challenge not found in authorization resourceN)r   r   typer?   rP   r
   r+   )r   r   rB   Zauthzr_challbr   r   r   rb     s
    !z AuthHandler._find_updated_challbc             C   s   g  } |  j  j |  } |  j r t d d   | D  } x4 |  j D]) } | | k rD | j t j j |  qD W| r{ | St j	 d   | j
 |  | S)z{Return list of challenge preferences.

        :param str domain: domain for which you are requesting preferences

        c             s   s   |  ] } | j  Vq d  S)N)typ)r   r?   r   r   r   r3   )  s    z.AuthHandler._get_chall_pref.<locals>.<genexpr>zENone of the preferred challenges are supported by the selected plugin)r   Zget_chall_prefr   rV   rN   r   Z	ChallengeZTYPESr
   r+   r=   )r   domainZchall_prefsZplugin_prefZplugin_pref_typesre   r   r   r   r9     s    		zAuthHandler._get_chall_prefNc             C   s   t  j d  | d k r( |  j |  } | r |  j j |  x? | D]7 } x. | D]& } | | j k rR | j j |  PqR WqE Wd S)a7  Cleanup challenges.

        :param aauthzrs: authorizations and their selected annotated
            challenges
        :type aauthzrs: `list` of `AnnotatedAuthzr`
        :param achalls: annotated challenges to cleanup
        :type achalls: `list` of :class:`certbot.achallenges.AnnotatedChallenge`

        zCleaning up challengesN)r'   r(   rD   r   Zcleanupr   r[   )r   r-   r   rB   r   r   r   r   r%   5  s    
zAuthHandler._cleanup_challengesc             C   sW   xP | D]H } | j  } | j j t j k r | j j t j k r t j d   q Wd S)a  Verifies that all authorizations have been decided.

        :param aauthzrs: authorizations and their selected annotated
            challenges
        :type aauthzrs: `list` of `AnnotatedAuthzr`

        :returns: Whether all authzr are complete
        :rtype: bool

        zIncomplete authorizationsN)r   r   r   r   r   rc   r
   r+   )r   r-   r   r   r   r   r   r*   J  s
    	z"AuthHandler.verify_authzr_completec             C   sS   g  } xF | D]> } | j  j | } | j t | |  j j | j  j j   q W| S)ai  Construct Namedtuple Challenges

        :param messages.AuthorizationResource authzr: authorization

        :param list path: List of indices from `challenges`.

        :returns: achalls, list of challenge type
            :class:`certbot.achallenges.Indexed`
        :rtype: list

        :raises .errors.Error: if challenge type is not recognized

        )r   r   rN   challb_to_achallr   keyr:   r;   )r   r   rA   r   r`   rP   r   r   r   r<   [  s    	#zAuthHandler._challenge_factory)__name__
__module____qualname____doc__r   r0   r    r$   r&   rD   r)   rI   rJ   rY   rb   r9   r%   r*   r<   r   r   r   r   r      s    / %&r   c             C   s   |  j  } t j d | j |  t | t j  rM t j d |  d | d |  St | t j	  ru t j	 d |  d |  St
 j d | j   d S)a:  Converts a ChallengeBody object to an AnnotatedChallenge.

    :param .ChallengeBody challb: ChallengeBody
    :param .JWK account_key: Authorized Account Key
    :param str domain: Domain of the challb

    :returns: Appropriate AnnotatedChallenge
    :rtype: :class:`certbot.achallenges.AnnotatedChallenge`

    z%s challenge for %srP   rf   account_keyz*Received unsupported challenge of type: %sN)r?   r'   r(   re   r>   r   ZKeyAuthorizationChallenger	   Z"KeyAuthorizationAnnotatedChallengeZDNSr
   Error)rP   rm   rf   r?   r   r   r   rg   s  s    		rg   c             C   s'   | r t  |  | |  St |  |  Sd S)a  Generate a plan to get authority over the identity.

    .. todo:: This can be possibly be rewritten to use resolved_combinations.

    :param tuple challbs: A tuple of challenges
        (:class:`acme.messages.Challenge`) from
        :class:`acme.messages.AuthorizationResource` to be
        fulfilled by the client in order to prove possession of the
        identifier.

    :param list preferences: List of challenge preferences for domain
        (:class:`acme.challenges.Challenge` subclasses)

    :param tuple combinations: A collection of sets of challenges from
        :class:`acme.messages.Challenge`, each of which would
        be sufficient to prove possession of the identifier.

    :returns: tuple of indices from ``challenges``.
    :rtype: tuple

    :raises certbot.errors.AuthorizationError: If a
        path cannot be created that satisfies the CA given the preferences and
        combinations.

    N)_find_smart_path_find_dumb_path)challbspreferencesr4   r   r   r   r8     s    r8   c             C   s   i  } d } x. t  |  D]  \ } } | | | <| | 7} q Wd } | } d }	 x] | D]U }
 x. |
 D]& } |	 | j |  | j j |  7}	 qc W|	 | k  r |
 } |	 } d }	 qV W| s t |   | S)zFind challenge path with server hints.

    Can be called if combinations is included. Function uses a simple
    ranking system to choose the combo with the lowest cost.

    r1   Nr   )rM   getr?   	__class___report_no_chall_path)rq   rr   r4   Z
chall_costZmax_costr2   Z	chall_clsZ
best_comboZbest_combo_costZcombo_totalZcomboZchallenge_indexr   r   r   ro     s&    


ro   c                si   g  } x\ t  |   D]N \ }   t   f d d   | D d  } | rW | j |  q t |   q W| S)zFind challenge path without server hints.

    Should be called if the combinations hint is not included by the
    server. This function either returns a path containing all
    challenges provided by the CA or raises an exception.

    c             3   s'   |  ] } t    j |  r d  Vq d S)TN)r>   r?   )r   Zpref_c)rP   r   r   r3     s    z"_find_dumb_path.<locals>.<genexpr>F)rM   rO   rN   ru   )rq   rr   rA   r2   Z	supportedr   )rP   r   rp     s    	rp   c             C   s[   d } t  |   d k r; t |  d j t j  r; | d 7} t j |  t j |   d S)zLogs and raises an error that no satisfiable chall path exists.

    :param challbs: challenges from the authorization that can't be satisfied

    zyClient with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.r1   r   zM You may need to use an authenticator plugin that can do challenges over DNS.N)	r7   r>   r?   r   ZDNS01r'   rE   r
   r+   )rq   msgr   r   r   ru     s    +ru   zTo fix these errors, please make sure that your domain name was entered correctly and the DNS A/AAAA record(s) for that domain contain(s) the right IP address.Z
connectiona   Additionally, please check that your computer has a publicly routable IP address and that no firewalls are preventing the server from communicating with the client. If you're using the webroot plugin, you should also verify that you are serving files from the webroot path you provided.Zdnssecze Additionally, if you have DNSSEC enabled for your domain, please ensure that the signature is valid.Z	malformedzTo fix these errors, please make sure that you did not provide any invalid information to the client, and try running Certbot again.ZserverInternalzoUnfortunately, an error on the ACME server prevented you from completing authorization. Please try again later.Ztlsz Additionally, please check that you have an up-to-date TLS configuration that allows the server to communicate with the Certbot client.ZunauthorizedZunknownHostc             C   s   t  j t  } x. |  D]& } | j r | | j j j |  q Wt j j t	 j
  } x0 t j |  D] } | j t |  | j  qe Wd S)zNotifies the user about failed challenges.

    :param set failed_achalls: A set of failed
        :class:`certbot.achallenges.AnnotatedChallenge`.

    N)collectionsdefaultdictlisterrorre   rN   r!   r"   r#   r   Z	IReportersixZ
itervaluesZadd_message_generate_failed_chall_msgZMEDIUM_PRIORITY)ra   ZproblemsrB   Zreporterr   r   r   r   r]     s    	r]   c             C   s   |  d j  } | j } t j |  r. | j } d g } x1 |  D]) } | j d | j | | j  j f  q> W| t k r | j d  | j t |  d j	 |  S)a  Creates a user friendly error message about failed challenges.

    :param list failed_achalls: A list of failed
        :class:`certbot.achallenges.AnnotatedChallenge` with the same error
        type.

    :returns: A formatted error message for the client.
    :rtype: str

    r   z1The following errors were reported by the server:z"

Domain: %s
Type:   %s
Detail: %sz

 )
rz   re   r   Zis_acme_errorcoderN   rf   Zdetail_ERROR_HELPjoin)ra   rz   re   rv   rB   r   r   r   r|   '  s    				r|   )%rl   rw   ZloggingrX   r{   Zzope.componentr!   r   r   r   Zacme.magic_typingr   r   r   r   r   Zcertbotr	   r
   r   r   Z	getLoggerri   r'   
namedtupler   objectr   rg   r8   ro   rp   ru   Z_ERROR_HELP_COMMONr   r]   r|   r   r   r   r   <module>   sH   ( Y %