Your IP : 216.73.216.224


Current Path : /lib/python3/dist-packages/certbot_apache/__pycache__/
Upload File :
Current File : //lib/python3/dist-packages/certbot_apache/__pycache__/configurator.cpython-38.pyc

U

���]e��@s�dZddlZddlZddlZddlZddlZddlZddlmZddl	Z	ddl
Z
ddlZddl
ZddlmZddlmZmZmZmZmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlm Z dd
l!m"Z"ddl#m$Z$ddl%m&Z&ddl%m'Z'ddl%m(Z(ddl%m)Z)ddl%m*Z*ddl%m+Z+e�,e-�Z.ej/�0ej1ej2�ej/�3ej4�Gdd�de j5���Z6e$�7e6�dS)zApache Configurator.�N)�defaultdict)�
challenges)�DefaultDict�Dict�List�Set�Union)�errors)�
interfaces)�util)�"KeyAuthorizationAnnotatedChallenge)�
filesystem)�os)�common)�path_surgery)�AutoHSTSEnhancement)�apache_util)�	constants)�display_ops)�http_01)�obj)�parsercs�eZdZdZdZej�d�dkr(ed7Zedddd	d
d
dgd
dgd
d
gdddddde	�
dd�d�Zdd�Zdd�Z
edd��Z�fdd�Zedd��Zedd��Zd d!�Zd�d"d#�Z�fd$d%�Zd&d'�Zd؇fd)d*�	Zd+d,�Zd-d.�Zd/d0�Zd�d1d2�Zd�d4d5�Zd6d7�Zd8d9�Zd�d:d;�Z d<d=�Z!d�d>d?�Z"d�d@dA�Z#dBdC�Z$d�dEdF�Z%d�dGdH�Z&dIdJ�Z'dKdL�Z(dMdN�Z)dOdP�Z*dQdR�Z+dSdT�Z,dUdV�Z-dWdX�Z.dYdZ�Z/d�d[d\�Z0d�d]d^�Z1d_d`�Z2dadb�Z3dcdd�Z4dedf�Z5dgdh�Z6didj�Z7dkdl�Z8dmdn�Z9dodp�Z:dqdr�Z;dsdt�Z<dudv�Z=dwdx�Z>dydz�Z?d{d|�Z@d}d~�ZAdd��ZBd�d��ZCd�d��ZDd�d��ZEd�d��ZFd�d��ZGd�d��ZHd�d��ZId�d��ZJd�d�d��ZKd�d��ZLd�d��ZMd�d��ZNd�d��ZOd�d��ZPd�d��ZQd�d��ZRd�d��ZSd�d��ZTd�d��ZUd�d��ZVd�d��ZWd�d��ZXd�d��ZYd�d��ZZd�d��Z[d�d��Z\d�d�d��Z]d�d��Z^d�d�d��Z_d�d��Z`d�d��Zad�d��Zbd�d„Zcd�dĄZdd�dƄZed�dȄZfd�dʄZgd�d̄Zhd�d΄Zid�dЄZjd�d҄Zkd�dԄZld�dքZm�ZnS)��ApacheConfiguratora�Apache configurator.

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

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

    :ivar tup version: version of Apache
    :ivar list vhosts: All vhosts found in the configuration
        (:class:`list` of :class:`~certbot_apache.obj.VirtualHost`)

    :ivar dict assoc: Mapping between domains and vhosts

    zApache Web Server plugin�CERTBOT_DOCS�1z (Please note that the default values of the Apache plugin options change depending on the operating system Certbot is run on.)z/etc/apache2z/etc/apache2/sites-available�*z/var/log/apache2Z
apache2ctlz-vZgracefulZ
configtestNz-le-ssl.confF�certbot_apachezoptions-ssl-apache.conf)�server_root�
vhost_rootZvhost_files�	logs_root�ctl�version_cmd�restart_cmd�conftest_cmd�enmod�dismod�le_vhost_ext�handle_modules�handle_sites�challenge_location�MOD_SSL_CONF_SRCcCs|j�|�S)zGet a value from options)�options�get)�self�key�r/�=/usr/lib/python3/dist-packages/certbot_apache/configurator.py�optionuszApacheConfigurator.optionc
Cs�ddddddddd	d
g
}|D]D}|�|�dd��d
k	rP|�|�dd��|j|<q|j||j|<q|�d
�|jdd<|�d
�|jdd<|�d
�|jdd<d
S)zw
        Set the values possibly changed by command line parameters to
        OS_DEFAULTS constant dictionary
        r$r%r&rrrr)r'r(r �_�-Nr!rr"r#)�conf�replacer+�OS_DEFAULTSr1)r-Zopts�or/r/r0�_prepare_optionsys
�z#ApacheConfigurator._prepare_optionscCs�tj�d�dkrtj}n|j}|d|ddd�|d|ddd�|d|d	d
d�|d|dd
d�|dddd�|d|ddd�|d|ddd�|d|ddd�|d|ddd�|d|ddd�tj|ddd �dS)!Nrrr$z#Path to the Apache 'a2enmod' binary)�default�helpr%z$Path to the Apache 'a2dismod' binaryzle-vhost-extr&z!SSL vhost configuration extensionzserver-rootrzApache server root directory�
vhost-rootz,Apache server VirtualHost configuration rootz	logs-rootrzApache server logs directoryzchallenge-locationr)z*Directory path for challenge configurationzhandle-modulesr'zULet installer handle enabling required modules for you (Only Ubuntu/Debian currently)zhandle-sitesr(zJLet installer handle enabling sites for you (Only Ubuntu/Debian currently)r z"Full path to Apache control scriptzinit-script�)Z
argument_name�nargs)r�environr,rr6rZadd_deprecated_argument)�cls�addZDEFAULTSr/r/r0�add_parser_arguments�sN
�
�
�
��
��
�
�
��z'ApacheConfigurator.add_parser_argumentscs�|�dd�}tt|�j||�t�|_t�|_t�|_t	t�|_
i|_d|_d|_
d|_||_d|_t�|j�|_|j|j|jd�|_dS)z�Initialize an Apache Configurator.

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

        �versionN�F)�redirect�ensure-http-header�staple-ocsp)�pop�superr�__init__�dict�assoc�set�
