
\\C                 @   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 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 m Z e j e  Z d d   Z d d   Z e j d  Z e j d e j  Z  e	 j! j" e j#  Gd d   d e$   Z% Gd d   d e%  Z& Gd d   d e$  Z' Gd d   d e$  Z( Gd d   d e(  Z) d d   Z* d d   Z+ d S) zPlugin common functions.    N)util)List)achallenges)	constants)crypto_util)errors)
interfaces)reverter)PluginStoragec             C   s   |  d S)z9ArgumentParser options namespace (prefix of all options).- )namer   r   8/usr/lib/python3/dist-packages/certbot/plugins/common.pyoption_namespace   s    r   c             C   s   |  j  d d  d S)z;ArgumentParser dest namespace (prefix of all destinations).r   _)replace)r   r   r   r   dest_namespace!   s    r   zX(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)z3^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*[a-z]+$c               @   s   e  Z d  Z d Z d d   Z e j d d    Z e d d    Z	 e
 d d	    Z d
 d   Z e
 d d    Z d d   Z d d   Z d S)PluginzGeneric plugin.c             C   s   | |  _  | |  _ d  S)N)configr   )selfr   r   r   r   r   __init__2   s    	zPlugin.__init__c             C   s   d S)a  Add plugin arguments to the CLI argument parser.

        NOTE: If some of your flags interact with others, you can
        use cli.report_config_interaction to register this to ensure
        values are correctly saved/overridable during renewal.

        :param callable add: Function that proxies calls to
            `argparse.ArgumentParser.add_argument` prepending options
            with unique plugin name prefix.

        Nr   )clsaddr   r   r   add_parser_arguments6   s    zPlugin.add_parser_argumentsc                s"      f d d   } |  j  |  S)zYInject parser options.

        See `~.IPlugin.inject_parser_options` for docs.

        c                s%    j  d j t    |   | |  S)Nz--{0}{1})add_argumentformatr   )Zarg_name_no_prefixargskwargs)r   parserr   r   r   L   s    z)Plugin.inject_parser_options.<locals>.add)r   )r   r   r   r   r   )r   r   r   inject_parser_optionsD   s    zPlugin.inject_parser_optionsc             C   s   t  |  j  S)z9ArgumentParser options namespace (prefix of all options).)r   r   )r   r   r   r   r   S   s    zPlugin.option_namespacec             C   s   |  j  | S)z'Option name (include plugin namespace).)r   )r   r   r   r   r   option_nameX   s    zPlugin.option_namec             C   s   t  |  j  S)z;ArgumentParser dest namespace (prefix of all destinations).)r   r   )r   r   r   r   r   \   s    zPlugin.dest_namespacec             C   s   |  j  | j d d  S)z.Find a destination for given variable ``var``.r   r   )r   r   )r   varr   r   r   desta   s    zPlugin.destc             C   s   t  |  j |  j |   S)z0Find a configuration value for variable ``var``.)getattrr   r"   )r   r!   r   r   r   confg   s    zPlugin.confN)__name__
__module____qualname____doc__r   	jose_utilabstractclassmethodr   classmethodr   propertyr   r    r   r"   r$   r   r   r   r   r   ,   s   r   c                   s   e  Z d  Z d Z   f d d   Z d d d  Z d d   Z d	 d
   Z d d   Z d d d  Z	 d d   Z
 e d d    Z e d d    Z d d   Z   S)	InstallerzAn installer base class with reverter and ssl_dhparam methods defined.

    Installer plugins do not have to inherit from this class.

    c                sJ   t  t |   j | |   t |  j |  j  |  _ t j |  j  |  _ d  S)N)	superr-   r   r
   r   r   Zstorager	   ZReverter)r   r   r   )	__class__r   r   r   r   s    zInstaller.__init__Fc             C   sv   | r |  j  j } n |  j  j } y | | |  Wn= t j k
 rq } z t j t |    WYd d } ~ Xn Xd S)a  Add files to a checkpoint.

        :param set save_files: set of filepaths to save
        :param str save_notes: notes about changes during the save
        :param bool temporary: True if the files should be added to a
            temporary checkpoint rather than a permanent one. This is
            usually used for changes that will soon be reverted.

        :raises .errors.PluginError: when unable to add to checkpoint

        N)r	   Zadd_to_temp_checkpointadd_to_checkpointr   ReverterErrorPluginErrorstr)r   Z
