
    M/e6                        d 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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mZ  ej:                  e      Z G d dej@                  ejB                  ejD                        Z# G d d      Z$de%ddfdZ&de%ddfdZ'de%dee%   fdZ(y)z*Common code for DNS Authenticator Plugins.    N)sleep)Callable)Iterable)List)Mapping)Optional)Type)
challenges)achallenges)configuration)errors)
interfaces)
filesystem)os)ops)util)commonc                       e Zd ZdZdej
                  deddf fdZe	 d$de	d   d	e
ddfd
       Zdeej                     defdZdedeeej&                        fdZd%dZdefdZdeej                     deej.                     fdZdeej                     ddfdZej6                  d%d       Zej6                  dedededdfd       Zej6                  dedededdfd       ZdededdfdZ	 d&dedede e	egdf      ddfdZ!	 	 d'dedede e"eef      de e	d gdf      dd f
d!Z#e$dedefd"       Z%e$d&dede e	egdf      defd#       Z& xZ'S )(DNSAuthenticatorz!Base class for DNS AuthenticatorsconfignamereturnNc                 4    t         |   ||       d| _        y )NF)super__init___attempt_cleanup)selfr   r   	__class__s      </usr/lib/python3/dist-packages/certbot/plugins/dns_common.pyr   zDNSAuthenticator.__init__   s    & %    add).Ndefault_propagation_secondsc                 $     |d|t         d       y )Npropagation-secondszjThe number of seconds to wait for DNS to propagate before asking the ACME server to verify the DNS record.)defaulttypehelp)int)clsr!   r"   s      r   add_parser_argumentsz%DNSAuthenticator.add_parser_arguments$   s     	!/-	.r    failed_achallsc                 x    | j                  d      }dj                  | j                  ||dk7  rd      S d      S )z,See certbot.plugins.common.Plugin.auth_hint.r$   zThe Certificate Authority failed to verify the DNS TXT records created by --{name}. Ensure the above domains are hosted by this DNS provider, or try increasing --{name}-propagation-seconds (currently {secs} second{suffix}).   s )r   secssuffix)confformatr   )r   r+   delays      r   	auth_hintzDNSAuthenticator.auth_hint-   sI    		/0N VeqjsVQ		
 OQVQ		
r    unused_domainc                 $    t         j                  gS N)r
   DNS01)r   r6   s     r   get_chall_prefzDNSAuthenticator.get_chall_pref7   s      !!r    c                      y r8    r   s    r   preparezDNSAuthenticator.prepare:   s    r    c                     t               r8   NotImplementedErrorr=   s    r   	more_infozDNSAuthenticator.more_info=   s    !##r    achallsc                    | j                          d| _        g }|D ]w  }|j                  }|j                  |      }|j	                  |j
                        }| j                  |||       |j                  |j                  |j
                               y t        j                  d| j                  d      z         t        | j                  d             |S )NTz/Waiting %d seconds for DNS changes to propagater$   )_setup_credentialsr   domainvalidation_domain_name
validationaccount_key_performappendresponsedisplay_utilnotifyr2   r   )r   rC   	responsesachallrF   rG   rH   s          r   performzDNSAuthenticator.perform@   s    ! $	 	BF]]F%+%B%B6%J"**6+=+=>JMM&"8*EV__V-?-?@A	B 	MII345 	6dii-./r    c                     | j                   rS|D ]M  }|j                  }|j                  |      }|j                  |j                        }| j                  |||       O y y r8   )r   rF   rG   rH   rI   _cleanup)r   rC   rP   rF   rG   rH   s         r   cleanupzDNSAuthenticator.cleanupX   sb      ! J)/)F)Fv)N&#..v/A/AB
f&<jIJ !r    c                     t               )z@
        Establish credentials, prompting if necessary.
        r@   r=   s    r   rE   z#DNSAuthenticator._setup_credentialsa   s    
 "##r    rF   validation_namerH   c                     t               )aX  
        Performs a dns-01 challenge by creating a DNS TXT record.

        :param str domain: The domain being validated.
        :param str validation_domain_name: The validation record domain name.
        :param str validation: The validation record content.
        :raises errors.PluginError: If the challenge cannot be performed
        r@   r   rF   rV   rH   s       r   rJ   zDNSAuthenticator._performh   s     "##r    c                     t               )aX  
        Deletes the DNS TXT record which would have been created by `_perform_achall`.

        Fails gracefully if no such record exists.

        :param str domain: The domain being validated.
        :param str validation_domain_name: The validation record domain name.
        :param str validation: The validation record content.
        r@   rX   s       r   rS   zDNSAuthenticator._cleanupu   s     "##r    keylabelc                     | j                  |      }|s8| j                  |      }t        | j                  | j	                  |      |       yy)a  
        Ensure that a configuration value is available.

        If necessary, prompts the user and stores the result.

        :param str key: The configuration key.
        :param str label: The user-friendly label for this piece of information.
        N)r2   _prompt_for_datasetattrr   dest)r   rZ   r[   configured_value	new_values        r   
_configurezDNSAuthenticator._configure   sB      99S>--e4IDKK3;  r    	validatorc           	         | j                  |      }|ss| j                  ||      }t        | j                  | j	                  |      t
        j                  j                  t
        j                  j                  |                   yy)a  
        Ensure that a configuration value is available for a path.

        If necessary, prompts the user and stores the result.

        :param str key: The configuration key.
        :param str label: The user-friendly label for this piece of information.
        N)	r2   _prompt_for_filer^   r   r_   r   pathabspath
