U
    ÔZjÀ  ã                   @   s”  d Z ddlm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ZddlmZ ddlmZ ddl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 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Z%dZ&dZ'dZ(dZ)e *e+¡Z,ej- .ej/ej0¡ej- 1ej2¡G dd„ dej3ƒƒƒZ4dd„ Z5dd„ Z6dd„ Z7dd„ Z8dS ) zNginx Configurationé    )ÚLooseVersionN)Ú
challenges)Úcrypto_util)ÚListÚDictÚSet)Ú	constants)Úerrors)Ú
interfaces)Úutil)Úos)Úcommon)Údisplay_ops)Úhttp_01)Únginxparser)Úobj)Úparseré   é   é   é   c                       sö  e Zd ZdZdZdZdddgZedd„ ƒZe	d	d
„ ƒZ
‡ fdd„Ze	dd„ ƒZe	dd„ ƒZe	dd„ ƒZdd„ Zdd„ Zdrdd„Zdd„ Zdsdd„Zdd„ Zdtd!d"„Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zdud3d4„Zd5d6„ Zd7d8„ Z d9d:„ Z!d;d<„ Z"d=d>„ Z#d?d@„ Z$dAdB„ Z%dvdCdD„Z&dEdF„ Z'dGdH„ Z(dIdJ„ Z)dwdKdL„Z*dMdN„ Z+dOdP„ Z,dQdR„ Z-dSdT„ Z.dUdV„ Z/dWdX„ Z0dYdZ„ Z1d[d\„ Z2d]d^„ Z3d_d`„ Z4dadb„ Z5dxdcdd„Z6‡ fdedf„Z7dgdh„ Z8dy‡ fdjdk„	Z9dldm„ Z:dndo„ Z;dpdq„ Z<‡  Z=S )zÚNginxConfiguratora:  Nginx configurator.

    .. todo:: Add proper support for comments in the config. Currently,
        config files modified by the configurator will lose all their comments.

    :ivar config: Configuration.
    :type config: :class:`~certbot.interfaces.IConfig`

    :ivar parser: Handles low level parsing
    :type parser: :class:`~certbot_nginx.parser`

    :ivar str save_notes: Human-readable config change notes

    :ivar reverter: saves and reverts checkpoints
    :type reverter: :class:`certbot.reverter.Reverter`

    :ivar tup version: version of Nginx

    zNginx Web Server pluginÚ80Ússl_certificateÚssl_certificate_keyÚssl_dhparamc                 C   s6   t ƒ }|dtjd d| d� |dtjd dd� d S )Núserver-rootÚserver_rootz*Nginx server root directory. (default: %s))ÚdefaultÚhelpÚctlzVPath to the 'nginx' binary, used for 'configtest' and retrieving nginx version number.)Ú_determine_default_server_rootr   ÚCLI_DEFAULTS)ÚclsÚaddÚdefault_server_root© r&   ú]/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/certbot_nginx/configurator.pyÚadd_parser_argumentsL   s
    ÿz&NginxConfigurator.add_parser_argumentsc                 C   s   t j |  d¡d¡S )zNginx config file path.r   z
nginx.conf)r   ÚpathÚjoinÚconf©Úselfr&   r&   r'   Ú
nginx_confU   s    zNginxConfigurator.nginx_confc                    s„   |  dd¡}|  dd¡}tt| ƒj||Ž |  ¡  d| _d| _i | _i | _d| _	d| _
|| _|| _| j| j| jdœ| _| j ¡  dS )a  Initialize an Nginx Configurator.

        :param tup version: version of Nginx as a tuple (1, 4, 7)
            (used mostly for unittesting)

        :param tup openssl_version: version of OpenSSL linked to Nginx as a tuple (1, 4, 7)
            (used mostly for unittesting)

        ÚversionNÚopenssl_versionÚ r   )Úredirectúensure-http-headerústaple-ocsp)ÚpopÚsuperr   Ú__init__Ú_verify_setupÚ
save_notesÚ	new_vhostÚ_wildcard_vhostsÚ_wildcard_redirect_vhostsÚ
_chall_outr   r/   r0   Ú_enable_redirectÚ_set_http_headerÚ_enable_ocsp_staplingÚ_enhance_funcZreverterÚrecovery_routine)r-   ÚargsÚkwargsr/   r0   ©Ú	__class__r&   r'   r7   Z   s"    
þzNginxConfigurator.__init__c                 C   sd   | j dk}| j dko*| jo*t| jƒtdƒk}|r@|r:d}qNd}n|rJd}nd}t dtj d	|¡¡S )
z4Full absolute path to SSL configuration file source.)r   é   r   )r   é   é	   z1.0.2lzoptions-ssl-nginx.confz+options-ssl-nginx-tls13-session-tix-on.confz!options-ssl-nginx-tls12-only.confzoptions-ssl-nginx-old.confÚcertbot_nginxZtls_configs)r/   r0   r   Úpkg_resourcesÚresource_filenamer   r)   r*   )r-   Z	use_tls13Zsession_tix_offZconfig_filenamer&   r&   r'   Úmod_ssl_conf_srcƒ   s    
ÿ ÿz"NginxConfigurator.mod_ssl_conf_srcc                 C   s   t j | jjtj¡S )z-Full absolute path to SSL configuration file.)r   r)   r*   ÚconfigÚ
config_dirr   ZMOD_SSL_CONF_DESTr,   r&   r&   r'   Úmod_ssl_conf¤   s    zNginxConfigurator.mod_ssl_confc                 C   s   t j | jjtj¡S )z?Full absolute path to digest of updated SSL configuration file.)r   r)   r*   rN   rO   r   ZUPDATED_MOD_SSL_CONF_DIGESTr,   r&   r&   r'   Úupdated_mod_ssl_conf_digest©   s    z-NginxConfigurator.updated_mod_ssl_conf_digestc                 C   s   t  ||| jtj¡S )zICopy Certbot's SSL options file into the system's config dir if required.)r   Zinstall_version_controlled_filerM   r   ZALL_SSL_OPTIONS_HASHES)r-   Zoptions_sslZoptions_ssl_digestr&   r&   r'   Úinstall_ssl_options_conf®   s     ÿz*NginxConfigurator.install_ssl_options_confc              
   C   sÌ   t  |  d¡¡st d¡‚|  ¡  t |  d¡¡| _| jdkrH|  	¡ | _| j