_chall_out�_wildcard_vhostsr�_enhanced_vhosts�	_autohsts�
save_notes�	_preparedrrB�vhosts�copy�deepcopyr6r+�_enable_redirect�_set_http_header�_enable_ocsp_stapling�
_enhance_func)r-�args�kwargsrB��	__class__r/r0rI�s"
�zApacheConfigurator.__init__cCstj�|jjtj�S)z-Full absolute path to SSL configuration file.)r�path�join�config�
config_dirrZMOD_SSL_CONF_DEST�r-r/r/r0�mod_ssl_conf�szApacheConfigurator.mod_ssl_confcCstj�|jjtj�S)z?Full absolute path to digest of updated SSL configuration file.)rr^r_r`rarZUPDATED_MOD_SSL_CONF_DIGESTrbr/r/r0�updated_mod_ssl_conf_digest�sz.ApacheConfigurator.updated_mod_ssl_conf_digestc
Cs|��|�|�d��|��|jdkrR|��|_t�dd�dd�|jD���|jdkrrt	�
d�t|j����|�
�|��|_|j�d	�|��|_|�|j|j�zt�|�d
��Wn>tt	jfk
r�tjddd
�t	�d�|�d
����YnXd|_dS)aWPrepare the authenticator/installer.

        :raises .errors.NoInstallationError: If Apache configs cannot be found
        :raises .errors.MisconfigurationError: If Apache is misconfigured
        :raises .errors.NotSupportedError: If Apache version is not supported
        :raises .errors.PluginError: If there is any other error

        r NzApache version is %s�.css|]}t|�VqdS�N��str��.0�ir/r/r0�	<genexpr>�sz-ApacheConfigurator.prepare.<locals>.<genexpr>)�rmz!Apache Version {0} not supported.z	httpd.augrzEncountered error:T��exc_infoz|Unable to create a lock file in {0}. Are you running Certbot with sufficient privileges to modify your Apache configuration?)r8�_verify_exe_availabilityr1�config_testrB�get_version�logger�debugr_r	ZNotSupportedError�formatrh�recovery_routine�
get_parserrZcheck_parsing_errors�get_virtual_hostsrS�install_ssl_options_confrcrdrZlock_dir_until_exit�OSErrorZ	LockError�PluginErrorrRrbr/r/r0�prepare�s:	

�
�

���
zApacheConfigurator.preparecCsB|j��}|r |j||j|d�|j�|�|r>|s>|�|�dS)afSaves all changes to the configuration files.

        This function first checks for save errors, if none are found,
        all configuration changes made will be saved. According to the
        function parameters. If an exception is raised, a new checkpoint
        was not created.

        :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)

        )�	temporaryN)rZ
unsaved_files�add_to_checkpointrQ�saveZfinalize_checkpoint)r-�titler}Z
save_filesr/r/r0rs
�zApacheConfigurator.savecs$tt|���|jr |jj��dS)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)rHrrvr�aug�loadrbr\r/r0rv-sz#ApacheConfigurator.recovery_routinecCs|��|jj��dS)z�Used to cleanup challenge configurations.

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

        N)Zrevert_temporary_configrr�r�rbr/r/r0�revert_challenge_config<sz*ApacheConfigurator.revert_challenge_configr<cs tt|��|�|jj��dS)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)rHr�rollback_checkpointsrr�r�)r-Zrollbackr\r/r0r�Es	z'ApacheConfigurator.rollback_checkpointscCs&t�|�s"t|�s"t�d�|���dS)z(Checks availability of Apache executablez!Cannot find Apache executable {0}N)rZ
exe_existsrr	ZNoInstallationErrorru)r-�exer/r/r0rpQs

�z+ApacheConfigurator._verify_exe_availabilitycCs tj|�d�|�d�|j|d�S)zInitializes the ApacheParserrr;)Zconfigurator)rZApacheParserr1r4rBrbr/r/r0rwXs�zApacheConfigurator.get_parsercCs t|tj�rd}nd}|�|�S)z�
        Checks if domain is a wildcard domain

        :param str domain: Domain to check

        :returns: If the domain is wildcard domain
        :rtype: bool
        z*.s*.)�
isinstance�sixZ	text_type�
startswith)r-�domainZwildcard_markerr/r/r0�_wildcard_domain_s	z#ApacheConfigurator._wildcard_domaincCs*|�|�}|D]}|�|||||�qdS)a�Deploys certificate to specified virtual host.

        Currently tries to find the last directives to deploy the certificate
        in the VHost associated with the given domain. If it can't find the
        directives, it searches the "included" confs. The function verifies
        that it has located the three directives and finally modifies them
        to point to the correct destination. After the certificate is
        installed, the VirtualHost is enabled if it isn't already.

        .. todo:: Might be nice to remove chain directive if none exists
                  This shouldn't happen within certbot though

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

        N)�
choose_vhosts�_deploy_cert)r-r��	cert_path�key_path�
chain_path�fullchain_pathrS�vhostr/r/r0�deploy_certns
zApacheConfigurator.deploy_certTcCs<|�|�r*||jkr|j|S|�||�S|�||�gSdS)a�
        Finds VirtualHosts that can be used with the provided domain

        :param str domain: Domain name to match VirtualHosts to
        :param bool create_if_no_ssl: If found VirtualHost doesn't have a HTTPS
            counterpart, should one get created

        :returns: List of VirtualHosts or None
        :rtype: `list` of :class:`~certbot_apache.obj.VirtualHost`
        N)r�rN�_choose_vhosts_wildcard�choose_vhost)r-r��create_if_no_sslr/r/r0r��s



z ApacheConfigurator.choose_vhostscCs>t�}|jD](}|��D]}|�||�r|�|�qqt|�S)z~
        Get VHost objects for every VirtualHost that the user wants to handle
        with the wildcard certificate.
        )rLrS�	get_names�_in_wildcard_scoper@�list)r-r�Zmatchedr��namer/r/r0�_vhosts_for_wildcard�s
z'ApacheConfigurator._vhosts_for_wildcardcCs,t|�d��t|�d��kr(t�||�SdS)a
        Helper method for _vhosts_for_wildcard() that makes sure that the domain
        is in the scope of wildcard domain.

        eg. in scope: domain = *.wild.card, name = 1.wild.card
        not in scope: domain = *.wild.card, name = 1.2.wild.card
        reN)�len�split�fnmatch)r-r�r�r/r/r0r��sz%ApacheConfigurator._in_wildcard_scopec
Cs�|�|�}t�}|D]6}|��D](}|jr4|||<q ||kr |r |||<q qtdd�|��D��}t�t|��}|s�t	�
d|�t�d��t�}	|D]&}|js�|	�
|�|��q�|	�
|�q�|	|j|<|	S)zCPrompts user to choose vhosts to install a wildcard certificate forcSsg|]}|�qSr/r/�rjr�r/r/r0�
<listcomp>�sz>ApacheConfigurator._choose_vhosts_wildcard.<locals>.<listcomp>z�No vhost exists with servername or alias for domain %s. No vhost was selected. Please specify ServerName or ServerAlias in the Apache config.�No vhost selected)r�rJr��sslrL�valuesrZselect_vhost_multipler�rs�errorr	r{�append�make_vhost_sslrN)
r-r�Z
create_sslrS�filtered_vhostsr�r�Zdialog_inputZ
dialog_outputZ
return_vhostsr/r/r0r��s.

�

z*ApacheConfigurator._choose_vhosts_wildcardcCs�|�d�|�|j�|�|�|j�dd|j�|j�dd|j�d�}|dk	rd|j�dd|j�|d<|ds�t�d	|j�t�	d
��n |ds�t�d|j�t�	d
��t�
d|j�|jdks�|�r(|�s(|}|jj
�|dd|�|jj
�|dd|�|dk	�r|j�|jd|�n
t�	d��nD|�s8t�	d��|}|jj
�|dd|�|jj
�|dd|�|j�s~|�|�|jd|jd�dd�|jD��||f7_|dk	�r�|jd|7_dS)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
        �443�SSLCertificateFileN�SSLCertificateKeyFile)r��cert_key�SSLCertificateChainFiler�r�zOCannot find an SSLCertificateFile directive in %s. VirtualHost was not modifiedz.Unable to find an SSLCertificateFile directiver�zbCannot find an SSLCertificateKeyFile directive for certificate in %s. VirtualHost was not modifiedzAUnable to find an SSLCertificateKeyFile directive for certificatez'Deploying Certificate to VirtualHost %s)rm�����z3--chain-path is required for your version of ApachezKPlease provide the --fullchain-path option pointing to your full chain filezZChanged vhost at %s with addresses of %s
	SSLCertificateFile %s
	SSLCertificateKeyFile %s
z, css|]}t|�VqdSrfrg�rj�addrr/r/r0rl(sz2ApacheConfigurator._deploy_cert.<locals>.<genexpr>z	SSLCertificateChainFile %s
)�prepare_server_https�_add_dummy_ssl_directivesr^�_clean_vhostr�find_dirrs�warningr	r{�info�fileprBr�rL�add_dir�enabled�enable_siterQr_�addrs)r-r�r�r�r�r�r^Z
set_cert_pathr/r/r0r��sz	

��������

�

��
zApacheConfigurator._deploy_certcCsh||jkr|j|S|�|�}|dk	rX|s.|S|js>|�|�}|�||�||j|<|S|j||d�S)a�Chooses a virtual host based on the given domain name.

        If there is no clear virtual host to be selected, the user is prompted
        with all available choices.

        The returned vhost is guaranteed to have TLS enabled unless
        create_if_no_ssl is set to False, in which case there is no such guarantee
        and the result is not cached.

        :param str target_name: domain name
        :param bool create_if_no_ssl: If found VirtualHost doesn't have a HTTPS
            counterpart, should one get created

        :returns: vhost associated with name
        :rtype: :class:`~certbot_apache.obj.VirtualHost`

        :raises .errors.PluginError: If no vhost is available or chosen

        N��temp)rK�_find_best_vhostr�r��_add_servername_alias�_choose_vhost_from_list)r-�target_namer�r�r/r/r0r�-s




zApacheConfigurator.choose_vhostcs�t�||j�}|dkr.t�d|�t�d��nR|r6|S|js�|�|d��t	�fdd�|jD��sl|�
|�}nt�d�t�d��|�||�||j|<|S)Nz�No vhost exists with servername or alias of %s. No vhost was selected. Please specify ServerName or ServerAlias in the Apache config.r�r�c3s|]}|jo|���VqdSrf)r��	conflictsr��r�r/r0rlds�z=ApacheConfigurator._choose_vhost_from_list.<locals>.<genexpr>z�The selected vhost would conflict with other HTTPS VirtualHosts within Apache. Please select another vhost or add ServerNames to your configuration.z$VirtualHost not able to be selected.)
rZselect_vhostrSrsr�r	r{r��_get_proposed_addrs�anyr�r�rK)r-r�r�r�r/r�r0r�Us0����
z*ApacheConfigurator._choose_vhost_from_listcCs8|��}|D]&}|��}d|krt�||�rdSqdS)a�Checks if target domain is covered by one or more of the provided
        names. The target name is matched by wildcard as well as exact match.

        :param names: server aliases
        :type names: `collections.Iterable` of `str`
        :param str target_name: name to compare with wildcards

        :returns: True if target_name is covered by a wildcard,
            otherwise, False
        :rtype: bool

        �[TF)�lowerr�)r-�namesr�r�r/r/r0�domain_in_namesssz"ApacheConfigurator.domain_in_names�80csFg}|jD],}t�fdd�|jD��r
|js
|�|�q
|�|||�S)a�Returns non-HTTPS vhost objects found from the Apache config

        :param str target: Domain name of the desired VirtualHost
        :param bool filter_defaults: whether _default_ vhosts should be
            included if it is the best match
        :param str port: port number the vhost should be listening on

        :returns: VirtualHost object that's the best match for target name
        :rtype: `obj.VirtualHost` or None
        c3s"|]}|��p|���kVqdSrf)Zis_wildcard�get_port�rj�a��portr/r0rl�sz:ApacheConfigurator.find_best_http_vhost.<locals>.<genexpr>)rSr�r�r�r�r�)r-�target�filter_defaultsr�r�r�r/r�r0�find_best_http_vhost�s

z'ApacheConfigurator.find_best_http_vhostc
s�d}d}|dkr|j}|D]v}|jdkr*q|��}�|kr@d}n2|�|��rRd}n t�fdd�|jD��rd}nq|jr�|d7}||kr|}|}q|dkr�|r�|�|�}d	d
�|D�}	t|	�dkr�|	d}|S)a�Finds the best vhost for a target_name.

        This does not upgrade a vhost to HTTPS... it only finds the most
        appropriate vhost for the given target_name.

        :param str target_name: domain handled by the desired vhost
        :param vhosts: vhosts to consider
        :type vhosts: `collections.Iterable` of :class:`~certbot_apache.obj.VirtualHost`
        :param bool filter_defaults: whether a vhost with a _default_
            addr is acceptable

        :returns: VHost or None

        NrT�rmc3s|]}|���kVqdSrf��get_addrr��r�r/r0rl�sz6ApacheConfigurator._find_best_vhost.<locals>.<genexpr>r<cSsg|]}|jdkr|�qS)F��modmacro�rj�vhr/r/r0r��s
�z7ApacheConfigurator._find_best_vhost.<locals>.<listcomp>)	rSr�r�r�r�r�r��_non_default_vhostsr�)
r-r�rSr�Zbest_candidateZbest_pointsr�r�ZpointsZreasonable_vhostsr/r�r0r��s:

�z#ApacheConfigurator._find_best_vhostcCsdd�|D�S)z%Return all non _default_ only vhosts.cSs$g|]}tdd�|jD��s|�qS)css|]}|��dkVqdS)�	_default_Nr�r�r/r/r0rl�szDApacheConfigurator._non_default_vhosts.<locals>.<listcomp>.<genexpr>)�allr�r�r/r/r0r��s
�z:ApacheConfigurator._non_default_vhosts.<locals>.<listcomp>r/)r-rSr/r/r0r��sz&ApacheConfigurator._non_default_vhostscCs�t�}g}|jD]h}|�|���|jr4|�|j�|jD]<}tj	�
|���r^|�|���q:|�
|�}|r:|�|�q:q|r�tj�tj�jd�d�|��dd�t�|�S)z�Returns all names found in the Apache Configuration.

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

        zaApache mod_macro seems to be in use in file(s):
{0}

Unfortunately mod_macro is not yet supportedz
  T)Zforce_interactive)rLrS�updater�r�r�r�r�rZhostname_regex�matchr�r@�get_name_from_ip�zope�	component�
getUtilityr
ZIDisplayZnotificationrur_rZget_filtered_names)r-Z	all_namesZvhost_macror�r�r�r/r/r0�
get_all_names�s(


��z ApacheConfigurator.get_all_namesc
CsXtj�|���sTz"t�|���t�|���dWStjtjtj	fk
rRYnXdS)z�Returns a reverse dns name if available.

        :param addr: IP Address
        :type addr: ~.common.Addr

        :returns: name or empty string if name cannot be determined
        :rtype: str

        rrC)
rZprivate_ips_regexr�r��socketZ	inet_atonZ
gethostbyaddrr�ZherrorZtimeout)r-r�r/r/r0r��sz#ApacheConfigurator.get_name_from_ipcCsl|jjdd|dd�}|jjdd|dd�}g}|D]}|j�|�}|�|�q0d}|rd|j�|d�}||fS)z�Helper method for getting the ServerName and
        ServerAlias values from vhost in path

        :param path: Path to read ServerName and ServerAliases from

        :returns: Tuple including ServerName and `list` of ServerAlias strings
        �
ServerNameNF��startZexclude�ServerAliasr�)rr��get_argr�)r-r^Zservername_matchZserveralias_match�
serveraliases�alias�serveralias�
servernamer/r/r0�_get_vhost_namess(	��z#ApacheConfigurator._get_vhost_namescCs<|�|j�\}}|D]}|js|j�|�q|js8||_dS)z�Helper function for get_virtual_hosts().

        :param host: In progress vhost whose names will be added
        :type host: :class:`~certbot_apache.obj.VirtualHost`

        N)r�r^r��aliasesr@r�)r-Zhostr�r�r�r/r/r0�_add_servernames-sz#ApacheConfigurator._add_servernamescCst�}z|jj�|d�}Wn"tk
r>t�d|�YdSX|D]}|�tj	�
|j�|���qDd}|jjdd|dd�r�d}|D]}|�
�d	kr�d}q�t�|jj�d
t�|���}|dkr�dSd}d|��kr�d}|j�|�}	tj|||||	|d�}
|�|
�|
S)
z�Used by get_virtual_hosts to create vhost objects

        :param str path: Augeas path to virtual host

        :returns: newly created vhost
        :rtype: :class:`~certbot_apache.obj.VirtualHost`

        �/argz6Encountered a problem while parsing file: %s, skippingNFZ	SSLEngine�onr�Tr�z/augeas/files%s/pathz/macro/r�)rLrr�r��RuntimeErrorrsr�r@r�Addr�
fromstringr�r�r�rZ
get_file_pathr,r��parsed_in_original�VirtualHostr�)r-r^r�rZ�argZis_sslr��filenameZmacroZ
vhost_enabledr�r/r/r0�
_create_vhost>s:	��
z ApacheConfigurator._create_vhostcCsRi}tt�}g}t|jj�D�].}|jj�d|t�d�f�}dd�|D�}|D]�}|�|�}|sdqPt	�
|j�}t�
|j�}	|	|kr�|j||	<||	�|�|�|�qP|	|jk�r&|	||	k�r&g}
|D]4}|j||	kr�||	�t	�
|j��q�|
�|�q�|
}|	||	<||	�|�|�|�qP|||	krP||	�|�|�|�qPq|S)z�Returns list of virtual hosts found in the Apache configuration.

        :returns: List of :class:`~certbot_apache.obj.VirtualHost`
            objects found in configuration
        :rtype: list

        z"/files%s//*[label()=~regexp('%s')]r�cSs$g|]}dtj�|���kr|�qS)�virtualhost)rr^�basenamer�)rjr^r/r/r0r�|s�z8ApacheConfigurator.get_virtual_hosts.<locals>.<listcomp>)rrLr�rZparser_pathsr�r��case_ir�rZget_internal_aug_pathr^r
�realpathr�r@r��remove)r-Z
file_pathsZinternal_pathsZvhsZ
vhost_path�pathsr^�	new_vhostZ
internal_pathr�Znew_vhs�vr/r/r0rxjsL	��


�
�z$ApacheConfigurator.get_virtual_hostscCs|jdkp|j�dt|��S)azReturns if vhost is a name based vhost

        NameVirtualHost was deprecated in Apache 2.4 as all VirtualHosts are
        now NameVirtualHosts. If version is earlier than 2.4, check if addr
        has a NameVirtualHost directive in the Apache config

        :param certbot_apache.obj.Addr target_addr: vhost address

        :returns: Success
        :rtype: bool

        �rmr��NameVirtualHost)rBrr�rh)r-Ztarget_addrr/r/r0�
is_name_vhost�s
�z ApacheConfigurator.is_name_vhostcCstt�|jjd�}|��dkr6|j�|dt|�g�}n|j�|dt|�g�}d||f}t�|�|j	|7_	dS)z�Adds NameVirtualHost directive for given address.

        :param addr: Address that will be added as NameVirtualHost directive
        :type addr: :class:`~certbot_apache.obj.Addr`

        r�r�rz=Setting %s to be NameBasedVirtualHost
	Directive added to %s
N)
r�get_aug_path�locr��add_dir_to_ifmodsslrhr�rsrtrQ)r-r�rr^�msgr/r/r0�add_name_vhost�s��
z!ApacheConfigurator.add_name_vhostcCs|�|�|j|dd�dS)z�Prepare the server for HTTPS.

        Make sure that the ssl_module is loaded and that the server
        is appropriately listening on port.

        :param str port: Port to listen on

        T)�httpsN)�prepare_https_modules�
ensure_listen)r-r�r�r/r/r0r��s

z'ApacheConfigurator.prepare_server_httpsc	s|r|dkrd|df}n|}�fdd��j�d�D�}��||�rHdSt|�}|s^|�|�|D]�}t|�d��d	kr�||kr�||kr�|�|�qb|ddd
��dd	�\}}|ddd
�}d||f|krbd||f|krb|�d||f�qb|�r��|||�n��|||�dS)aXMake sure that Apache is listening on the port. Checks if the
        Listen statement for the port already exists, and adds it to the
        configuration if necessary.

        :param str port: Port number to check and add Listen for if not in
            place already
        :param bool https: If the port will be used for HTTPS

        r��%s %srcs g|]}�j�|���d�qS)r)rr�r��rj�xrbr/r0r��s�z4ApacheConfigurator.ensure_listen.<locals>.<listcomp>�ListenN�:r<r�z%s:%s)	rr��_has_port_alreadyrLr@r�r��_add_listens_https�_add_listens_http)	r-r�r�port_service�listensZlisten_dirs�listenr2Zipr/rbr0r�s0

�
�z ApacheConfigurator.ensure_listencCs�|�|�}||krP|j�t�|jjd�d|�|jd||jjdf7_nL|D]F}|j�t�|jjd�d|�d��|jd||jjdf7_qTdS)a<Helper method for ensure_listen to figure out which new
        listen statements need adding for listening HTTP on port

        :param set listens: Set of all needed Listen statements
        :param list listens_orig: List of existing listen statements
        :param string port: Port number we're adding
        rr� Added Listen %s directive to %s
� N)�
differencerr�rrrQr�)r-r�listens_origr��new_listensrr/r/r0rs,	
�
�

��
��z$ApacheConfigurator._add_listens_httpcCs�|dkrd|df}n|}|�|�}||ks4||krx|j�t�|jjd�d|�d��|jd||jjdf7_nL|D]F}|j�t�|jjd�d|�d��|jd||jjdf7_q|dS)	a=Helper method for ensure_listen to figure out which new
        listen statements need adding for listening HTTPS on port

        :param set listens: Set of all needed Listen statements
        :param list listens_orig: List of existing listen statements
        :param string port: Port number we're adding
        r�rrrrrrN)rrr	rrr�rQ)r-rrr�rrrr/r/r0r s2

�
��
��z%ApacheConfigurator._add_listens_httpscCsN||krdS|D]8}t|�d��dkr|�d�d�d�d|krdSqdS)z�Helper method for prepare_server_https to find out if user
        already has an active Listen statement for the port we need

        :param list listens: List of listen variables
        :param string port: Port in question
        Trr<r�rrN)r�r�)r-rr�rr/r/r0rAsz$ApacheConfigurator._has_port_alreadycCsL|�d�rH|jdkr.d|jjkr.|jd|d�d|jjkrH|jd|d�dS)	z�Helper method for prepare_server_https, taking care of enabling
        needed modules

        :param boolean temp: If the change is temporary
        r'r�socache_shmcb_module�
socache_shmcbr�Z
ssl_moduler�N)r1rBr�modules�
enable_mod)r-r�r/r/r0r
Ss
�z(ApacheConfigurator.prepare_https_modulescCs|j}|�|�}|jj�d|�|�t�d�f�}|�||�|jj��|jj�d|�|�t�d�f�}|�	||�}|s�|j�
|�|jj�d|�|�t�d�f�}|�	||�}|s�t�d��|�
|�t�d|�|jd|7_|��|�|�}||_|j�|�|�|�|S)axMakes an ssl_vhost version of a nonssl_vhost.

        Duplicates vhost and adds default ssl options
        New vhost will reside as (nonssl_vhost.path) +
        ``self.option("le_vhost_ext")``

        .. note:: This function saves the configuration

        :param nonssl_vhost: Valid VH that doesn't have SSLEngine on
        :type nonssl_vhost: :class:`~certbot_apache.obj.VirtualHost`

        :returns: SSL vhost
        :rtype: :class:`~certbot_apache.obj.VirtualHost`

        :raises .errors.PluginError: If more than one virtual host is in
            the file or if plugin is unable to write/read vhost files.

        z#/files%s//* [label()=~regexp('%s')]r�z;Could not reverse map the HTTPS VirtualHost to the originalzCreated an SSL vhost at %szCreated ssl vhost at %s
)r��_get_ssl_vhost_pathrr�r��_escaper��_copy_create_ssl_vhost_skeletonr��_get_new_vh_path�
parse_filer	r{�_update_ssl_vhosts_addrsrsr�rQrr��ancestorrSr��_add_name_vhost_if_necessary)r-Znonssl_vhostZavail_fp�ssl_fp�orig_matches�new_matchesZvh_p�	ssl_vhostr/r/r0r�asL

��
������

	
z!ApacheConfigurator.make_vhost_sslcCs4dd�|D�}|D]}|�dd�|kr|SqdS)a Helper method for make_vhost_ssl for matching augeas paths. Returns
        VirtualHost path from new_matches that's not present in orig_matches.

        Paths are normalized, because augeas leaves indices out for paths
        with only single directive with a similar key cSsg|]}|�dd��qS)�[1]rC�r5rir/r/r0r��sz7ApacheConfigurator._get_new_vh_path.<locals>.<listcomp>r/rCNr0)r-r,r-r�r/r/r0r&�s

z#ApacheConfigurator._get_new_vh_pathcCs~|�d�r@tj�|�d��r@tj�t�|�d��tj�|��}n
t�|�}|�	d�rp|dt
d��|�d�S||�d�S)a- Get a file path for SSL vhost, uses user defined path as priority,
        but if the value is invalid or not defined, will fall back to non-ssl
        vhost filepath.

        :param str non_ssl_vh_fp: Filepath of non-SSL vhost

        :returns: Filepath for SSL vhost
        :rtype: str
        r;rz.confNr&)r4rr^�existsr_r
r�r1r��endswithr�)r-Z
non_ssl_vh_fp�fpr/r/r0r#�s
�

z&ApacheConfigurator._get_ssl_vhost_pathcCsX|�����d�sdS|��d��}|ddkrN|d|dkrN|dd�}|�d�S)	a`Decides whether a line should be copied to a SSL vhost.

        A canonical example of when sifting a line is required:
        When the http vhost contains a RewriteRule that unconditionally
        redirects any request to the https version of the same site.
        e.g:
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,QSA,R=permanent]
        Copying the above line to the ssl vhost would cause a
        redirection loop.

        :param str line: a line extracted from the http vhost.

        :returns: True - don't copy line from http vhost to SSL vhost.
        :rtype: bool

        �rewriteruleFrmr)�'�"r�r<zhttps://)r��lstripr�r��strip)r-�liner�r/r/r0�_sift_rewrite_rule�sz%ApacheConfigurator._sift_rewrite_rulec
	CsRtj�|�r4d|}t�}|�|�|j�||�n|j�d|�d}zx|�|�}|�	|�\}}t
