
¡\\h<  ã               @   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	 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 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" d# „ Z# d! d d$ d% „ Z$ d& d' „  Z% d( d) „  Z& d* d+ „  Z' d, d- „  Z( d S).z Tools for managing certificates.é    N)ÚList)Úcompat)Úcrypto_util)Úerrors)Ú
interfaces)Úocsp)Ústorage)Úutilc             C   s4   x- t  j |  ƒ D] } t  j | |  d d ƒq Wd S)a`  Update the certificate file family symlinks to use archive_dir.

    Use the information in the config file to make symlinks point to
    the correct archive directory.

    .. note:: This assumes that the installation is using a Reverter object.

    :param config: Configuration.
    :type config: :class:`certbot.configuration.NamespaceConfig`

    Zupdate_symlinksTN)r   Úrenewal_conf_filesÚRenewableCert)ÚconfigÚrenewal_file© r   ú6/usr/lib/python3/dist-packages/certbot/cert_manager.pyÚupdate_live_symlinks   s    r   c             C   sé   t  j j t j ƒ } t |  d ƒ d } |  j } | s† | j d j | ƒ d d d d ƒ\ } } | t	 j
 k sw | r† t j d ƒ ‚ t |  | ƒ } | s³ t j d	 j | ƒ ƒ ‚ t j | | |  ƒ | j d
 j | | ƒ d d ƒd S)z—Rename the specified lineage to the new name.

    :param config: Configuration.
    :type config: :class:`certbot.configuration.NamespaceConfig`

    Úrenamer   z&Enter the new name for certificate {0}Zflagz--updated-cert-nameÚforce_interactiveTzUser ended interaction.z,No existing certificate with name {0} found.z Successfully renamed {0} to {1}.ÚpauseFN)ÚzopeÚ	componentÚ
getUtilityr   ÚIDisplayÚget_certnamesÚnew_certnameÚinputÚformatÚdisplay_utilÚOKr   ÚErrorÚlineage_for_certnameZConfigurationErrorr   Zrename_renewal_configÚnotification)r   ÚdispÚcertnamer   ÚcodeÚlineager   r   r   Úrename_lineage*   s     	r%   c             C   sÈ   g  } g  } x¥ t  j |  ƒ D]” } y0 t  j | |  ƒ } t j | ƒ | j | ƒ Wq t k
 r¯ } z; t j d | | ƒ t j	 d t
 j ƒ  ƒ | j | ƒ WYd d } ~ Xq Xq Wt |  | | ƒ d S)z Display information about certs configured with Certbot

    :param config: Configuration.
    :type config: :class:`certbot.configuration.NamespaceConfig`
    zIRenewal configuration file %s produced an unexpected error: %s. Skipping.zTraceback was:
%sN)r   r
   r   r   Zverify_renewable_certÚappendÚ	ExceptionÚloggerZwarningÚdebugÚ	tracebackÚ
format_excÚ_describe_certs)r   Úparsed_certsÚparse_failuresr   Zrenewal_candidateÚer   r   r   ÚcertificatesE   s    	
$r0   c             C   sk   t  |  d d d ƒ} xO | D]G } t j |  | ƒ t j j t j ƒ } | j d j	 | ƒ d d ƒq Wd S)z;Delete Certbot files associated with a certificate lineage.ÚdeleteÚallow_multipleTz.Deleted all files relating to certificate {0}.r   FN)
r   r   Zdelete_filesr   r   r   r   r   r    r   )r   Ú	certnamesr"   r!   r   r   r   r1   [   s    r1   c             C   sº   |  j  } t j | d d d t j ƒ  ƒy t j |  | ƒ } Wn t j k
 rY d SYn Xy t j	 | |  ƒ SWnE t j t
 f k
 rµ t j d | ƒ t j d t j ƒ  ƒ d SYn Xd S)z)Find a lineage object with name certname.Úmodeií  ÚuidNzRenewal conf file %s is broken.zTraceback was:
%s)Úrenewal_configs_dirr	   Úmake_or_verify_dirr   Ú
os_geteuidr   Zrenewal_file_for_certnamer   ÚCertStorageErrorr   ÚIOErrorr(   r)   r*   r+   )Ú
cli_configr"   Úconfigs_dirr   r   r   r   r   h   s    		r   c             C   s#   t  |  | ƒ } | r | j ƒ  Sd S)z0Find the domains in the cert with name certname.N)r   Únames)r   r"   r$   r   r   r   Údomains_for_certnamex   s    r>   c                s"   ‡  f d d †  } t  |  | d ƒ S)a~  Find existing certs that match the given domain names.

    This function searches for certificates whose domains are equal to
    the `domains` parameter and certificates whose domains are a subset
    of the domains in the `domains` parameter. If multiple certificates
    are found whose names are a subset of `domains`, the one whose names
    are the largest subset of `domains` is returned.

    If multiple certificates' domains are an exact match or equally
    sized subsets, which matching certificates are returned is
    undefined.

    :param config: Configuration.
    :type config: :class:`certbot.configuration.NamespaceConfig`
    :param domains: List of domain names
    :type domains: `list` of `str`

    :returns: lineages representing the identically matching cert and the
        largest subset if they exist
    :rtype: `tuple` of `storage.RenewableCert` or `None`

    c                s‘   | \ } } t  |  j ƒ  ƒ } | t  ˆ  ƒ k r9 |  } nN | j t  ˆ  ƒ ƒ r‡ | d k rc |  } n$ t | ƒ t | j ƒ  ƒ k r‡ |  } | | f S)zsReturn cert as identical_names_cert if it matches,
           or subset_names_cert if it matches as subset
        N)Úsetr=   ÚissubsetÚlen)Úcandidate_lineageÚrvZidentical_names_certZsubset_names_certZcandidate_names)Údomainsr   r   Úupdate_certs_for_domain_matches”   s    		z?find_duplicative_certs.<locals>.update_certs_for_domain_matchesN)NN)Ú_search_lineages)r   rD   rE   r   )rD   r   Úfind_duplicative_certs}   s    rG   c                sL   |  j  ‰  ‡  ‡ f d d †  t j ˆ  ƒ Dƒ } t | ƒ d k rD | Sd Sd S)aJ   In order to match things like:
        /etc/letsencrypt/archive/example.com/chain1.pem.

        Anonymous functions which call this function are eventually passed (in a list) to
        `match_and_check_overlaps` to help specify the acceptable_matches.

        :param `.storage.RenewableCert` candidate_lineage: Lineage whose archive dir is to
            be searched.
        :param str filetype: main file name prefix e.g. "fullchain" or "chain".

        :returns: Files in candidate_lineage's archive dir that match the provided filetype.
        :rtype: list of str or None
    c                s@   g  |  ]6 } t  j d  j ˆ ƒ | ƒ r t j j ˆ  | ƒ ‘ q S)z{0}[0-9]*.pem)ÚreÚmatchr   ÚosÚpathÚjoin)Ú.0Úf)Úarchive_dirÚfiletyper   r   ú
<listcomp>¸   s   	 z"_archive_files.<locals>.<listcomp>r   N)rO   rJ   ÚlistdirrA   )rB   rP   Úpatternr   )rO   rP   r   Ú_archive_files©   s
    	%rT   c               C   s(   d d „  d d „  d d „  d d „  g S)zª Generates the list that's passed to match_and_check_overlaps. Is its own function to
    make unit testing easier.

    :returns: list of functions
    :rtype: list
    c             S   s   |  j  S)N)Zfullchain_path)Úxr   r   r   Ú<lambda>Æ   s    z%_acceptable_matches.<locals>.<lambda>c             S   s   |  j  S)N)Ú	cert_path)rU   r   r   r   rV   Æ   s    c             S   s   t  |  d ƒ S)NÚcert)rT   )rU   r   r   r   rV   Ç   s    c             S   s   t  |  d ƒ S)NÚ	fullchain)rT   )rU   r   r   r   rV   Ç   s    r   r   r   r   r   Ú_acceptable_matches¿   s    rZ   c                s8   t  ƒ  } t ˆ  | ‡  f d d †  d d „  ƒ } | d S)a“   If config.cert_path is defined, try to find an appropriate value for config.certname.

    :param `configuration.NamespaceConfig` cli_config: parsed command line arguments

    :returns: a lineage name
    :rtype: str

    :raises `errors.Error`: If the specified cert path can't be matched to a lineage name.
    :raises `errors.OverlappingMatchFound`: If the matched lineage's archive is shared.
    c                s   ˆ  j  d S)Nr   )rW   )rU   )r;   r   r   rV   Ö   s    z&cert_path_to_lineage.<locals>.<lambda>c             S   s   |  j  S)N)Úlineagename)rU   r   r   r   rV   Ö   s    r   )rZ   Úmatch_and_check_overlaps)r;   Úacceptable_matchesrI   r   )r;   r   Úcert_path_to_lineageÉ   s    		r^   c                s{   ‡  ‡ f d d †  } t  |  | g  | ƒ } | sR t j d j |  j d ƒ ƒ ‚ n% t | ƒ d k rs t j ƒ  ‚ n | Sd S)a   Searches through all lineages for a match, and checks for duplicates.
    If a duplicate is found, an error is raised, as performing operations on lineages
    that have their properties incorrectly duplicated elsewhere is probably a bad idea.

    :param `configuration.NamespaceConfig` cli_config: parsed command line arguments
    :param list acceptable_matches: a list of functions that specify acceptable matches
    :param function match_func: specifies what to match
    :param function rv_func: specifies what to return

    c                sˆ   ‡  f d d †  | Dƒ } g  } x7 | D]/ } t  | t ƒ rH | | 7} q& | j | ƒ q& Wˆ ˆ  ƒ } | | k r„ | j ˆ ˆ  ƒ ƒ | S)z1Returns a list of matches using _search_lineages.c                s   g  |  ] } | ˆ  ƒ ‘ q Sr   r   )rM   Úfunc)rB   r   r   rQ   æ   s   	 zBmatch_and_check_overlaps.<locals>.find_matches.<locals>.<listcomp>)Ú
isinstanceÚlistr&   )rB   Zreturn_valuer]   Zacceptable_matches_rvÚitemrI   )Ú
match_funcÚrv_func)rB   r   Úfind_matchesä   s    z.match_and_check_overlaps.<locals>.find_matchesz!No match found for cert-path {0}!r   é   N)rF   r   r   r   rW   rA   ZOverlappingMatchFound)r;   r]   rc   rd   re   Zmatchedr   )rc   rd   r   r\   Ù   s    "r\   Fc       
      C   s³  g  } t  j ƒ  } |  j r8 | j |  j k r8 | r8 d S|  j rd t |  j ƒ j | j ƒ  ƒ rd d St j	 j
 t j j ƒ  ƒ } g  } | j r› | j d ƒ | j | k r· | j d ƒ | j | j | j ƒ rÜ | j d ƒ | rø d d j | ƒ } n_ | j | } | j d k rd } n: | j d k  rEd	 j | j d
 ƒ } n d j | j ƒ } d j | j | ƒ }	 | j d j | j d j | j ƒ  ƒ |	 | j | j ƒ ƒ d j | ƒ S)zJ Returns a human readable description of info about a RenewableCert objectÚ Z	TEST_CERTZEXPIREDZREVOKEDz	INVALID: z, rf   zVALID: 1 dayzVALID: {0} hour(s)i  zVALID: {0} daysz	{0} ({1})zq  Certificate Name: {0}
    Domains: {1}
    Expiry Date: {2}
    Certificate Path: {3}
    Private Key Path: {4}ú )r   ZRevocationCheckerr"   r[   rD   r?   r@   r=   ÚpytzZUTCZfromutcÚdatetimeZutcnowZis_test_certr&   Ztarget_expiryZocsp_revokedrX   ÚchainrL   Zdaysr   ZsecondsrY   Zprivkey)
r   rX   Zskip_filter_checksÚcertinfoZcheckerZnowZreasonsZstatusZdiffZvalid_stringr   r   r   Úhuman_readable_cert_infoú   s<    "(		rm   c             C   s\  |  j  } | r | g } n=t j j t j ƒ } t j |  ƒ } d d „  | Dƒ } | sg t j	 d ƒ ‚ | rÐ | s… d j
 | ƒ }	 n | }	 | j |	 | d d d d ƒ\ }
 } |
 t j k rXt j	 d	 ƒ ‚ nˆ | sè d
 j
 | ƒ }	 n | }	 | j |	 | d d d d ƒ\ }
 } |
 t j k s<| t d t | ƒ ƒ k rKt j	 d	 ƒ ‚ | | g } | S)z9Get certname from flag, interactively, or error out.
    c             S   s   g  |  ] } t  j | ƒ ‘ q Sr   )r   Zlineagename_for_filename)rM   Únamer   r   r   rQ   .  s   	 z!get_certnames.<locals>.<listcomp>zNo existing certificates found.z+Which certificate(s) would you like to {0}?Zcli_flagz--cert-namer   TzUser ended interaction.z(Which certificate would you like to {0}?r   )r"   r   r   r   r   r   r   r
   r   r   r   Z	checklistr   r   ZmenuÚrangerA   )r   Zverbr2   Zcustom_promptr"   r3   r!   Ú	filenamesÚchoicesÚpromptr#   Úindexr   r   r   r   %  s2    	*r   c             C   s   d d j  d d „  |  Dƒ ƒ S)zFFormat a results report for a category of single-line renewal outcomesz  z
  c             s   s   |  ] } t  | ƒ Vq d  S)N)Ústr)rM   Úmsgr   r   r   ú	<genexpr>N  s    z _report_lines.<locals>.<genexpr>)rL   )Zmsgsr   r   r   Ú_report_linesL  s    rw   c             C   s:   g  } x$ | D] } | j  t |  | ƒ ƒ q Wd j | ƒ S)z)Format a results report for a parsed certÚ
)r&   rm   rL   )r   r-   rl   rX   r   r   r   Ú_report_human_readableP  s    ry   c             C   sÏ   g  } | j  } | r* | r* | d ƒ nj | rt |  j sB |  j rH d n d } | d j | ƒ ƒ | t |  | ƒ ƒ | r” | d ƒ | t | ƒ ƒ t j j t	 j
 ƒ } | j d j | ƒ d d d	 d ƒd
 S)z/Print information about the certs we know aboutzNo certs found.z	matching rg   zFound the following {0}certs:z3
The following renewal configurations were invalid:rx   r   FZwrapN)r&   r"   rD   r   ry   rw   r   r   r   r   r   r    rL   )r   r-   r.   ÚoutZnotifyrI   r!   r   r   r   r,   W  s    	
r,   c             G   s»   |  j  } t j | d d d t j ƒ  ƒ| } x† t j |  ƒ D]u } y t j | |  ƒ } WnD t j	 t
 f k
 r  t j d | ƒ t j d t j ƒ  ƒ w> Yn X| | | | Œ } q> W| S)aâ  Iterate func over unbroken lineages, allowing custom return conditions.

    Allows flexible customization of return values, including multiple
    return values and complex checks.

    :param `configuration.NamespaceConfig` cli_config: parsed command line arguments
    :param function func: function used while searching over lineages
    :param initial_rv: initial return value of the function (any type)

    :returns: Whatever was specified by `func` if a match is found.
    r4   ií  r5   z)Renewal conf file %s is broken. Skipping.zTraceback was:
%s)r6   r	   r7   r   r8   r   r
   r   r   r9   r:   r(   r)   r*   r+   )r;   r_   Z
initial_rvÚargsr<   rC   r   rB   r   r   r   rF   l  s    	rF   ))Ú__doc__rj   ZloggingrJ   ri   rH   r*   Zzope.componentr   Zacme.magic_typingr   Zcertbotr   r   r   r   r   r   r	   Zcertbot.displayr   Z	getLoggerÚ__name__r(   r   r%   r0   r1   r   r>   rG   rT   rZ   r^   r\   rm   r   rw   ry   r,   rF   r   r   r   r   Ú<module>   sD   ,
!+'