dkr\|  ¡ | _
|  | j| j¡ |  ¡  zt  |  d¡¡ W n> ttjfk
rÆ   tjddd� t d |  d¡¡¡‚Y nX dS )	zÁPrepare the authenticator/installer.

        :raises .errors.NoInstallationError: If Nginx ctl cannot be found
        :raises .errors.MisconfigurationError: If Nginx is misconfigured
        r    zvCould not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly.r   NzEncountered error:T©Úexc_infozUnable to lock {0})r   Z
exe_existsr+   r	   ZNoInstallationErrorÚconfig_testr   ZNginxParserr/   Úget_versionr0   Ú_get_openssl_versionrR   rP   rQ   Zinstall_ssl_dhparamsZlock_dir_until_exitÚOSErrorZ	LockErrorÚloggerÚdebugÚPluginErrorÚformatr,   r&   r&   r'   Úprepare´   s"    ÿ



zNginxConfigurator.prepareNc                 C   s<   |st  d¡‚| j|dd�}|D ]}|  |||||¡ q dS )aU  Deploys certificate to specified virtual host.

        .. note:: Aborts if the vhost is missing ssl_certificate or
            ssl_certificate_key.

        .. note:: This doesn't save the config files!

        :raises errors.PluginError: When unable to deploy certificate due to
            a lack of directives or configuration

        zGThe nginx plugin currently requires --fullchain-path to install a cert.T)Úcreate_if_no_matchN)r	   r[   Úchoose_vhostsÚ_deploy_cert)r-   ÚdomainÚ	cert_pathÚkey_pathÚ
chain_pathÚfullchain_pathÚvhostsÚvhostr&   r&   r'   Údeploy_certØ   s    ÿzNginxConfigurator.deploy_certc                 C   s†   ddd|gddd|gg}| j  ||¡ t d|j¡ |  jd|jd dd	„ |jD ƒ¡f 7  _|  jd
| 7  _|  jd| 7  _dS )a  
        Helper function for deploy_cert() that handles the actual deployment
        this exists because we might want to do multiple deployments per
        domain originally passed for deploy_cert(). This is especially true
        with wildcard certificates
        ú
    r   ú r   z'Deploying Certificate to VirtualHost %sz)Changed vhost at %s with addresses of %s
z, c                 s   s   | ]}t |ƒV  qd S ©N©Ústr©Ú.0Úaddrr&   r&   r'   Ú	<genexpr>þ   s     z1NginxConfigurator._deploy_cert.<locals>.<genexpr>z	ssl_certificate %s
z	ssl_certificate_key %s
N)r   Úupdate_or_add_server_directivesrY   ÚinfoÚfilepr9   r*   Úaddrs)r-   rg   rb   rc   rd   re   Zcert_directivesr&   r&   r'   r`   î   s    

ÿÿÿÿzNginxConfigurator._deploy_certc                 C   sÞ   |r| j }dd„ }n| j}dd„ }||kr2|| S | j ¡ }i }|D ]H}|dk	r^|  ||¡s^qD|jD ]&}	||ƒrz|||	< qd|	|krd|||	< qdqDtdd„ | ¡ D ƒƒ}
t 	t
|
ƒ¡}|D ]"}||krÊg ||< ||  |¡ q¶|S )zCPrompts user to choose vhosts to install a wildcard certificate forc                 S   s   | j S rk   ©Ússl©Úxr&   r&   r'   Ú<lambda>  ó    z;NginxConfigurator._choose_vhosts_wildcard.<locals>.<lambda>c                 S   s   | j  S rk   rv   rx   r&   r&   r'   rz   	  r{   Nc                 S   s   g | ]}|‘qS r&   r&   ©ro   rg   r&   r&   r'   Ú
<listcomp>$  s     z=NginxConfigurator._choose_vhosts_wildcard.<locals>.<listcomp>)r;   r<   r   Ú
get_vhostsÚ_vhost_listening_on_port_no_sslÚnamesÚsetÚvaluesr   Zselect_vhost_multipleÚlistÚappend)r-   ra   Ú
prefer_sslÚno_ssl_filter_portZvhosts_cacheZpreference_testrf   Zfiltered_vhostsrg   ÚnameZdialog_inputZreturn_vhostsr&   r&   r'   Ú_choose_vhosts_wildcard  s2    