|d��4}|�d�|�d�|��|�d�|�d�W5QRX|j
�|�s�|j
�|�Wn,tk
r�tjdd	d
�t�d��YnX|�rtj�tj�}	|	�d�|j|�|	j�|j
j�d
|�|�d�|j
j�d
|�|j�d�dS)aCopies over existing Vhost with IfModule mod_ssl.c> skeleton.

        :param obj.VirtualHost vhost: Original VirtualHost object
        :param str ssl_fp: Full path where the new ssl_vhost will reside.

        A new file is created on the filesystem.

        z-Appended new VirtualHost directive to file %sFr�z<IfModule mod_ssl.c>
�
z</VirtualHost>
z</IfModule>
z/Error writing/reading to file in make_vhost_sslTrnz&Unable to write/read in make_vhost_sslz�Some rewrite rules copied from {0} were disabled in the vhost for your HTTPS site located at {1} because they have the potential to create redirection loops.z/augeas/files%s/mtime�0N) rr^r1rLr@�reverterr~�register_file_creation�_get_vhost_block�_sift_rewrite_rules�open�writer_r�parsed_in_currentr'�IOErrorrs�criticalr	r{r�r�r�r
Z	IReporterZadd_messagerur�ZMEDIUM_PRIORITYr�r$)
r-r�r+Znotes�files�siftZ
orig_contentsZssl_vh_contentsZnew_fileZreporterr/r/r0r%�s>