expanduser)r   rZ   r[   rc   r`   ra   s         r   _configure_filez DNSAuthenticator._configure_file   sa      99S>--eY?IDKK3ASAST]A^1_`  r    required_variablesCredentialsConfigurationc                      dt         ddf fd} j                  |||       t         j                  |       j                        }r|j                         r |       |S )a  
        As `_configure_file`, but for a credential configuration file.

        If necessary, prompts the user and stores the result.

        Always stores absolute paths to avoid issues during renewal.

        :param str key: The configuration key.
        :param str label: The user-friendly label for this piece of information.
        :param dict required_variables: Map of variable which must be present to error to display.
        :param callable validator: A method which will be called to validate the
            `CredentialsConfiguration` resulting from the supplied input after it has been validated
            to contain the `required_variables`. Should throw a `~certbot.errors.PluginError` to
            indicate any issue.
        filenamer   Nc                 n    t        | j                        }r|j                         r	 |       y y r8   )rk   r_   require)rm   applied_configurationrj   r   rc   s     r   __validatorz<DNSAuthenticator._configure_credentials.<locals>.__validator   s7    $<Xtyy$Q!!%--.@A/0 r    )strri   rk   r2   r_   ro   )r   rZ   r[   rj   rc   _DNSAuthenticator__validatorcredentials_configurations   `  ``  r   _configure_credentialsz'DNSAuthenticator._configure_credentials   sg    (	1# 	1$ 	1 	S%5$<TYYs^TYY$W!%--.@A/0((r    c                      dt         ddf fd}t        j                  |dj                         d      \  }}|t        j
                  k(  r|S t        j                  dj                               )	z
        Prompt the user for a piece of information.

        :param str label: The user-friendly label for this piece of information.
        :returns: The user's response (guaranteed non-empty).
        :rtype: str
        ir   Nc                 R    | s$t        j                  dj                              y )NzPlease enter your {0}.)r   PluginErrorr3   )rw   r[   s    r   rq   z6DNSAuthenticator._prompt_for_data.<locals>.__validator   s(    (()A)H)H)OPP r    zInput your {0}Tforce_interactive{0} required to proceed.)rr   r   validated_inputr3   rM   OKr   ry   )r[   rs   coderL   s   `   r   r]   z!DNSAuthenticator._prompt_for_data   ss    	Q3 	Q4 	Q ,,##E*"$h
 <??"O  !;!B!B5!IJJr    c                      dt         ddf fd}t        j                  |dj                         d      \  }}|t        j
                  k(  r|S t        j                  dj                               )	a  
        Prompt the user for a path.

        :param str label: The user-friendly label for the file.
        :param callable validator: A method which will be called to validate the supplied input
            after it has been validated to be a non-empty path to an existing file. Should throw a
            `~certbot.errors.PluginError` to indicate any issue.
        :returns: The user's response (guaranteed to exist).
        :rtype: str
        rm   r   Nc                     | s$t        j                  dj                              t        j                  j                  |       } t        |        r	 |        y y )Nz&Please enter a valid path to your {0}.)r   ry   r3   r   rf   rh   validate_file)rm   r[   rc   s    r   rq   z6DNSAuthenticator._prompt_for_file.<locals>.__validator   sP    (()Q)X)XY^)_``ww))(3H(#(# r    zInput the path to your {0}Trz   r|   )rr   r   validated_directoryr3   rM   r~   r   ry   )r[   rc   rs   r   rL   s   ``   r   re   z!DNSAuthenticator._prompt_for_file   sp    		$# 		$$ 		$ 00(//6"$h
 <??"O  !;!B!B5!IJJr    )
   )r   Nr8   )NN)(__name__
__module____qualname____doc__r   NamespaceConfigrr   r   classmethodr   r(   r*   r   r   AnnotatedChallenger5   r   r	   r
   	Challenger:   r>   rB   ChallengeResponserQ   rT   abcabstractmethodrE   rJ   rS   rb   r   ri   r   ru   staticmethodr]   re   __classcell__)r   s   @r   r   r      s   +&}<< &C &D &
 @B.x	': .:=.GK. .