z)NginxConfigurator._choose_vhosts_wildcardc                 C   s$   |   |¡}dd„ |  |¡fD ƒ}|S )Nc                 S   s   g | ]}|d k	r|‘qS rk   r&   ©ro   ry   r&   r&   r'   r}   5  s      z:NginxConfigurator._choose_vhost_single.<locals>.<listcomp>)Ú_get_ranked_matchesÚ_select_best_name_match)r-   Útarget_nameÚmatchesrf   r&   r&   r'   Ú_choose_vhost_single3  s    
z&NginxConfigurator._choose_vhost_singleFc                 C   sr   t  |¡r| j|dd�}n
|  |¡}|sT|rF|  |dt| jjƒ¡g}nt 	d| ¡‚|D ]}|j
sX|  |¡ qX|S )a@  Chooses a virtual host based on the given domain name.

        .. note:: This makes the vhost SSL-enabled if it isn't already. Follows
            Nginx's server block selection rules preferring blocks that are
            already SSL.

        .. todo:: This should maybe return list if no obvious answer
            is presented.

        .. todo:: The special name "$hostname" corresponds to the machine's
            hostname. Currently we just ignore this.

        :param str target_name: domain name
        :param bool create_if_no_match: If we should create a new vhost from default
            when there is no match found. If we can't choose a default, raise a
            MisconfigurationError.

        :returns: ssl vhosts associated with name
        :rtype: list of :class:`~certbot_nginx.obj.VirtualHost`

        T)r…   a	  Cannot find a VirtualHost matching domain %s. In order for Certbot to correctly perform the challenge please add a corresponding server_name directive to your nginx configuration for every domain on your certificate: https://nginx.org/en/docs/http/server_names.html)r   Úis_wildcard_domainrˆ   rŽ   Ú_vhost_from_duplicated_defaultrm   rN   Ú
https_portr	   ÚMisconfigurationErrorrw   Ú_make_server_ssl)r-   rŒ   r^   rf   rg   r&   r&   r'   r_   8  s"    


ÿüÿzNginxConfigurator.choose_vhostsc                 C   sX   t |ƒ}| j ¡ }d}d}|D ]0}|jD ]$}|jr6d}|jr(| ¡ |kr(d}q(q||fS )a,  Returns tuple of booleans (ipv6_active, ipv6only_present)
        ipv6_active is true if any server block listens ipv6 address in any port

        ipv6only_present is true if ipv6only=on option exists in any server
        block ipv6 listen directive for the specified port.

        :param str port: Port to check ipv6only=on directive for

        :returns: Tuple containing information if IPv6 is enabled in the global
            configuration, and existence of ipv6only directive for specified port
        :rtype: tuple of type (bool, bool)
        FT)rm   r   r~   ru   Úipv6Zipv6onlyÚget_port)r-   Úportrf   Zipv6_activeZipv6only_presentZvhrp   r&   r&   r'   Ú	ipv6_infog  s    

zNginxConfigurator.ipv6_infoc                 C   sH   | j dkr4|  |||¡}| jj|dd�| _ tƒ | j _|  | j |¡ | j S )zŒif allow_port_mismatch is False, only server blocks with matching ports will be
           used as a default server block template.
        NT)Zremove_singleton_listen_params)r:   Ú_get_default_vhostr   Úduplicate_vhostr�   r€   Ú_add_server_name_to_vhost)r-   ra   Úallow_port_mismatchr–   Zdefault_vhostr&   r&   r'   r�   ‚  s    
ÿ
z0NginxConfigurator._vhost_from_duplicated_defaultc                 C   sP   |j  |¡ ddgg}|j D ] }|d  d¡ |d  |¡ q| j ||¡ d S )Nri   Úserver_namer   rj   )r€   r$   r„   r   rr   )r-   rg   ra   Z
name_blockr‡   r&   r&   r'   rš   �  s    

z+NginxConfigurator._add_server_name_to_vhostc           	      C   s”   | j  ¡ }g }g }|D ]>}|jD ]2}|jr | |¡ |  || ¡ ¡rN| |¡  qq qt|ƒdkrj|d S t|ƒdkr‚|r‚|d S t 	d| ¡‚dS )zRHelper method for _vhost_from_duplicated_default; see argument documentation therer   r   zxCould not automatically find a matching server block for %s. Set the `server_name` directive to use the Nginx installer.N)
r   r~   ru   r   r„   Ú_port_matchesr•   Úlenr	   r’   )	r-   ra   r›   r–   Ú
vhost_listZall_default_vhostsZport_matching_vhostsrg   rp   r&   r&   r'   r˜   —  s"    



ÿz$NginxConfigurator._get_default_vhostc                 C   s   | j  ¡ }|  ||¡S )a)  Returns a ranked list of vhosts that match target_name.
        The ranking gives preference to SSL vhosts.

        :param str target_name: The name to match
        :returns: list of dicts containing the vhost, the matching name, and
            the numerical rank
        :rtype: list

        )r   r~   Ú_rank_matches_by_name_and_ssl)r-   rŒ   rŸ   r&   r&   r'   rŠ   ¯  s    