��z2ApacheConfigurator._copy_create_ssl_vhost_skeletonc	CsDg}d}t|�}d}|D�] }|�����d�}|�����d�}|sV|sV|�|�q|rp|�|�sp|�|�q|r�|�|�r�|s�|�|�d}|�d|�qg}|r|�|�t|�}|�����d�s�|�|�t|�}q�|�|�|�|��r(|�s
|�|�d}|�d�dd	�|D���qq|�d�|��qq||fS)
z� Helper function for _copy_create_ssl_vhost_skeleton to prepare the
        new HTTPS VirtualHost contents. Currently disabling the rewrites Fz�# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.
Zrewritecondr4T�# r;cSsg|]}d|�qS)rHr/)rj�lr/r/r0r�]sz:ApacheConfigurator._sift_rewrite_rules.<locals>.<listcomp>)�iterr�r7r�r�r:�nextr_)	r-�contents�resultrG�commentr9�A�B�chunkr/r/r0r@$sL








�z&ApacheConfigurator._sift_rewrite_rulesc	Cs�z|jj�|j�}Wn4tk
rHtjd|j|jdd�t	�
d��YnX|d}|d}|d}t|d��$}|�|�|�
||��d	�}W5QRX|�|�|S)
a Helper method to get VirtualHost contents from the original file.
        This is done with help of augeas span, which returns the span start and
        end positions

        :returns: `list` of VirtualHost block content lines without closing tag
        z3Error while reading the VirtualHost %s from file %sTrnz$Unable to read VirtualHost from filer���rr;)rr��spanr^�
