a
    `                     @   s0  d Z ddlZddlZddlZddlmZ ddlZddlZddlZ	ddl
mZ ddl
mZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ eeZereejeej f ZG dd de Z!e	j"#ej$e	j"%ej&G dd dej'Z(dd Z)dS )zStandalone Authenticator.    N)errno)
challenges)
standalone)DefaultDict)Dict)Set)Tuple)TYPE_CHECKING)achallenges)errors)
interfaces)commonc                   @   s2   e Zd ZdZdd ZdddZdd Zd	d
 ZdS )ServerManagera  Standalone servers manager.

    Manager for `ACMEServer` and `ACMETLSServer` instances.

    `certs` and `http_01_resources` correspond to
    `acme.crypto_util.SSLSocket.certs` and
    `acme.crypto_util.SSLSocket.http_01_resources` respectively. All
    created servers share the same certificates and resources, so if
    you're running both TLS and non-TLS instances, HTTP01 handlers
    will serve the same URLs!

    c                 C   s   i | _ || _|| _d S N)
_instancescertshttp_01_resources)selfr   r    r   F/usr/lib/python3/dist-packages/certbot/_internal/plugins/standalone.py__init__-   s    zServerManager.__init__ c              
   C   s   |t jksJ || jv r"| j| S ||f}zt|| j}W n2 tjyn } zt	||W Y d}~n
d}~0 0 |
  | d d }|| j|< |S )a  Run ACME server on specified ``port``.

        This method is idempotent, i.e. all calls with the same pair of
        ``(port, challenge_type)`` will reuse the same server.

        :param int port: Port to run the server on.
        :param challenge_type: Subclass of `acme.challenges.Challenge`,
            currently only `acme.challenge.HTTP01`.
        :param str listenaddr: (optional) The address to listen on. Defaults to all addrs.

        :returns: DualNetworkedServers instance.
        :rtype: ACMEServerMixin

        Nr      )r   HTTP01r   acme_standaloneZHTTP01DualNetworkedServersr   socketerrorr   StandaloneBindErrorZserve_forevergetsocknames)r   portZchallenge_type
listenaddrZaddressserversr   Z	real_portr   r   r   run2   s    

"
zServerManager.runc                 C   sF   | j | }| D ]}tjdg|dd R   q|  | j |= dS )zWStop ACME server running on the specified ``port``.

        :param int port:

        zStopping server at %s:%d...N   )r   r   loggerdebugZshutdown_and_server_close)r   r   instanceZsocknamer   r   r   stopT   s    


zServerManager.stopc                 C   s
   | j  S )zReturn all running instances.

        Once the server is stopped using `stop`, it will not be
        returned.

        :returns: Mapping from ``port`` to ``servers``.
        :rtype: tuple

        )r   copyr   r   r   r   runninga   s    
zServerManager.runningN)r   )__name__
__module____qualname____doc__r   r"   r'   r*   r   r   r   r   r       s
   
"r   c                       sp   e Zd ZdZdZ fddZedd Zdd Zd	d
 Z	dd Z
dd Zdd Zdd Zdd Zdd Z  ZS )Authenticatora  Standalone Authenticator.

    This authenticator creates its own ephemeral TCP listener on the
    necessary port in order to respond to incoming http-01
    challenges from the certificate authority. Therefore, it does not
    rely on any existing server program.
    zSpin up a temporary webserverc                    sD   t t| j|i | tt| _i | _t | _t	| j| j| _
d S r   )superr/   r   collectionsdefaultdictsetservedr   r   r   r!   )r   argskwargs	__class__r   r   r   {   s
    zAuthenticator.__init__c                 C   s   d S r   r   )clsaddr   r   r   add_parser_arguments   s    z"Authenticator.add_parser_argumentsc                 C   s   dS )NzThis authenticator creates its own ephemeral TCP listener on the necessary port in order to respond to incoming http-01 challenges from the certificate authority. Therefore, it does not rely on any existing server program.r   r)   r   r   r   	more_info   s    zAuthenticator.more_infoc                 C   s   d S r   r   r)   r   r   r   prepare   s    zAuthenticator.preparec                 C   s   t jgS r   )r   r   )r   Zdomainr   r   r   get_chall_pref   s    zAuthenticator.get_chall_prefc                    s    fdd|D S )Nc                    s   g | ]}  |qS r   )_try_perform_single).0achallr)   r   r   
<listcomp>       z)Authenticator.perform.<locals>.<listcomp>r   )r   achallsr   r)   r   perform   s    zAuthenticator.performc              
   C   sB   z|  |W S  tjy: } zt| W Y d }~q d }~0 0 q d S r   )_perform_singler   r   _handle_perform_error)r   rA   r   r   r   r   r?      s    z!Authenticator._try_perform_singlec                 C   s"   |  |\}}| j| | |S r   )_perform_http_01r4   r:   )r   rA   r!   responser   r   r   rF      s    zAuthenticator._perform_singlec                 C   sX   | j j}| j j}| jj|tj|d}| \}}tj	j
|j||d}| j| ||fS )N)r    )challrI   
validation)ZconfigZhttp01_portZhttp01_addressr!   r"   r   r   Zresponse_and_validationr   ZHTTP01RequestHandlerZHTTP01ResourcerJ   r   r:   )r   rA   r   Zaddrr!   rI   rK   resourcer   r   r   rH      s    zAuthenticator._perform_http_01c                 C   sd   | j  D ]$\}}|D ]}||v r|| qq
t| j D ]\}}| j | s@| j| q@d S r   )r4   itemsremovesixZ	iteritemsr!   r*   r'   )r   rD   Zunused_serversZserver_achallsrA   r   r!   r   r   r   cleanup   s    
zAuthenticator.cleanup)r+   r,   r-   r.   Zdescriptionr   classmethodr;   r<   r=   r>   rE   r?   rF   rH   rP   __classcell__r   r   r7   r   r/   n   s   

r/   c                 C   sr   | j jtjkr td| j| j jtjkrjt	j
tj}d| j}|j|dddd}|snt|n| d S )NzCould not bind TCP port {0} because you don't have the appropriate permissions (for example, you aren't running this program as root).zCould not bind TCP port {0} because it is already in use by another process on this system (such as a web server). Please stop the program in question and then try again.ZRetryZCancelF)default)Zsocket_errorr   socket_errorsZEACCESr   ZPluginErrorformatr   Z
EADDRINUSEzopeZ	componentZ
getUtilityr   ZIDisplayZyesno)r   ZdisplaymsgZshould_retryr   r   r   rG      s$    rG   )*r.   r1   Zloggingr   r   rT   ZOpenSSLrO   Zzope.interfacerV   Zacmer   r   r   Zacme.magic_typingr   r   r   r   r	   Zcertbotr
   r   r   Zcertbot.pluginsr   Z	getLoggerr+   r$   ZBaseDualNetworkedServersZ"KeyAuthorizationAnnotatedChallengeZ
ServedTypeobjectr   Z	interfaceZimplementerZIAuthenticatorZproviderZIPluginFactoryZPluginr/   rG   r   r   r   r   <module>   s<   
NO