z%NginxConfigurator._get_ranked_matchesc                    sf   |sdS |d d t tt t tt fkrZ|d d ‰ ‡ fdd„|D ƒ}t|dd„ d�d	 S |d d	 S )
a  Returns the best name match of a ranked list of vhosts.

        :param list matches: list of dicts containing the vhost, the matching name,
            and the numerical rank
        :returns: the most matching vhost
        :rtype: :class:`~certbot_nginx.obj.VirtualHost`

        Nr   Úrankc                    s   g | ]}|d  ˆ kr|‘qS ©r¡   r&   r‰   r¢   r&   r'   r}   Ë  s      z=NginxConfigurator._select_best_name_match.<locals>.<listcomp>c                 S   s   t | d ƒS )Nr‡   )rž   rx   r&   r&   r'   rz   Ì  r{   z;NginxConfigurator._select_best_name_match.<locals>.<lambda>©Úkeyrg   )ÚSTART_WILDCARD_RANKÚEND_WILDCARD_RANKÚNO_SSL_MODIFIERÚmax)r-   r�   Ú	wildcardsr&   r¢   r'   r‹   ¼  s    	 ÿz)NginxConfigurator._select_best_name_matchc                 C   sž   g }|D ]„}t  ||j¡\}}|dkr:| ||tdœ¡ q|dkrV| ||tdœ¡ q|dkrr| ||tdœ¡ q|dkr| ||tdœ¡ qt|dd„ d�S )	a›  Returns a ranked list of vhosts from vhost_list that match target_name.
        This method should always be followed by a call to _select_best_name_match.

        :param list vhost_list: list of vhosts to filter and rank
        :param str target_name: The name to match
        :returns: list of dicts containing the vhost, the matching name, and
            the numerical rank
        :rtype: list

        Úexact)rg   r‡   r¡   Zwildcard_startZwildcard_endÚregexc                 S   s   | d S ©Nr¡   r&   rx   r&   r&   r'   rz   ó  r{   z9NginxConfigurator._rank_matches_by_name.<locals>.<lambda>r£   )	r   Zget_best_matchr€   r„   Ú	NAME_RANKr¥   r¦   Ú
REGEX_RANKÚsorted)r-   rŸ   rŒ   r�   rg   Z	name_typer‡   r&   r&   r'   Ú_rank_matches_by_nameÐ  s0    þ
þ
þ
þ
z'NginxConfigurator._rank_matches_by_namec                 C   s@   |   ||¡}|D ]}|d js|d  t7  < qt|dd„ d�S )a“  Returns a ranked list of vhosts from vhost_list that match target_name.
        The ranking gives preference to SSLishness before name match level.

        :param list vhost_list: list of vhosts to filter and rank
        :param str target_name: The name to match
        :returns: list of dicts containing the vhost, the matching name, and
            the numerical rank
        :rtype: list

        rg   r¡   c                 S   s   | d S r¬   r&   rx   r&   r&   r'   rz     r{   zANginxConfigurator._rank_matches_by_name_and_ssl.<locals>.<lambda>r£   )r°   rw   r§   r¯   )r-   rŸ   rŒ   r�   Úmatchr&   r&   r'   r    õ  s
    
z/NginxConfigurator._rank_matches_by_name_and_sslc                 C   sZ   t  |¡r| j|d|d�}n"|  ||¡}dd„ |  |¡fD ƒ}|sV|rV|  |d|¡g}|S )a  Chooses a single virtual host for redirect enhancement.

        Chooses the vhost most closely matching target_name that is
        listening to port without using ssl.

        .. todo:: This should maybe return list if no obvious answer
            is presented.

        .. todo:: The special name "$hostname" corresponds to the machine's
            hostname. Currently we just ignore this.

        :param str target_name: domain name
        :param str port: port number
        :param bool create_if_no_match: If we should create a new vhost from default
            when there is no match found. If we can't choose a default, raise a
            MisconfigurationError.

        :returns: vhosts associated with name
        :rtype: list of :class:`~certbot_nginx.obj.VirtualHost`

        F)r…   r†   c                 S   s   g | ]}|d k	r|‘qS rk   r&   r‰   r&   r&   r'   r}   "  s      z<NginxConfigurator.choose_redirect_vhosts.<locals>.<listcomp>)r   r�   rˆ   Ú_get_redirect_ranked_matchesr‹   r�   )r-   rŒ   r–   r^   rf   r�   r&   r&   r'   Úchoose_redirect_vhosts  s    
ÿz(NginxConfigurator.choose_redirect_vhostsc                 C   s"   |dks|d kr|| j kS ||kS )Nr1   )ÚDEFAULT_LISTEN_PORT)r-   Z	test_portZmatching_portr&   r&   r'   r�   '  s    
zNginxConfigurator._port_matchesc                 C   sR   d}|j s|| jk}n&|j D ]}|  || ¡ ¡r|jsd}q|rN| j |¡ S dS )NFT)ru   r´   r�   r•   rw   r   Zhas_ssl_on_directive)r-   rg   r–   Zfound_matching_portrp   r&   r&   r'   r   .  s    
z1NginxConfigurator._vhost_listening_on_port_no_sslc                    s6   ˆj  ¡ }‡fdd„‰ ‡ ‡fdd„|D ƒ}ˆ ||¡S )a·  Gets a ranked list of plaintextish port-listening vhosts matching target_name

        Filter all hosts for those listening on port without using ssl.
        Rank by how well these match target_name.

        :param str target_name: The name to match
        :param str port: port number as a string
        :returns: list of dicts containing the vhost, the matching name, and
            the numerical rank
        :rtype: list

        c                    s   ˆ   | |¡S rk   )r   )rg   r–   r,   r&   r'   Ú_vhost_matchesM  s    zFNginxConfigurator._get_redirect_ranked_matches.<locals>._vhost_matchesc                    s   g | ]}ˆ |ˆƒr|‘qS r&   r&   r|   )rµ   r–   r&   r'   r}   P  s     
 zBNginxConfigurator._get_redirect_ranked_matches.<locals>.<listcomp>)r   r~   r°   )r-   rŒ   r–   Z