ValueErrorrsrEr�r�r	r{rA�seek�readr��_remove_closing_vhost_tag)r-r�Zspan_valZ
span_filepZ
span_startZspan_endZfh�vh_contentsr/r/r0r?ds"�

z#ApacheConfigurator._get_vhost_blockcCsXtt|��D]F\}}|r|���d�}|dkrNt|�|d}|d|�||<qTqdS)a�Removes the closing VirtualHost tag if it exists.

        This method modifies vh_contents directly to remove the closing
        tag. If the closing vhost tag is found, everything on the line
        after it is also removed. Whether or not this tag is included
        in the result of span depends on the Augeas version.

        :param list vh_contents: VirtualHost block contents to check

        z</virtualhost>r�r<N)�	enumerate�reversedr��findr�)r-rZ�offsetr9Z
line_indexZ
content_indexr/r/r0rY{sz,ApacheConfigurator._remove_closing_vhost_tagcCsft�}|jj�|d�}|D]D}tj�t|j�|���}|�	d�}|jj�|t|��|�
|�q|S)Nr�r�)rLrr�r�rr�r�rhr��get_addr_objr@)r-�vh_pathZ	ssl_addrsZ
ssl_addr_pr�Zold_addrZssl_addrr/r/r0r(�s�
z+ApacheConfigurator._update_ssl_vhosts_addrscCs&|�|jddg�|�|jdg�dS)Nr�r�r�)�_deduplicate_directivesr^�_remove_directives�r-r�r/r/r0r��s��zApacheConfigurator._clean_vhostc	CsX|D]N}t|j�|d|d��dkr|j�|d|d�}|jj�t�dd|d��qqdS)NFr<�/\w*$rCr)r�rr�r�r�re�sub�r-r`Z
directivesZ	directiveZdirective_pathr/r/r0ra�s��
�z*ApacheConfigurator._deduplicate_directivesc	CsP|D]F}|j�|d|d�r|j�|d|d�}|jj�t�dd|d��qqdS)NFrdrCr)rr�r�rrerfrgr/r/r0rb�s
�z%ApacheConfigurator._remove_directivescCsL|j�|dd�|j�|dd�|j�d|j|�}|sH|j�|d|j�dS)Nr�Zinsert_cert_file_pathr�Zinsert_key_file_pathZInclude)rr�r�rc)r-r`Zexisting_incr/r/r0r��s
�
�z,ApacheConfigurator._add_dummy_ssl_directivescCs||j}|�|�\}}||ks$||kr(dS|�||�r8dS|jjdd|dd�s^|j�|d|�n|j�|d|�|�|�dS)Nr�Fr�r�)r^r��_has_matching_wildcardrr�r�r�)r-r�r�r`ZsnameZsaliasesr/r/r0r��s
�z(ApacheConfigurator._add_servername_aliascs0�jjd|dd�}�fdd�|D�}��||�S)aLIs target_name already included in a wildcard in the vhost?

        :param str vh_path: Augeas path to the vhost
        :param str target_name: name to compare with wildcards

        :returns: True if there is a wildcard covering target_name in
            the vhost in vhost_path, otherwise, False
        :rtype: bool

        r�Fr�c3s|]}�jj�|�VqdSrf�rr�r,)rjr�rbr/r0rl�sz<ApacheConfigurator._has_matching_wildcard.<locals>.<genexpr>)rr�r�)r-r`r��matchesr�r/rbr0rh�s�z)ApacheConfigurator._has_matching_wildcardcs�d}|jD]��t�f�����dkr<���fdd�dD��|jD]P}|j|jkrBt�fdd�|jD��rB|���sB|���t	�
d��d}q
qBq
|r�|��dS)	aGAdd NameVirtualHost Directives if necessary for new vhost.

        NameVirtualHosts was a directive in Apache < 2.4
        https://httpd.apache.org/docs/2.2/mod/core.html#namevirtualhost

        :param vhost: New virtual host that was recently created.
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        F)rr�c3s |]}t�|���f�VqdSrf)rr�r�r�)r�r/r0rl�s�zBApacheConfigurator._add_name_vhost_if_necessary.<locals>.<genexpr>c3s|]}|�kVqdSrfr/)rjZ	test_addrr�r/r0rl�s�zEnabling NameVirtualHosts on %sTN)r�rLr�r�rSr�r�rrrsr�r)r-r�Zneed_to_saveZtest_vhr/)r�r�r0r*�s*


�
���
z/ApacheConfigurator._add_name_vhost_if_necessarycCsD|jD]}|�|�|kr|Sqd�|�}t�|�t�|��dS)a>
        Searches through VirtualHosts and tries to match the id in a comment

        :param str id_str: Id string for matching

        :returns: The matched VirtualHost or None
        :rtype: :class:`~certbot_apache.obj.VirtualHost` or None

        :raises .errors.PluginError: If no VirtualHost is found
        z$No VirtualHost with ID {} was found.N)rS�_find_vhost_idrursr�r	r{)r-�id_strr�r
r/r/r0�find_vhost_by_id�s



z#ApacheConfigurator.find_vhost_by_idcCsBtj�d�}|j�||j�}|r>|j�|d�}|�d�dSdS)aCTries to find the unique ID from the VirtualHost comments. This is
        used for keeping track of VirtualHost directive over time.

        :param vhost: Virtual host to add the id
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :returns: The unique ID or None
        :rtype: str or None
        rCrrr�N)r�MANAGED_COMMENT_IDrurZ
find_commentsr^r�r�)r-r�Zsearch_commentZ
id_commentrNr/r/r0rksz!ApacheConfigurator._find_vhost_idcCs:|�|�}|r|St��}tj�|�}|j�|j|�|S)a�Adds an unique ID to the VirtualHost as a comment for mapping back
        to it on later invocations, as the config file order might have changed.
        If ID already exists, returns that instead.

        :param vhost: Virtual host to add or find the id
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :returns: The unique ID for vhost
        :rtype: str or None
        )	rkrZ	unique_idrrnrurZadd_commentr^)r-r�Zvh_idZ	id_stringrNr/r/r0�add_vhost_id%s