save_filesZ
save_notesZ	temporaryZcheckpoint_funcerrr   r   r   r0   w   s    zInstaller.add_to_checkpointc             C   sX   y |  j  j |  Wn= t j k
 rS } z t j t |    WYd d } ~ Xn Xd S)zTimestamp and save changes made through the reverter.

        :param str title: Title describing checkpoint

        :raises .errors.PluginError: when an error occurs

        N)r	   finalize_checkpointr   r1   r2   r3   )r   titler4   r   r   r   r5      s    zInstaller.finalize_checkpointc             C   sU   y |  j  j   Wn= t j k
 rP } z t j t |    WYd d } ~ Xn Xd S)zRevert all previously modified files.

        Reverts all modified files that have not been saved as a checkpoint

        :raises .errors.PluginError: If unable to recover the configuration

        N)r	   recovery_routiner   r1   r2   r3   )r   r4   r   r   r   r7      s    zInstaller.recovery_routinec             C   sU   y |  j  j   Wn= t j k
 rP } z t j t |    WYd d } ~ Xn Xd S)zkRollback temporary checkpoint.

        :raises .errors.PluginError: when unable to revert config

        N)r	   revert_temporary_configr   r1   r2   r3   )r   r4   r   r   r   r8      s    z!Installer.revert_temporary_config   c             C   sX   y |  j  j |  Wn= t j k
 rS } z t j t |    WYd d } ~ Xn Xd S)zRollback saved checkpoints.

        :param int rollback: Number of checkpoints to revert

        :raises .errors.PluginError: If there is a problem with the input or
            the function is unable to correctly revert the configuration

        N)r	   rollback_checkpointsr   r1   r2   r3   )r   Zrollbackr4   r   r   r   r:      s    	zInstaller.rollback_checkpointsc             C   sU   y |  j  j   Wn= t j k
 rP } z t j t |    WYd d } ~ Xn Xd S)zShow all of the configuration changes that have taken place.

        :raises .errors.PluginError: If there is a problem while processing
            the checkpoints directories.

        N)r	   view_config_changesr   r1   r2   r3   )r   r4   r   r   r   r;      s    zInstaller.view_config_changesc             C   s   t  j j |  j j t j  S)z(Full absolute path to ssl_dhparams file.)ospathjoinr   
config_dirr   ZSSL_DHPARAMS_DEST)r   r   r   r   ssl_dhparams   s    zInstaller.ssl_dhparamsc             C   s   t  j j |  j j t j  S)z:Full absolute path to digest of updated ssl_dhparams file.)r<   r=   r>   r   r?   r   ZUPDATED_SSL_DHPARAMS_DIGEST)r   r   r   r   updated_ssl_dhparams_digest   s    z%Installer.updated_ssl_dhparams_digestc             C   s   t  |  j |  j t j t j  S)zJCopy Certbot's ssl_dhparams file into the system's config dir if required.)install_version_controlled_filer@   rA   r   ZSSL_DHPARAMS_SRCZALL_SSL_DHPARAMS_HASHES)r   r   r   r   install_ssl_dhparams   s
    zInstaller.install_ssl_dhparams)r%   r&   r'   r(   r   r0   r5   r7   r8   r:   r;   r,   r@   rA   rC   r   r   )r/   r   r-   l   s   r-   c               @   s   e  Z d  Z d Z d d d  Z e d d    Z d d   Z d	 d
   Z d d   Z	 d d   Z
 d d   Z d d   Z d d   Z d d   Z d d   Z d d   Z d S)AddrzRepresents an virtual host address.

    :param str addr: addr part of vhost address
    :param str port: port number or \*, or ""

    Fc             C   s   | |  _  | |  _ d  S)N)tupipv6)r   rE   rF   r   r   r   r      s    	zAddr.__init__c             C   s   | j  d  r | j d  } | d | d  } d } t |  | d k rv | | d d k rv | | d d  } |  | | f d d	 S| j d  } |  | d
 | d f  Sd S)zInitialize Addr from string.[]Nr9       :rF   Tr   )