all_vhostsZmatching_vhostsr&   )rµ   r–   r-   r'   r²   >  s    
z.NginxConfigurator._get_redirect_ranked_matchesc                 C   sÎ   t ƒ }| j ¡ D ]²}| |j¡ |jD ]š}| ¡ }tj 	|¡rJ| 
|¡ q&tj 	|¡s&zD|jrv| ¡ }t tj|¡ nt tj|¡ | 
t |¡d ¡ W q& tjtjtjfk
r¾   Y q&Y q&X q&qt |¡S )zÉReturns all names found in the Nginx Configuration.

        :returns: All ServerNames, ServerAliases, and reverse DNS entries for
                  virtual host addresses
        :rtype: set

        r   )r�   r   r~   Úupdater€   ru   Zget_addrr   Zhostname_regexr±   r$   Zprivate_ips_regexr”   Zget_ipv6_explodedÚsocketÚ	inet_ptonÚAF_INET6ÚAF_INETÚgethostbyaddrÚerrorÚherrorÚtimeoutr   Zget_filtered_names)r-   Z	all_namesrg   rp   Úhostr&   r&   r'   Úget_all_namesT  s"    
zNginxConfigurator.get_all_namesc              	   C   sœ   t j | jjd¡}tjd|dd�}tj 	tjj
|j¡}tj|t ¡ gd�}tj tjj
|¡}tjt j |d¡dd�\}}|� | |¡ W 5 Q R X ||jfS )	zBGenerate invalid certs that let us create ssl directives for NginxZsnakeoili   zkey.pem)Zkey_sizeZkey_dirZkeyname)Údomainszcert.pemÚwb)Úmode)r   r)   r*   rN   Úwork_dirr   Zinit_save_keyÚOpenSSLZcryptoZload_privatekeyZFILETYPE_PEMÚpemÚacme_crypto_utilZgen_ss_certr·   ÚgethostnameZdump_certificater   Zunique_fileÚwriteÚfile)r-   Ztmp_dirZle_keyr¤   ÚcertZcert_pemÚ	cert_filerb   r&   r&   r'   Ú_get_snakeoil_pathst  s,      ÿ ÿ ÿ ÿ
z%NginxConfigurator._get_snakeoil_pathsc           
   	   C   sì   | j j}|  |¡}dg}dg}|jsBddd| jgg}| j ||¡ | ¡ r|dddd |¡ddg}|d s|| 	d¡ | 	d¡ | 
¡ ršdddd	 |¡ddg}|  ¡ \}}||dd
d|gddd|gddd| jgddd| jgg}	| j ||	¡ dS )zÍMake a server SSL.

        Make a server SSL by adding new listen and SSL directives.

        :param vhost: The vhost to add SSL to.
        :type vhost: :class:`~certbot_nginx.obj.VirtualHost`

        r1   ri   Úlistenrj   z[::]:{0}rw   r   zipv6only=onz{0}r   r   Úincluder   N)rN   r‘   r—   ru   r´   r   Úadd_server_directivesZipv6_enabledr\   r„   Zipv4_enabledrÍ   rP   Zssl_dhparams)
r-   rg   r‘   Zipv6infoZ
ipv6_blockZ
ipv4_blockZlisten_blockZsnakeoil_certZsnakeoil_keyZ	ssl_blockr&   r&   r'   r“   …  sL    	
û

û

ú	 ÿz"NginxConfigurator._make_server_sslc                 C   s
   dddgS )z)Returns currently supported enhancements.r2   r3   r4   r&   r,   r&   r&   r'   Úsupported_enhancements¾  s    z(NginxConfigurator.supported_enhancementsc              	   C   sd   z| j | ||ƒW S  ttfk
r:   t d |¡¡‚Y n& tjk
r^   t d||¡ ‚ Y nX dS )aa  Enhance configuration.

        :param str domain: domain to enhance
        :param str enhancement: enhancement type defined in
            :const:`~certbot.constants.ENHANCEMENTS`
        :param options: options for the enhancement
            See :const:`~certbot.constants.ENHANCEMENTS`
            documentation for appropriate parameter.

        zUnsupported enhancement: {0}zFailed %s for %sN)rA   ÚKeyErrorÚ
ValueErrorr	   r[   r\   rY   Úwarning)r-   ra   ZenhancementÚoptionsr&   r&   r'   ÚenhanceÂ  s    ÿzNginxConfigurator.enhancec                 C   s   t t|ƒƒ}| |¡S rk   )Ú_test_block_from_blockÚ_redirect_block_for_domainZcontains_list)r-   rg   ra   Ztest_redirect_blockr&   r&   r'   Ú_has_certbot_redirectÖ  s    z'NginxConfigurator._has_certbot_redirectc                 C   s’   |   |¡}|st d¡‚|D ]p}| |¡r8t d| ¡‚|jr`tdd„ |jD ƒƒr`|  |¡\}}ddd|dgt	j
|  dgg}| j ||¡ qd	S )
ab  Enables header identified by header_substring on domain.

        If the vhost is listening plaintextishly, separates out the relevant
        directives into a new server block, and only add header directive to
        HTTPS block.

        :param str domain: the domain to enable header for.
        :param str header_substring: String to uniquely identify a header.
                        e.g. Strict-Transport-Security, Upgrade-Insecure-Requests
        :returns: Success
        :raises .errors.PluginError: If no viable HTTPS host can be created or
            set with header header_substring.
        z8Unable to find corresponding HTTPS host for enhancement.zExisting %s headerc                 S   s   g | ]}|j  ‘qS r&   rv   rn   r&   r&   r'   r}   ó  s     z6NginxConfigurator._set_http_header.<locals>.<listcomp>ri   Ú