zApacheConfigurator.add_vhost_idcCsd|�dd�}|�dd�}|�dd�}|�dd�}|�d	d
�}|�dd�}|�d
d�}|�dd�}|S)N�,z\,r�z\[�]z\]�|z\|�=z\=�(z\(�)z\)�!z\!r0)r-r3r/r/r0r$:szApacheConfigurator._escapecCs
dddgS)z)Returns currently supported enhancements.rDrErFr/rbr/r/r0�supported_enhancementsHsz)ApacheConfigurator.supported_enhancementscCs�z|j|}Wn$tk
r2t�d�|���YnX|j|dd�}dd�|D�}|s�d}|}|rl|d|7}|�||�}	t�|	�t�|	��z|D]}
||
|�q�Wn&tjk
r�t�d||��YnXd	S)
a�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.

        :raises .errors.PluginError: If Enhancement is not supported, or if
            there is any other problem with the enhancement.

        zUnsupported enhancement: {0}F�r�cSsg|]}|jr|�qSr/�r�r�r/r/r0r�bsz.ApacheConfigurator.enhance.<locals>.<listcomp>z�Certbot was not able to find SSL VirtualHost for a domain {0} for enabling enhancement "{1}". The requested enhancement was not configured.z: zFailed %s for %sN)rY�KeyErrorr	r{rur�rsr�)r-r�Zenhancementr+�func�matched_vhostsrS�msg_tmplZmsg_enhancementr
r�r/r/r0�enhanceLs,�


zApacheConfigurator.enhancecCs.tj|}|�||�|t��d�|j|<dS)a Increase the AutoHSTS max-age value

        :param vhost: Virtual host object to modify
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :param str id_str: The unique ID string of VirtualHost

        :param int nextstep: Next AutoHSTS max-age value index

        ��laststep�	timestampN)r�AUTOHSTS_STEPS�_autohsts_write�timerP)r-r�rl�nextstep�nextstep_valuer/r/r0�_autohsts_increaseus
z%ApacheConfigurator._autohsts_increasec
Cs�d}|j�dd|j�}|rFd}|D]"}t�||jj�|����r"|}q"|s`d�|j	�}t
�|��d�|�}|�dd�}|jj�
||�d�||j	�}	t�|	�|j|	7_|�|	�dS)	zJ
        Write the new HSTS max-age value to the VirtualHost file
        N�Headerz/(?:[ "]|^)(strict-transport-security)(?:[ "]|$)zUCertbot was unable to find the existing HSTS header from the VirtualHost at path {0}.�
"max-age={0}"zarg[3]zarg[4]z<Increasing HSTS max-age value to {0} for VirtualHost in {1}
)rr�r^re�searchr�r,r�rur�r	r{r5rLrsrtrQr)
r-r�r�Zhsts_dirpath�header_path�patr��err_msgZhsts_maxage�note_msgr/r/r0r��s,�

�
z"ApacheConfigurator._autohsts_writecCs4z|j�d�|_Wntk
r.t�|_YnXdS)zE
        Populates the AutoHSTS state from the pluginstorage
        �autohstsN)�storageZfetchrPrzrJrbr/r/r0�_autohsts_fetch_state�sz(ApacheConfigurator._autohsts_fetch_statecCs|j�d|j�|j��dS)zE
        Saves the state of AutoHSTS object to pluginstorage
        r�N)r�ZputrPrrbr/r/r0�_autohsts_save_state�sz'ApacheConfigurator._autohsts_save_statecCst|j�d|j|j��S)zz
        Searches AutoHSTS managed VirtualHosts that belong to the lineage.
        Matches the private key path.
        r�)�boolrr�r�r^)r-r��lineager/r/r0�_autohsts_vhost_in_lineage�s��z-ApacheConfigurator._autohsts_vhost_in_lineagecCs�d}|��|krt�d��d|jjkr0|�d�|jjdd|jd�}|sZ|j�|jdd�|�	t�
|j��}|j�dd	|�}|r�|jj�
t�d
d|d��|j�|dd
g�d|j}|j|7_|��t�|�d	S)a�Enables OCSP Stapling

        In OCSP, each client (e.g. browser) would have to query the
        OCSP Responder to validate that the site certificate was not revoked.

        Enabling OCSP Stapling, would allow the web-server to query the OCSP
        Responder, and staple its response to the offered certificate during
        TLS. i.e. clients would not have to query the OCSP responder.

        OCSP Stapling enablement on Apache implicitly depends on
        SSLCertificateChainFile being set by other code.

        .. note:: This function saves the configuration

        :param ssl_vhost: Destination of traffic, an ssl enabled vhost
        :type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`

        :param unused_options: Not currently used
        :type unused_options: Not Available

        :returns: Success, general_vhost (HTTP vhost)
        :rtype: (bool, :class:`~certbot_apache.obj.VirtualHost`)

        )rmr�r�z=Unable to set OCSP directives.
Apache version is below 2.3.3.rr ZSSLUseStaplingr��r�ZSSLStaplingCacheNrdrCrz-shmcb:/var/run/apache2/stapling_cache(128000)z,OCSP Stapling was enabled on SSL Vhost: %s.
)rrr	r{rr!r"r�r^r�r$rr�r�rrerfr	rQrrsr�)r-r.�unused_optionsZmin_apache_verZuse_stapling_aug_pathZssl_vhost_aug_pathZstapling_cache_aug_pathr
r/r/r0rX�s@�
�����z(ApacheConfigurator._enable_ocsp_staplingcCsnd|jjkr|�d�|�||�|j�|jdtj|�|jd||j	f7_|�
�t�d||j	�dS)a�Enables header that is identified by header_substring on ssl_vhost.

        If the header identified by header_substring is not already set,
        a new Header directive is placed in ssl_vhost's configuration with
        arguments from: constants.HTTP_HEADER[header_substring]

        .. note:: This function saves the configuration

        :param ssl_vhost: Destination of traffic, an ssl enabled vhost
        :type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`

        :param header_substring: string that uniquely identifies a header.
                e.g: Strict-Transport-Security, Upgrade-Insecure-Requests.
        :type str

        :returns: Success, general_vhost (HTTP vhost)
        :rtype: (bool, :class:`~certbot_apache.obj.VirtualHost`)

        :raises .errors.PluginError: If no viable HTTP host can be created or
            set with header header_substring.

        �headers_module�headersr�z$Adding %s header to ssl vhost in %s
z#Adding %s header to ssl vhost in %sN)
rr!r"�_verify_no_matching_http_headerr�r^r�HEADER_ARGSrQr�rrsr�)r-r.�header_substringr/r/r0rW�s
���z#ApacheConfigurator._set_http_headercCsZ|jjdd|jd�}|rVd|��}|D],}t�||jj�|����r(t�	d|��q(dS)a%Checks to see if an there is an existing Header directive that
        contains the string header_substring.

        :param ssl_vhost: vhost to check
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :param header_substring: string that uniquely identifies a header.
                e.g: Strict-Transport-Security, Upgrade-Insecure-Requests.
        :type str

        :returns: boolean
        :rtype: (bool)

        :raises errors.PluginEnhancementAlreadyPresent When header
                header_substring exists

        r�Nr�z(?:[ "]|^)(%s)(?:[ "]|$)zExisting %s header)
