ó
Á£ô_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 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 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z  d „  Z! d „  Z" d „  Z# e$ d „ Z% e$ d d „ Z' d „  Z( d „  Z) d „  Z* d „  Z+ d S(   s    Tools for managing certificates.iÿÿÿÿN(   t   List(   t   crypto_util(   t   errors(   t
   interfaces(   t   ocsp(   t   util(   t   storage(   t   osc         C   s4   x- t  j |  ƒ D] } t  j | |  d t ƒq Wd S(   sj  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._internal.configuration.NamespaceConfig`

    t   update_symlinksN(   R   t   renewal_conf_filest   RenewableCertt   True(   t   configt   renewal_file(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   update_live_symlinks   s    c         C   sò   t  j j t j ƒ } t |  d ƒ d } |  j } | sŒ | j d j | ƒ d d d t	 ƒ\ } } | t
 j k sw | rŒ t j d ƒ ‚ qŒ n  t |  | ƒ } | s¼ t j d j | ƒ ƒ ‚ n  t j | | |  ƒ | j d	 j | | ƒ d
 t ƒd S(   s¡   Rename the specified lineage to the new name.

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

    t   renamei    s&   Enter the new name for certificate {0}t   flags   --updated-cert-namet   force_interactives   User ended interaction.s,   No existing certificate with name {0} found.s    Successfully renamed {0} to {1}.t   pauseN(   t   zopet	   componentt
   getUtilityR   t   IDisplayt   get_certnamest   new_certnamet   inputt   formatR   t   display_utilt   OKR   t   Errort   lineage_for_certnamet   ConfigurationErrorR   t   rename_renewal_configt   notificationt   False(   R   t   dispt   certnameR   t   codet   lineage(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   rename_lineage)   s     	c         C   s¶   g  } g  } x“ t  j |  ƒ D]‚ } y0 t  j | |  ƒ } t j | ƒ | j | ƒ Wq t k
 r } t j d | | ƒ t j	 d t
 j ƒ  ƒ | j | ƒ q Xq Wt |  | | ƒ d S(   sª   Display information about certs configured with Certbot

    :param config: Configuration.
    :type config: :class:`certbot._internal.configuration.NamespaceConfig`
    sI   Renewal configuration file %s produced an unexpected error: %s. Skipping.s   Traceback was:
%sN(   R   R	   R
   R   t   verify_renewable_certt   appendt	   Exceptiont   loggert   warningt   debugt	   tracebackt
   format_exct   _describe_certs(   R   t   parsed_certst   parse_failuresR   t   renewal_candidatet   e(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   certificatesE   s    	
c         C   sÌ   t  |  d d t ƒ} t j j t j ƒ } d g } x | D] } | j d | ƒ q: W| j d ƒ | j d j	 | ƒ d t ƒs‘ t
 j d ƒ d	 Sx4 | D], } t j |  | ƒ t j d
 j | ƒ ƒ q˜ Wd	 S(   s;   Delete Certbot files associated with a certificate lineage.t   deletet   allow_multiples8   The following certificate(s) are selected for deletion:
s     * s:   
Are you sure you want to delete the above certificate(s)?s   
t   defaults$   Deletion of certificate(s) canceled.Ns.   Deleted all files relating to certificate {0}.(   R   R   R   R   R   R   R   R)   t   yesnot   joinR+   t   infoR   t   delete_filesR   t   notifyR   (   R   t	   certnamesR#   t   msgR$   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyR6   \   s    	c         C   s¦   |  j  } t j | d d ƒy t j |  | ƒ } Wn t j k
 rI d SXy t j | |  ƒ SWnA t j t	 f k
 r¡ t
 j d | ƒ t
 j d t j ƒ  ƒ d SXd S(   s)   Find a lineage object with name certname.t   modeií  s   Renewal conf file %s is broken.s   Traceback was:
%sN(   t   renewal_configs_dirR   t   make_or_verify_dirR   t   renewal_file_for_certnameR   t   CertStorageErrort   NoneR
   t   IOErrorR+   R-   R.   R/   (   t
   cli_configR$   t   configs_dirR   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyR   p   s    	c         C   s#   t  |  | ƒ } | r | j ƒ  Sd S(   s0   Find the domains in the cert with name certname.N(   R   t   namesRE   (   R   R$   R&   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   domains_for_certname   s    c            s   ‡  f d †  } t  |  | d ƒ S(   sˆ  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._internal.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 |  } nT | j t  ˆ  ƒ ƒ r | d k rc |  } q t | ƒ t | j ƒ  ƒ k r |  } q n  | | f S(   ss   Return cert as identical_names_cert if it matches,
           or subset_names_cert if it matches as subset
        N(   t   setRI   t   issubsetRE   t   len(   t   candidate_lineaget   rvt   identical_names_certt   subset_names_certt   candidate_names(   t   domains(    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   update_certs_for_domain_matchesž   s    		N(   NN(   t   _search_lineagesRE   (   R   RS   RT   (    (   RS   sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   find_duplicative_certs‡   s    c         C   sc   |  j  } g  t j | ƒ D]6 } t j d j | ƒ | ƒ r t j j | | ƒ ^ q } | r_ | Sd S(   sJ   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
    s   {0}[0-9]*.pemN(	   t   archive_dirR   t   listdirt   ret   matchR   t   pathR:   RE   (   RN   t   filetypeRW   t   ft   pattern(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   _archive_files´   s    	6c           C   s   d „  d „  d „  d „  g S(   sª    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(   t   fullchain_path(   t   x(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   <lambda>Ñ   s    c         S   s   |  j  S(   N(   t	   cert_path(   Ra   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRb   Ñ   s    c         S   s   t  |  d ƒ S(   Nt   cert(   R_   (   Ra   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRb   Ò   s    c         S   s   t  |  d ƒ S(   Nt	   fullchain(   R_   (   Ra   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRb   Ò   s    (    (    (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   _acceptable_matchesÊ   s    c            s2   t  ƒ  } t ˆ  | ‡  f d †  d „  ƒ } | d S(   s“   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(   Ni    (   Rc   (   Ra   (   RG   (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRb   â   s    c         S   s   |  j  S(   N(   t   lineagename(   Ra   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRb   â   s    i    (   Rf   t   match_and_check_overlaps(   RG   t   acceptable_matchesRZ   (    (   RG   sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   cert_path_to_lineageÕ   s    		c            st   ‡  ‡ f d †  } t  |  | g  | ƒ } | sO t j d j |  j d ƒ ƒ ‚ n! t | ƒ d k rp t j ƒ  ‚ n  | S(   s   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‘   g  | D] } | |  ƒ ^ q } g  } x7 | D]/ } t  | t ƒ rN | | 7} q, | j | ƒ q, Wˆ  |  ƒ } | | k r | j ˆ |  ƒ ƒ n  | S(   s1   Returns a list of matches using _search_lineages.(   t
   isinstancet   listR)   (   RN   t   return_valueRi   t   funct   acceptable_matches_rvt   itemRZ   (   t
   match_funct   rv_func(    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   find_matchesñ   s    s!   No match found for cert-path {0}!i    i   (   RU   R   R   R   Rc   RM   t   OverlappingMatchFound(   RG   Ri   Rq   Rr   Rs   t   matched(    (   Rq   Rr   sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRh   æ   s    "c         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 ƒ n  | j | k r½ | j d ƒ n | j | ƒ rÜ | j d ƒ n  | 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 | ƒ }	 t t j | j ƒ d ƒ }
 | j d j | j |
 | j d j | j ƒ  ƒ |	 | j | j ƒ ƒ d j | ƒ S(   sJ    Returns a human readable description of info about a RenewableCert objectt    t	   TEST_CERTt   EXPIREDt   REVOKEDs	   INVALID: s   , i   s   VALID: 1 days   VALID: {0} hour(s)i  s   VALID: {0} dayss	   {0} ({1})Ra   s“     Certificate Name: {}
    Serial Number: {}
    Key Type: {}
    Domains: {}
    Expiry Date: {}
    Certificate Path: {}
    Private Key Path: {}t    (   R   t   RevocationCheckerR$   Rg   RS   RK   RL   RI   t   pytzt   UTCt   fromutct   datetimet   utcnowt   is_test_certR)   t   target_expiryt   ocsp_revokedR:   t   daysR   t   secondsR   t   get_serial_from_certRc   t   private_key_typeRe   t   privkey(   R   Rd   t   skip_filter_checkst   certinfot   checkert   nowt   reasonst   statust   difft   valid_stringt   serial(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   human_readable_cert_info  sB    "(		c         C   st  |  j  } | r | g } nUt j j t j ƒ } t j |  ƒ } g  | D] } t j | ƒ ^ qF }	 |	 sy t	 j
 d ƒ ‚ n  | rå | s— d j | ƒ }
 n | }
 | j |
 |	 d d d t ƒ\ } } | t j k rpt	 j
 d ƒ ‚ qpn‹ | sý d j | ƒ }
 n | }
 | j |
 |	 d d d t ƒ\ } } | t j k sQ| t d t |	 ƒ ƒ k rct	 j
 d ƒ ‚ n  |	 | g } | S(	   s9   Get certname from flag, interactively, or error out.
    s   No existing certificates found.s+   Which certificate(s) would you like to {0}?t   cli_flags   --cert-nameR   s   User ended interaction.s(   Which certificate would you like to {0}?i    (   R$   R   R   R   R   R   R   R	   t   lineagename_for_filenameR   R   R   t	   checklistR   R   R   t   menut   rangeRM   (   R   t   verbR7   t   custom_promptR$   R>   R#   t	   filenamest   namet   choicest   promptR%   t   index(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyR   8  s2    	"*c         C   s   d d j  d „  |  Dƒ ƒ S(   sF   Format a results report for a category of single-line renewal outcomess     s   
  c         s   s   |  ] } t  | ƒ Vq d  S(   N(   t   str(   t   .0R?   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pys	   <genexpr>b  s    (   R:   (   t   msgs(    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   _report_lines`  s    c         C   s:   g  } x$ | D] } | j  t |  | ƒ ƒ q Wd j | ƒ S(   s)   Format a results report for a parsed certs   