add_headerrj   Ú
N)r_   r	   r[   Ú
has_headerZPluginEnhancementAlreadyPresentrw   Úanyru   Ú_split_blockr   ZHEADER_ARGSr   rÐ   )r-   ra   Zheader_substringrf   rg   Ú_Zheader_directivesr&   r&   r'   r?   Ú  s$    
ÿ
ÿÿýz"NginxConfigurator._set_http_headerc                 C   s   t |ƒ}| jj||dd� dS )z(Add redirect directive to vhost
        T)Zinsert_at_topN)rØ   r   rÐ   )r-   rg   ra   Úredirect_blockr&   r&   r'   Ú_add_redirect_blockü  s      ÿz%NginxConfigurator._add_redirect_blockc                    s„   ˆ j j||d�}dd„ }‡ fdd„}dd„ }ˆ jD ]}ˆ j  ||¡ q2ˆ j j|d|d	� ˆ j j|d
|d	� ˆ j j|d|d	� ||fS )aÝ  Splits this "virtual host" (i.e. this nginx server block) into
        separate HTTP and HTTPS blocks.

        :param vhost: The server block to break up into two.
        :param list only_directives: If this exists, only duplicate these directives
            when splitting the block.
        :type vhost: :class:`~certbot_nginx.obj.VirtualHost`
        :returns: tuple (http_vhost, https_vhost)
        :rtype: tuple of type :class:`~certbot_nginx.obj.VirtualHost`
        )Úonly_directivesc                 S   s   d| kS ©Nrw   r&   ©Ú	directiver&   r&   r'   Ú_ssl_match_func  s    z7NginxConfigurator._split_block.<locals>._ssl_match_funcc                    s
   ˆ j | kS rk   )rP   rä   r,   r&   r'   Ú_ssl_config_match_func  s    z>NginxConfigurator._split_block.<locals>._ssl_config_match_funcc                 S   s   d| kS rã   r&   rä   r&   r&   r'   Ú_no_ssl_match_func  s    z:NginxConfigurator._split_block.<locals>._no_ssl_match_funcrÎ   )Ú
match_funcrÏ   )r   r™   ÚSSL_DIRECTIVESZremove_server_directives)r-   rg   râ   Ú
http_vhostræ   rç   rè   rå   r&   r,   r'   rÞ     s    

ÿzNginxConfigurator._split_blockc                 C   sB   | j }|  ||¡}|s(t d| j ¡ dS |D ]}|  ||¡ q,dS )a¡  Redirect all equivalent HTTP traffic to ssl_vhost.

        If the vhost is listening plaintextishly, separate out the
        relevant directives into a new server block and add a rewrite directive.

        .. note:: This function saves the configuration

        :param str domain: domain to enable redirect for
        :param unused_options: Not currently used
        :type unused_options: Not Available
        z>No matching insecure server blocks listening on port %s found.N)r´   r³   rY   rs   Ú_enable_redirect_single)r-   ra   Zunused_optionsr–   rf   rg   r&   r&   r'   r>   %  s    ÿz"NginxConfigurator._enable_redirectc                 C   s|   |j r:|  |ddg¡\}}ddddgg}| j ||¡ |}|  ||¡rZt d| j|j¡ n|  	||¡ t d| j|j¡ d	S )
aƒ  Redirect all equivalent HTTP traffic to ssl_vhost.

        If the vhost is listening plaintextishly, separate out the
        relevant directives into a new server block and add a rewrite directive.

        .. note:: This function saves the configuration

        :param str domain: domain to enable redirect for
        :param `~obj.Vhost` vhost: vhost to enable redirect for
        rÎ   rœ   ri   Úreturnrj   Z404z3Traffic on port %s already redirecting to ssl in %sz/Redirecting all traffic on port %s to ssl in %sN)
rw   rÞ   r   rÐ   rÙ   rY   rs   r´   rt   rá   )r-   ra   rg   rë   rß   Zreturn_404_directiver&   r&   r'   rì   @  s     ÿ ÿz)NginxConfigurator._enable_redirect_singlec                 C   s$   |   |¡}|D ]}|  ||¡ qdS )zÄInclude OCSP response in TLS handshake

        :param str domain: domain to enable OCSP response for
        :param chain_path: chain file path
        :type chain_path: `str` or `None`

        N)r_   Ú_enable_ocsp_stapling_single)r-   ra   rd   rf   rg   r&   r&   r'   r@   ]  s    
z'NginxConfigurator._enable_ocsp_staplingc              
   C   sî   | j dk rt d¡‚|dkr&t d¡‚ddd|gdddd	gdd
dd	gdgg}z| j ||¡ W nD tjk
r¢ } z$t t|ƒ¡ t d 	|j
¡¡‚W 5 d}~X Y nX |  jd 	|j¡7  _|  jd 	|¡7  _|  jd7  _|  jd7  _dS )zÂInclude OCSP response in TLS handshake

        :param str vhost: vhost to enable OCSP response for
        :param chain_path: chain file path
        :type chain_path: `str` or `None`

        )r   r   é   zCVersion 1.3.7 or greater of nginx is needed to enable OCSP staplingNzh--chain-path is required to enable Online Certificate Status Protocol (OCSP) stapling on nginx >= 1.3.7.ri   Zssl_trusted_certificaterj   Zssl_staplingÚonZssl_stapling_verifyrÛ   z7An error occurred while enabling OCSP stapling for {0}.z-OCSP Stapling was enabled on SSL Vhost: {0}.
z	ssl_trusted_certificate {0}
z	ssl_stapling on
z	ssl_stapling_verify on
)r/   r	   r[   r   rÐ   r’   rY   rZ   rm   r\   r€   r9   rt   )r-   rg   rd   Zstapling_directivesr¼   r&   r&   r'   rî   i  s4    

ÿ


 ýÿÿ