[-K-K(L 
QT 
"C "HT*BVBV=W4X "$3 $tK$B$BC *6670JtK$B$BC J J 	$ $ 	
$s 
$S 
$ 
$%)
$ 
$ 	$s $S $ $%)$ $<c <# <$ <" FJa3 as a#+HcUD[,A#BaNRa$ W[LP&)&)"&)8@cAR8S&)H&@%A4%GHI&) 
$&)P K K K K, K K3%+9N0O K[^ K Kr    r   )	metaclassc                       e Zd ZdZd fdedeegef   ddfdZdeeef   ddfd	Zd
ede	e   fdZ
d
edefdZd
ede	e   fdZy)rk   z>Represents a user-supplied filed which stores API credentials.c                     | S r8   r<   )xs    r   <lambda>z!CredentialsConfiguration.<lambda>  s    q r    rm   mapperr   Nc                    t        |       	 t        j                  |      | _        || _
        y# t        j                  $ rC}t
        j                  d||d       t        j                  dj                  ||            d}~ww xY w)z
        :param str filename: A path to the configuration file.
        :param callable mapper: A transformation to apply to configuration key names
        :raises errors.PluginError: If the file does not exist or is not a valid format.
        z0Error parsing credentials configuration '%s': %sT)exc_infoz0Error parsing credentials configuration '{}': {}N)validate_file_permissions	configobj	ConfigObjconfobjConfigObjErrorloggerdebugr   ry   r3   r   )r   rm   r   es       r   r   z!CredentialsConfiguration.__init__  s     	"(+	$..x8DL  '' 	LLB	   $$BII 	s   / B>B  Brj   c           	         g }|D ]  }| j                  |      s4|j                  dj                  | j                  |      ||                H| j	                  |      rZ|j                  dj                  | j                  |      ||                 |rYt        j                  dj                  t        |      dk(  rdnd| j                  j                  dj                  |                  y)	zEnsures that the supplied set of variables are all present in the file.

        :param dict required_variables: Map of variable which must be present to error to display.
        :raises errors.PluginError: If one or more are missing.
        z)Property "{0}" not found (should be {1}).z'Property "{0}" not set (should be {1}).z9Missing {0} in credentials configuration file {1}:
 * {2}r-   property
propertiesz
 * N)_hasrK   r3   r   _getr   ry   lenr   rm   join)r   rj   messagesvars       r   ro   z CredentialsConfiguration.require"  s     % 	TC99S> K!'C(8:LS:Q!RTYYs^ I!'C(8:LS:Q!RT	T $$LSS&)(mq&8
l--X.  r    r   c                 $    | j                  |      S )zFind a configuration value for variable `var`, as transformed by `mapper`.

        :param str var: The variable to get.
        :returns: The value of the variable, if it exists.
        :rtype: str or None
        )r   r   r   s     r   r2   zCredentialsConfiguration.conf;  s     yy~r    c                 <    | j                  |      | j                  v S r8   )r   r   r   s     r   r   zCredentialsConfiguration._hasE  s    {{34<<//r    c                 V    | j                   j                  | j                  |            S r8   )r   getr   r   s     r   r   zCredentialsConfiguration._getH  s     ||C 011r    )r   r   r   r   rr   r   r   r   ro   r   r2   boolr   r   r<   r    r   rk   rk     s    HEP  hucz.B UY 4'#s(*;  2  0 0 02 2 2r    rk   rm   r   c                    t         j                  j                  |       s$t        j                  dj                  |             t         j                  j                  |       r$t        j                  dj                  |             y)z&Ensure that the specified file exists.zFile not found: {0}zPath is a directory: {0}N)r   rf   existsr   ry   r3   isdirrm   s    r   r   r   L  sc     77>>(#  !6!=!=h!GHH	ww}}X  !;!B!B8!LMM r    c                 r    t        |        t        j                  |       rt        j	                  d|        yy)zHEnsure that the specified file exists and warn about unsafe permissions.z8Unsafe permissions on credentials configuration file: %sN)r   r   has_world_permissionsr   warningr   s    r   r   r   V  s/     (''1QS[\ 2r    rF   c                     | j                  d      }t        dt        |            D cg c]  }dj                  ||d        c}S c c}w )a  Return a list of progressively less-specific domain names.

    One of these will probably be the domain name known to the DNS provider.

    :Example:

    >>> base_domain_name_guesses('foo.bar.baz.example.com')
    ['foo.bar.baz.example.com', 'bar.baz.example.com', 'baz.example.com', 'example.com', 'com']

    :param str domain: The domain for which to return guesses.
    :returns: The a list of less specific domain names.
    :rtype: list
    .r   N)splitranger   r   )rF   	fragmentsrw   s      r   base_domain_name_guessesr   _  s@     S!I-21c)n-EFCHHYqr]#FFFs   A))r   r   loggingtimer   typingr   r   r   r   r   r	   r   acmer
   certbotr   r   r   r   certbot.compatr   r   certbot.displayr   r   rM   certbot.pluginsr   	getLoggerr   r   PluginAuthenticatorABCMetar   rk   rr   r   r   r   r<   r    r   <module>r      s    0 
            !   %   0 "			8	$fKv}}j&>&>#++ fKRD2 D2NNC ND N] ] ]GS GT#Y Gr    