startswithrfindlen	partition)r   Zstr_addrZendIndexhostportrE   r   r   r   
fromstring   s    *zAddr.fromstringc             C   s#   |  j  d r d |  j  S|  j  d S)Nr9   z%s:%sr   )rE   )r   r   r   r   __str__   s    zAddr.__str__c             C   s'   |  j  r  |  j   |  j d f S|  j S)z5Normalized representation of addr/port tuple
        r9   )rF   get_ipv6_explodedrE   )r   r   r   r   normalized_tuple   s    	zAddr.normalized_tuplec             C   s,   t  | |  j  r( |  j   | j   k Sd S)NF)
isinstancer/   rU   )r   otherr   r   r   __eq__  s    zAddr.__eq__c             C   s   t  |  j  S)N)hashrE   )r   r   r   r   __hash__  s    zAddr.__hash__c             C   s   |  j  d S)z Return addr part of Addr object.r   )rE   )r   r   r   r   get_addr  s    zAddr.get_addrc             C   s   |  j  d S)zReturn port.r9   )rE   )r   r   r   r   get_port  s    zAddr.get_portc             C   s    |  j  |  j d | f |  j  S)z6Return new address object with same addr and new port.r   )r/   rE   rF   )r   rQ   r   r   r   get_addr_obj  s    zAddr.get_addr_objc             C   s+   | j  d  } | j d  } |  j |  S)z7Return IPv6 address in normalized form, helper functionrG   rH   )lstriprstrip_explode_ipv6)r   addrr   r   r   _normalize_ipv6  s    zAddr._normalize_ipv6c             C   s*   |  j  r& d j |  j |  j d   Sd S)zReturn IPv6 in normalized formrK   r   rI   )rF   r>   rb   rE   )r   r   r   r   rT   "  s    	zAddr.get_ipv6_explodedc             C   s  d d d d d d d d g } | j  d  } t |  t |  k r[ | d t |   } d } x t d t |   D] } | | } t |  d k r d } qw n! t |  d k r | j d  } | s t |  | | <qw t |  | | t |  <qw W| S)z#Explode IPv6 address for comparison0rK   r   FTr9   )splitrN   ranger^   r3   )r   ra   resultZ	addr_listZappend_to_endiblockr   r   r   r`   (  s     
zAddr._explode_ipv6N)r%   r&   r'   r(   r   r+   rR   rS   rU   rX   rZ   r[   r\   r]   rb   rT   r`   r   r   r   r   rD      s   rD   c               @   s=   e  Z d  Z d Z d d   Z d d d  Z d d   Z d S)	ChallengePerformerav  Abstract base for challenge performers.

    :ivar configurator: Authenticator and installer plugin
    :ivar achalls: Annotated challenges
    :vartype achalls: `list` of `.KeyAuthorizationAnnotatedChallenge`
    :ivar indices: Holds the indices of challenges from a larger array
        so the user of the class doesn't have to.
    :vartype indices: `list` of `int`

    c             C   s   | |  _  g  |  _ g  |  _ d  S)N)configuratorachallsindices)r   rj   r   r   r   r   N  s    		zChallengePerformer.__init__Nc             C   s0   |  j  j |  | d k	 r, |  j j |  d S)zStore challenge to be performed when perform() is called.

        :param .KeyAuthorizationAnnotatedChallenge achall: Annotated
            challenge.
        :param int idx: index to challenge in a larger array

        N)rk   appendrl   )r   achallidxr   r   r   	add_challS  s    zChallengePerformer.add_challc             C   s   t     d S)zPerform all added challenges.

        :returns: challenge respones
        :rtype: `list` of `acme.challenges.KeyAuthorizationChallengeResponse`


        N)NotImplementedError)r   r   r   r   perform_  s    zChallengePerformer.perform)r%   r&   r'   r(   r   rp   rr   r   r   r   r   ri   B  s   
ri   c                   s[   e  Z d  Z d Z   f d d   Z d d   Z d d   Z d d	   Z d
 d d  Z   S)TLSSNI01z1Abstract base for TLS-SNI-01 challenge performersc                s8   t  t |   j |  t j j | j j d  |  _ d  S)Nz!le_tls_sni_01_cert_challenge.conf)	r.   rs   r   r<   r=   r>   r   r?   Zchallenge_conf)r   rj   )r/   r   r   r   n  s    	zTLSSNI01.__init__c             C   s,   t  j j |  j j j | j j d  d  S)zReturns standardized name for challenge certificate.

        :param .KeyAuthorizationAnnotatedChallenge achall: Annotated
            tls-sni-01 challenge.

        :returns: certificate file name
        :rtype: str

        tokenz.crt)r<   r=   r>   rj   r   work_dirchallencode)r   rn   r   r   r   get_cert_patht  s    