ÿz.NginxConfigurator._enable_ocsp_stapling_singlec                 C   s   t |  d¡| jƒ dS )zlRestarts nginx server.

        :raises .errors.MisconfigurationError: If either the reload fails.

        r    N)Únginx_restartr+   r.   r,   r&   r&   r'   Úrestart‘  s    zNginxConfigurator.restartc              
   C   sV   zt  |  d¡d| jdg¡ W n2 tjk
rP } zt t|ƒ¡‚W 5 d}~X Y nX dS )z{Check the configuration of Nginx for errors.

        :raises .errors.MisconfigurationError: If config_test fails

        r    ú-cz-tN)r   Ú
run_scriptr+   r.   r	   ÚSubprocessErrorr’   rm   )r-   Úerrr&   r&   r'   rU   ™  s    zNginxConfigurator.config_testc                 C   s:   t  | jjtj¡ t  | jjtj¡ t  | jjtj¡ dS )zñVerify the setup to ensure safe operating environment.

        Make sure that files/directories are setup with appropriate permissions
        Aim for defensive coding... make sure all input files
        have permissions of root.

        N)r   Zmake_or_verify_dirrN   rÄ   Úcore_constantsZCONFIG_DIRS_MODEÚ
backup_dirrO   r,   r&   r&   r'   r8   ¤  s    zNginxConfigurator._verify_setupc              
   C   sˆ   z6t j|  d¡d| jdgt jt jdd�}| ¡ d }W nL ttfk
r‚ } z*tj	t
|ƒdd� t d|  d¡ ¡‚W 5 d	}~X Y nX |S )
z¦Return results of nginx -V

        :returns: version text
        :rtype: str

        :raises .PluginError:
            Unable to run Nginx version command
        r    ró   z-VT)ÚstdoutÚstderrÚuniversal_newlinesr   rS   zUnable to run %s -VN)Ú
subprocessÚPopenr+   r.   ÚPIPEÚcommunicaterX   rÓ   rY   rZ   rm   r	   r[   )r-   ÚprocÚtextr¼   r&   r&   r'   Ú_nginx_version°  s    	üÿz NginxConfigurator._nginx_versionc                 C   sÄ   |   ¡ }t dtj¡}| |¡}t dtj¡}| |¡}t d¡}| |¡}|sZt d¡‚|sht d¡‚|svt d¡‚|d \}}	|dkr–t d	|¡ t	d
d„ |	 
d¡D ƒƒ}
|
dk rÀt d¡‚|
S )zûReturn version of Nginx Server.

        Version is returned as tuple. (ie. 2.4.7 = (2, 4, 7))

        :returns: version
        :rtype: tuple

        :raises .PluginError:
            Unable to find Nginx version or version is unsupported

        z!nginx version: ([^/]+)/([0-9\.]*)zTLS SNI support enabledz --with-http_ssl_modulezUnable to find Nginx versionz;Nginx build is missing SSL module (--with-http_ssl_module).zNginx build doesn't support SNIr   Únginxz:NGINX derivative %s is not officially supported by certbotc                 S   s   g | ]}t |ƒ‘qS r&   )Úint©ro   Úir&   r&   r'   r}   ê  s     z1NginxConfigurator.get_version.<locals>.<listcomp>Ú.)r   é   é0   zNginx version must be 0.8.48+)r  ÚreÚcompileÚ
IGNORECASEÚfindallr	   r[   rY   rÔ   ÚtupleÚsplitZNotSupportedError)r-   r  Úversion_regexZversion_matchesZ	sni_regexZsni_matchesZ	ssl_regexZssl_matchesZproduct_nameZproduct_versionZnginx_versionr&   r&   r'   rV   Æ  s0    




ÿ
ÿ
zNginxConfigurator.get_versionc                 C   s>   |   ¡ }t d|¡}|s6t d|¡}|s6t d¡ dS |d S )a  Return version of OpenSSL linked to Nginx.

        Version is returned as string. If no version can be found, empty string is returned.

        :returns: openssl_version
        :rtype: str

        :raises .PluginError:
            Unable to run Nginx version command
        zrunning with OpenSSL ([^ ]+) zbuilt with OpenSSL ([^ ]+) zQNGINX configured with OpenSSL alternatives is not officiallysupported by Certbot.r1   r   )r  r
  r  rY   rÔ   )r-   r  r�   r&   r&   r'   rW   ó  s    
z&NginxConfigurator._get_openssl_versionc                 C   s(   dj tj| jjd dd„ | jD ƒ¡d�S )z3Human-readable string to help understand the modulez^Configures Nginx to authenticate and install HTTPS.{0}Server root: {root}{0}Version: {version}r  c                 s   s   | ]}t |ƒV  qd S rk   rl   r  r&   r&   r'   rq     s     z.NginxConfigurator.more_info.<locals>.<genexpr>)Úrootr/   )r\   r   Úlinesepr   Zconfig_rootr*   r/   r,   r&   r&   r'   Ú	more_info	  s     üÿzNginxConfigurator.more_infoc                 C   sJ   t | jj ¡ ƒ}|  || j|¡ d| _| jjdd� |rF|sF|  |¡ dS )a  Saves all changes to the configuration files.

        :param str title: The title of the save. If a title is given, the
            configuration will be saved as a new checkpoint and put in a
            timestamped directory.

        :param bool temporary: Indicates whether the changes made will
            be quickly reversed in the future (ie. challenges)

        :raises .errors.PluginError: If there was an error in
            an attempt to save the configuration, or an error creating a
            checkpoint

        r1   )ÚextN)r�   r   ÚparsedÚkeysZadd_to_checkpointr9   ZfiledumpZfinalize_checkpoint)r-   ÚtitleÚ	temporaryZ