(   R)   R’   R:   (   R   R1   RŠ   Rd   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   _report_human_readablee  s    c         C   sÕ   g  } | j  } | r* | r* | d ƒ np | rw |  j sB |  j rH d n d } | d j | ƒ ƒ | t |  | ƒ ƒ n  | rš | d ƒ | t | ƒ ƒ n  t j j t	 j
 ƒ } | j d j | ƒ d t d t ƒd	 S(
   s/   Print information about the certs we know abouts   No certificates found.s	   matching Rv   s   Found the following {0}certs:s3   
The following renewal configurations were invalid:s   
R   t   wrapN(   R)   R$   RS   R   R£   R¢   R   R   R   R   R   R!   R:   R"   (   R   R1   R2   t   outR=   RZ   R#   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyR0   m  s    	
c         G   s®   |  j  } t j | d d ƒ| } x… t j |  ƒ D]t } y t j | |  ƒ } WnC t j t f k
 r“ t	 j
 d | ƒ t	 j
 d t j ƒ  ƒ q2 n X| | | | Œ } q2 W| S(   sâ  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.
    R@   ií  s)   Renewal conf file %s is broken. Skipping.s   Traceback was:
%s(   RA   R   RB   R   R	   R
   R   RD   RF   R+   R-   R.   R/   (   RG   Rn   t
   initial_rvt   argsRH   RO   R   RN   (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyRU   ƒ  s    	(,   t   __doc__R   t   loggingRY   R.   R|   t   zope.componentR   t   acme.magic_typingR    t   certbotR   R   R   R   R   t   certbot._internalR   t   certbot.compatR   t   certbot.displayR   t	   getLoggert   __name__R+   R   R'   R5   R6   R   RJ   RV   R_   Rf   Rj   Rh   R"   R’   RE   R   R¢   R£   R0   RU   (    (    (    sB   /usr/lib/python2.7/site-packages/certbot/_internal/cert_manager.pyt   <module>   sB   							-				!1(			