zTLSSNI01.get_cert_pathc             C   s,   t  j j |  j j j | j j d  d  S)z'Get standardized path to challenge key.rt   z.pem)r<   r=   r>   rj   r   ru   rv   rw   )r   rn   r   r   r   get_key_path  s    zTLSSNI01.get_key_pathc             C   s   | j  | j  j j d  S)z.Returns z_domain (SNI) name for the challenge.zutf-8)responseZaccount_keyZz_domaindecode)r   rn   r   r   r   get_z_domain  s    zTLSSNI01.get_z_domainNc             C   s   |  j  |  } |  j |  } |  j j j d |  |  j j j d |  | j d |  \ } \ } } t j j t j j	 |  } t j j
 t j j	 |  }	 t | d   }
 |
 j |  Wd QRXt j | d d d  } | j |	  Wd QRX| S)z-Generate and write out challenge certificate.Tcert_keywbNchmod   )rx   ry   rj   r	   Zregister_file_creationZresponse_and_validationOpenSSLZcryptoZdump_certificateZFILETYPE_PEMZdump_privatekeyopenwriter   Z	safe_open)r   rn   r}   Z	cert_pathZkey_pathrz   ZcertkeyZcert_pemZkey_pemZcert_chall_fdZkey_filer   r   r   _setup_challenge_cert  s    			zTLSSNI01._setup_challenge_cert)	r%   r&   r'   r(   r   rx   ry   r|   r   r   r   )r/   r   rs   j  s   rs   c                s   t  j      f d d         f d d   } t j j   sY |   d St  j   } |  k rx d S| | k r |   nd t j j   r t  d   } | j   } Wd QRX|  k r d S    t j d     d S)a  Copy a file into an active location (likely the system's config dir) if required.

       :param str dest_path: destination path for version controlled file
       :param str digest_path: path to save a digest of the file in
       :param str src_path: path to version controlled file found in distribution
       :param list all_hashes: hashes of every released version of the file
    c           	      s*   t   d   }  |  j    Wd  QRXd  S)Nw)r   r   )f)current_hashdigest_pathr   r   _write_current_hash  s    z<install_version_controlled_file.<locals>._write_current_hashc                  s   t  j        d  S)N)shutilZcopyfiler   )r   	dest_pathsrc_pathr   r   _install_current_file  s    z>install_version_controlled_file.<locals>._install_current_fileNrzh%s has been manually modified; updated file saved to %s. We recommend updating %s for security purposes.)	r   Z	sha256sumr<   r=   isfiler   readloggerZwarning)r   r   r   Z
all_hashesr   Zactive_file_digestr   Zsaved_digestr   )r   r   r   r   r   r   rB     s&    
	rB   c             C   s   d d   } | d  } | d  } | d  } t  j | t j  t  j | t j  t  j | t j  t j | t  j j d |    } t j	 | t  j j | |   d d | | | f S)	z5Setup the directories necessary for the configurator.c             S   s   t  j j t j |    S)a  Return the real path of a temp directory with the specified prefix

        Some plugins rely on real paths of symlinks for working correctly. For
        example, certbot-apache uses real paths of configuration files to tell
        a virtual host from another. On systems where TMP itself is a symbolic
        link, (ex: OS X) such plugins will be confused. This function prevents
        such a case.
        )r<   r=   realpathtempfileZmkdtemp)prefixr   r   r   expanded_tempdir  s    	z#dir_setup.<locals>.expanded_tempdirZtempr   ZworkZtestdataZsymlinksT)
r<   r   r   ZCONFIG_DIRS_MODEpkg_resourcesZresource_filenamer=   r>   r   Zcopytree)Ztest_dirpkgr   Ztemp_dirr?   ru   Ztest_configsr   r   r   	dir_setup  s    r   ),r(   Zloggingr<   rer   r   r   r   Zzope.interfacezopeZjosepyr   r)   Zacme.magic_typingr   Zcertbotr   r   r   r   r   r	   Zcertbot.plugins.storager
   Z	getLoggerr%   r   r   r   compileZprivate_ips_regex
IGNORECASEZhostname_regexZ	interfaceZimplementerZIPluginobjectr   r-   rD   ri   rs   rB   r   r   r   r   r   <module>   sB   	?sc(92