save_filesr&   r&   r'   Úsave  s    zNginxConfigurator.savec                    s"   t t| ƒ ¡  d| _| j ¡  dS )zÉRevert 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)r6   r   rB   r:   r   Úloadr,   rE   r&   r'   rB   .  s    z"NginxConfigurator.recovery_routinec                 C   s   |   ¡  d| _| j ¡  dS )zƒUsed to cleanup challenge configurations.

        :raises .errors.PluginError: If unable to revert the challenge config.

        N)Zrevert_temporary_configr:   r   r  r,   r&   r&   r'   Úrevert_challenge_config:  s    z)NginxConfigurator.revert_challenge_configr   c                    s$   t t| ƒ |¡ d| _| j ¡  dS )zúRollback 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)r6   r   Úrollback_checkpointsr:   r   r  )r-   ÚrollbackrE   r&   r'   r  D  s    	z&NginxConfigurator.rollback_checkpointsc                 C   s   t jgS )z%Return list of challenge preferences.)r   ZHTTP01)r-   Zunused_domainr&   r&   r'   Úget_chall_prefT  s    z NginxConfigurator.get_chall_prefc                 C   s|   |  j t|ƒ7  _ dgt|ƒ }t | ¡}t|ƒD ]\}}| ||¡ q2| ¡ }|  ¡  t|ƒD ]\}}|||j| < q`|S )a	  Perform the configuration related challenge.

        This function currently assumes all challenges will be fulfilled.
        If this turns out not to be the case in the future. Cleanup and
        outstanding challenges will have to be designed better.

        N)	r=   rž   r   ZNginxHttp01Ú	enumerateZ	add_challÚperformrò   Úindices)r-   ÚachallsÚ	responsesZ	http_doerr  ZachallÚhttp_responseÚrespr&   r&   r'   r   Y  s    
zNginxConfigurator.performc                 C   s0   |  j t|ƒ8  _ | j dkr,|  ¡  |  ¡  dS )zRevert all challenges.r   N)r=   rž   r  rò   )r-   r"  r&   r&   r'   Úcleanupy  s    
zNginxConfigurator.cleanup)NN)N)F)F)N)N)NF)r   )>Ú__name__Ú
__module__Ú__qualname__Ú__doc__Údescriptionr´   rê   Úclassmethodr(   Úpropertyr.   r7   rM   rP   rQ   rR   r]   rh   r`   rˆ   rŽ   r_   r—   r�   rš   r˜   rŠ   r‹   r°   r    r³   r�   r   r²   rÀ   rÍ   r“   rÑ   rÖ   rÙ   r?   rá   rÞ   r>   rì   r@   rî   rò   rU   r8   r  rV   rW   r  r  rB   r  r  r  r   r&  Ú__classcell__r&   r&   rE   r'   r   -   s~   


)
 

%   ÿ

1
/%
! 9
"
!(-

 r   c                 C   s"   t  | ¡}t |d¡ |d d… S )Nr   éÿÿÿÿ)r   ZUnspacedListr   Zcomment_directive)ÚblockZ
test_blockr&   r&   r'   r×   ƒ  s    
r×   c              	   C   sr   | }d}t  | ¡r:d}| dd¡}| dd¡}d| d }d	d
ddd|dd| dg	ddddddgd	ggdgg}|S )Nú=ú~r  z\.Ú*z[^.]+ú^ú$ri   Úifrj   z($hostz%s)z	
        rí   Z301zhttps://$host$request_urirÛ   )r   r�   Úreplace)ra   Zupdated_domainZmatch_symbolrà   r&   r&   r'   rØ   ‰  s    
ÿþürØ   c              
   C   sÆ   z”t  | d|ddg¡}| ¡  |jdkr’t ¡ �\}t ¡ �H}t j| d|g||d�}| ¡  |jdkr~t d| ¡ | ¡ f ¡‚W 5 Q R X W 5 Q R X W n" t	t
fk
r¶   t d¡‚Y nX t d¡ d	S )
a  Restarts the Nginx Server.

    .. todo:: Nginx restart is fatal if the configuration references
        non-existent SSL cert/key files. Remove references to /etc/letsencrypt
        before restart.

    :param str nginx_ctl: Path to the Nginx binary.

    ró   z-sÚreloadr   )rù   rú   znginx restart failed:
%s
%sznginx restart failedr   N)rü   rý   rÿ   Ú
returncodeÚtempfileÚTemporaryFiler	   r’   ÚreadrX   rÓ   ÚtimeÚsleep)Z	nginx_ctlr.   r   Úoutrö   Z
nginx_procr&   r&   r'   rñ   ™  s$    



 ÿ
ÿrñ   c                  C   s0   t j d¡dkr"dtjtjf } n
tjd } | S )NZCERTBOT_DOCSÚ1z%s or %sr   )r   ÚenvironÚgetr   ZLINUX_SERVER_ROOTZFREEBSD_DARWIN_SERVER_ROOTr"   )r%   r&   r&   r'   r!   ½  s    ÿ
r!   )9r*  Zdistutils.versionr   Úloggingr
  r·   rü   r:  r=  rK   rÅ   Zzope.interfaceZzopeZacmer   r   rÇ   Zacme.magic_typingr   r   r   Zcertbotr   r÷   r	   r
   r   Zcertbot.compatr   Zcertbot.pluginsr   rJ   r   r   r   r   r   r­   r¥   r¦   r®   r§   Ú	getLoggerr'  rY   Z	interfaceZimplementerZIAuthenticatorZ
IInstallerÚproviderZIPluginFactoryZ	Installerr   r×   rØ   rñ   r!   r&   r&   r&   r'   Ú<module>   s^   
        \$