rr�r^r�rer�r�r,r	�PluginEnhancementAlreadyPresent)r-r.r�r�r�r�r/r/r0r�#s
��z2ApacheConfigurator._verify_no_matching_http_headerc
Csld|jjkr|�d�|�|�}|dkrnt�d�|�|�}|jD]}|jrB|�	|�rBt
�d��qB|�|�n�||j
dkr�t�d�dS|�|�|�|�r�t�d�|�|�s�|j�|jd	d
�|��}t|�D]D\}}dd�|�d
g}	|t|�dk�r|	��|j�|jd|	�q�|�|�|jd|j|jf7_|��|j
d�|�t�d|j|j�dS)a:Redirect all equivalent HTTP traffic to ssl_vhost.

        .. todo:: This enhancement should be rewritten and will
           unfortunately require lots of debugging by hand.

        Adds Redirect directive to the port 80 equivalent of ssl_vhost
        First the function attempts to find the vhost with equivalent
        ip addresses that serves on non-ssl ports
        The function then adds the directive

        .. note:: This function saves the configuration

        :param ssl_vhost: Destination of traffic, an ssl enabled vhost
        :type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`

        :param unused_options: Not currently used
        :type unused_options: Not Available

        :raises .errors.PluginError: If no viable HTTP host can be created or
            used for the redirect.

        Zrewrite_moduleZrewriteNzBDid not find http version of ssl virtual host attempting to createz�Unable to find corresponding HTTP vhost; Unable to create one as intended addresses conflict; Current configuration does not support automated redirectionrDz'Already enabled redirect for this vhostznAdded an HTTP->HTTPS rewrite in addition to other RewriteRules; you may wish to check for overall consistency.�
RewriteEnginer�z%{SERVER_NAME}z={0}z[OR]r<ZRewriteCondz*Redirecting host in %s to ssl vhost in %s
z*Redirecting vhost in %s to ssl vhost in %s)rr!r"�_get_http_vhostrsrtr�rSr�r�r	r{�_create_redirect_vhostrO�_verify_no_certbot_redirect�_is_rewrite_existsr��_is_rewrite_engine_onr�r^r�r[rur�rG�#_set_https_redirection_rewrite_rulerQr�rr@r�)
r-r.r�Z
general_vhZredirect_addrsr�r��idxr�rZr/r/r0rV?sH




�






��z#ApacheConfigurator._enable_redirectcCs:|��dkr"|j�|jdtj�n|j�|jdtj�dS)N�rmr��	�RewriteRule)rrrr�r^r�REWRITE_HTTPS_ARGS_WITH_END�REWRITE_HTTPS_ARGSrcr/r/r0r��s��z6ApacheConfigurator._set_https_redirection_rewrite_rulecs��jjdd|jd�}tt�}d}|D],}t�||�}|r$|�d�}||�|�q$|r�t	j
t	jg}|��D]`\}}	�fdd�|	D�}
|
t	j
kr��jj�|���|����t�d��|
|krjt�d��qjdS)	aVChecks to see if a redirect was already installed by certbot.

        Checks to see if virtualhost already contains a rewrite rule that is
        identical to Certbot's redirection rewrite rule.

        For graceful transition to new rewrite rules for HTTPS redireciton we
        delete certbot's old rewrite rules and set the new one instead.

        :param vhost: vhost to check
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :raises errors.PluginEnhancementAlreadyPresent: When the exact
                certbot redirection WriteRule exists in virtual host.
        r�Nr�z(.*directive\[\d+\]).*r<csg|]}�jj�|��qSr/rirrbr/r0r��szBApacheConfigurator._verify_no_certbot_redirect.<locals>.<listcomp>z'Certbot has already enabled redirection)rr�r^rr�rer��groupr�rr�r��itemsZOLD_REWRITE_HTTPS_ARGSr�rr�rr	r�)r-r��rewrite_pathZrewrite_args_dictr�r��mZdir_pathZ
redirect_argsZ
args_pathsZarg_valsr/rbr0r��s:�
�

��z.ApacheConfigurator._verify_no_certbot_redirectcCs|jjdd|jd�}t|�S)z�Checks if there exists a RewriteRule directive in vhost

        :param vhost: vhost to check
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :returns: True if a RewriteRule directive exists.
        :rtype: bool

        r�Nr�)rr�r^r�)r-r�r�r/r/r0r��s
�z%ApacheConfigurator._is_rewrite_existscCsB|jjdd|jd�}|r>|D] }d|��kr|j�|�SqdS)z�Checks if a RewriteEngine directive is on

        :param vhost: vhost to check
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        r�r�r�r�F)rr�r^r�r�)r-r�Zrewrite_engine_path_listZre_pathr/r/r0r��s
�z(ApacheConfigurator._is_rewrite_engine_oncCsr|�|�}|�||�}|jj��|�t�|�|���}|j�	|�|j
d�|�|jd|j
|j
f7_dS)a/Creates an http_vhost specifically to redirect for the ssl_vhost.

        :param ssl_vhost: ssl vhost
        :type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`

        :returns: tuple of the form
            (`success`, :class:`~certbot_apache.obj.VirtualHost`)
        :rtype: tuple

        rDz=Created a port 80 vhost, %s, for redirection to ssl vhost %s
N)�_get_redirect_config_str�_write_out_redirectrr�r�r�rr$rSr�rOr@rQr�)r-r.�text�redirect_filepathrr/r/r0r��s

�z)ApacheConfigurator._create_redirect_vhostcCs�d}d}|jdk	rd|j}|jr2dd�|j�}g}|��dkrJtj}ntj}dd�dd�|�|�D��||d�|�|�d	�fS)
NrCzServerName zServerAlias rr�z�<VirtualHost %s>
%s 
%s 
ServerSignature Off

RewriteEngine On
RewriteRule %s

ErrorLog %s/redirect.error.log
LogLevel warn
</VirtualHost>
css|]}t|�VqdSrfrgr�r/r/r0rls�z>ApacheConfigurator._get_redirect_config_str.<locals>.<genexpr>r)	r�r�r_rrrr�r�r�r1)r-r.r�r�Zrewrite_rule_argsr/r/r0r�s(


���z+ApacheConfigurator._get_redirect_config_strc	Cs�d}|jdk	r2t|j�dt|�dkr2d|j}tj�|�d�|�}|j�d|�t|d��}|�	|�W5QRX|j
�|�s�|j
�|�t
�d|�|S)	Nzle-redirect.conf�r<zle-redirect-%s.confrF�wzCreated redirect file: %s)r�r�rr^r_r1r=r>rArBrrCr'rsr�)r-r.r�Zredirect_filenamer�Z
redirect_filer/r/r0r�"s

�z&ApacheConfigurator._write_out_redirectcCs\|jr|jSdd�|jD�}|D]}|�|�r |Sq |D]}|j|dd�r<|Sq<dS)z*Find appropriate HTTP vhost for ssl_vhost.cSsg|]}|js|�qSr/ryr�r/r/r0r�Esz6ApacheConfigurator._get_http_vhost.<locals>.<listcomp>T)ZgenericN)r)rSZsame_server)r-r.Zcandidate_http_vhsZhttp_vhr/r/r0r�@s�


z"ApacheConfigurator._get_http_vhostcCs&t�}|jD]}|�|�|��q|S)z�Return all addrs of vhost with the port replaced with the specified.

        :param obj.VirtualHost ssl_vhost: Original Vhost
        :param str port: Desired port for new addresses

        :returns: `set` of :class:`~obj.Addr`

        )rLr�r@r_)r-r�r�Z	redirectsr�r/r/r0r�Ts	
z&ApacheConfigurator._get_proposed_addrscCs\|jr
dS|j�|j�sXt�d|j�|jd|j7_|j�|jjd|j�d|_dS)aEnables an available site, Apache reload required.

        .. note:: Does not make sure that the site correctly works or that all
                  modules are enabled appropriately.
        .. note:: The distribution specific override replaces functionality
                  of this method where available.

        :param vhost: vhost to enable
        :type vhost: :class:`~certbot_apache.obj.VirtualHost`

        :raises .errors.NotSupportedError: If filesystem layout is not
            supported.

        Nz8Enabling site %s by adding Include to root configurationzEnabled site %s
r9T)	r�rr�r�rsr�rQZadd_includerrcr/r/r0r�cs�zApacheConfigurator.enable_sitecCsd}t�|�|���dS)a�Enables module in Apache.

        Both enables and reloads Apache so module is active.

        :param str mod_name: Name of the module to enable. (e.g. 'ssl')
        :param bool temp: Whether or not this is a temporary action.

        .. note:: The distribution specific override replaces functionality
                  of this method where available.

        :raises .errors.MisconfigurationError: We cannot enable modules in
            generic fashion.

        z�Apache needs to have module  "{0}" active for the requested installation options. Unfortunately Certbot is unable to install or enable it for you. Please install the module, and run Certbot again.N)r	�MisconfigurationErrorru)r-�mod_namer�Zmod_messager/r/r0r"~szApacheConfigurator.enable_modcCs|��|��dS)z�Runs a config test and reloads the Apache server.

        :raises .errors.MisconfigurationError: If either the config test
            or reload fails.

        N)rq�_reloadrbr/r/r0�restart�szApacheConfigurator.restartc
Cs�zt�|�d��Wn�tjk
r�}z�t�d|�d��|�d�}|r�t�d|�zt�|�d��WWY�HdStjk
r�}zt|�}W5d}~XYq�Xnt|�}t�	|��W5d}~XYnXdS)zdReloads the Apache server.

        :raises .errors.MisconfigurationError: If reload fails

        r"z!Unable to restart apache using %sZrestart_cmd_altz&Trying alternative restart command: %sN)
r�
run_scriptr1r	�SubprocessErrorrsr�rtrhr�)r-�errZalt_restartZsecerrr�r/r/r0r��s(�
��zApacheConfigurator._reloadc
CsLzt�|�d��Wn2tjk
rF}zt�t|���W5d}~XYnXdS)z|Check the configuration of Apache for errors.

        :raises .errors.MisconfigurationError: If config_test fails

        r#N)rr�r1r	r�r�rh)r-r�r/r/r0rq�szApacheConfigurator.config_testc	Cs�zt�|�d��\}}Wn*tjk
rBt�d|�d���YnXt�dtj�}|�	|�}t
|�dkrrt�d��tdd�|d�d	�D��S)
z�Return version of Apache Server.

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

        :returns: version
        :rtype: tuple

        :raises .PluginError: if unable to find Apache version

        r!zUnable to run %s -vzApache/([0-9\.]*)r<zUnable to find Apache versioncSsg|]}t|��qSr/)�intrir/r/r0r��sz2ApacheConfigurator.get_version.<locals>.<listcomp>rre)
rr�r1r	r�r{re�compile�
IGNORECASE�findallr��tupler�)r-�stdoutr2Zregexrjr/r/r0rr�s��


zApacheConfigurator.get_versioncCs,djtj|jjdd�dd�|jD��d�S)z3Human-readable string to help understand the modulez_Configures Apache to authenticate and install HTTPS.{0}Server root: {root}{0}Version: {version}�rootrecss|]}t|�VqdSrfrgrir/r/r0rl�sz/ApacheConfigurator.more_info.<locals>.<genexpr>)r�rB)rur�lineseprrr_rBrbr/r/r0�	more_info�s
��zApacheConfigurator.more_infocCstjgS)z%Return list of challenge preferences.)rZHTTP01)r-Z
unused_domainr/r/r0�get_chall_pref�sz!ApacheConfigurator.get_chall_prefcCsr|j�|�dgt|�}t�|�}t|�D]\}}|�||�q,|��}|rn|��t	�
d�|�|||�|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.

        Nr�)rMr�r�rZApacheHttp01r[Z	add_chall�performr�r��sleep�_update_responses)r-�achalls�	responsesZ	http_doerrkZachallZ
http_responser/r/r0r��s

zApacheConfigurator.performcCs$t|�D]\}}|||j|<qdSrf)r[�indices)r-r�Zchall_responseZ
chall_doerrkZrespr/r/r0r�	sz$ApacheConfigurator._update_responsescCs0|j�|�|js,|��|��|j��dS)zRevert all challenges.N)rM�difference_updater�r�rZ
reset_modules)r-r�r/r/r0�cleanup	s
zApacheConfigurator.cleanupcCst�|||�d�tj�S)zICopy Certbot's SSL options file into the system's config dir if required.r*)rZinstall_version_controlled_filer1rZALL_SSL_OPTIONS_HASHES)r-Zoptions_sslZoptions_ssl_digestr/r/r0ry 	s�z+ApacheConfigurator.install_ssl_options_confcCs�|��g}|D]�}|j|dd�}dd�|D�}|sVd}|�|�}t�|�t�|��|D]X}	z|�|	�|�|	�WqZtj	k
r�|	|kr�YqZd}t�	|�||	j
���YqZXqZq|r�d}
|�|
�t�|
�|�
�|��dS)	a$
        Enable the AutoHSTS enhancement for defined domains

        :param _unused_lineage: Certificate lineage object, unused
        :type _unused_lineage: certbot.storage.RenewableCert

        :param domains: List of domains in certificate to enhance
        :type domains: str
        FrxcSsg|]}|jr|�qSr/ryr�r/r/r0r�9	sz6ApacheConfigurator.enable_autohsts.<locals>.<listcomp>z`Certbot was not able to find SSL VirtualHost for a domain {0} for enabling AutoHSTS enhancement.z_VirtualHost for domain {0} in file {1} has a String-Transport-Security header present, exiting.zEnabling AutoHSTSN)r�r�rursr�r	r{�_enable_autohsts_domainr�r�r�rr�r�r�)r-Z_unused_lineageZdomainsrO�dr|rSr}r
r�r�r/r/r0�enable_autohsts)	s6



�

z"ApacheConfigurator.enable_autohstscCs�|�|d�d|jjkr"|�d�tjddd�}tjd}|�d�|��|�	|�}|j
d�||j�7_
|j�|j
d	|�d
�||j�}|j
|7_
dt��d�|j|<dS)aDo the initial AutoHSTS deployment to a vhost

        :param ssl_vhost: The VirtualHost object to deploy the AutoHSTS
        :type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost` or None

        :raises errors.PluginEnhancementAlreadyPresent: When already enhanced

        zStrict-Transport-Securityr�r�Nr�rr�z+Adding unique ID {0} to VirtualHost in {1}
r�zXAdding gradually increasing HSTS header with initial value of {0} to VirtualHost in {1}
r)r�rr!r"rr�r�r�rurorQr�r�r^r�rP)r-r.Zhsts_headerZinitial_maxageZuniq_idr�r/r/r0r�U	s(
�



��z*ApacheConfigurator._enable_autohsts_domainc		Cs|��|jsdSt��}d}t|j���D]�\}}|dtj|krHq,|dd}|ttj�kr,|j	sp|�
�z|�|�}Wn:tj
k
r�d�|�}t�|�|j�|�Yq,YnX|�|||�d�|�}|j|7_d}q,|r�|�d	�|��|��dS)
z�
        Increase the AutoHSTS values of VirtualHosts that the user has enabled
        this enhancement for.

        :param _unused_domain: Not currently used
        :type _unused_domain: Not Available

        NFr�r�r<zOCould not find VirtualHost with ID {0}, disabling AutoHSTS for this VirtualHostz9Increasing HSTS max-age value for VirtualHost with id {0}TzIncreased HSTS max-age values)r�rPr�r�r�rZ
AUTOHSTS_FREQr�r�rRr|rmr	r{rursr�rGr�rQrr�r�)	r-Z_unused_domainZcurtime�save_and_restartrlr`r�r�r
r/r/r0�update_autohstsw	s>	�

�
z"ApacheConfigurator.update_autohstsc		Cs6|��|jsdSg}g}t|j���D]�\}}|ddttj�kr(z|�|�}Wn:tj	k
r�d�
|�}t�|�|j�
|�Yq(YnX|�||�r(|�|�|�|�q(d}|D]>}|�|tj�d�
|j�}t�|�|j|d7_d}q�|�r|�d	�|��|D]}|j�
|��q|��dS)
z�
        Checks if autohsts vhost has reached maximum auto-increased value
        and changes the HSTS max-age to a high value.

        :param lineage: Certificate lineage object
        :type lineage: certbot.storage.RenewableCert
        Nr�r<zLVirtualHost with id {} was not found, unable to make HSTS max-age permanent.FzRStrict-Transport-Security max-age value for VirtualHost in {0} was made permanent.r;TzMade HSTS max-age permanent)r�rPr�r�r�rr�rmr	r{rursr�rGr�r�r�ZAUTOHSTS_PERMANENTr�rtrQrr�r�)	r-r�rSZaffected_idsrlr`r�r
r�r/r/r0�deploy_autohsts�	sD�


�

z"ApacheConfigurator.deploy_autohsts)NF)r<)NN)T)T)T)F)r�)NT)F)F)N)r�)F)o�__name__�
__module__�__qualname__�__doc__Zdescriptionrr>r,rJ�
pkg_resourcesZresource_filenamer6r1r8�classmethodrArI�propertyrcrdr|rrvr�r�rprwr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rxrrr�rrrrr
r�r&r#r:r%r@r?rYr(r�rarbr�r�rhr*rmrkror$rwr~r�r�r�r�r�rXrWr�rVr�r�r�r�r�r�r�r�r�r�r"r�r�rqrrr�r�r�r�r�ryr�r�r�r��
__classcell__r/r/r\r0rGs����
&"

4
	�


,L
(


=!,5

2!N!0@

#
)	
>(Q0!



!
	,".r)8r�rTr�Zloggingrer�r��collectionsrr�r�Zzope.componentr�Zzope.interfaceZacmerZacme.magic_typingrrrrrZcertbotr	r
rZcertbot.achallengesrZcertbot.compatr
rZcertbot.pluginsrZcertbot.plugins.utilrZcertbot.plugins.enhancementsrrrrrrrrZ	getLoggerr�rsZ	interfaceZimplementerZIAuthenticatorZ
IInstallerZproviderZIPluginFactoryZ	Installerr�registerr/r/r/r0�<module>sh
 "