U
    ]                     @   s  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mZmZmZ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 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ListType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   </usr/lib/python3/dist-packages/certbot/plugins/standalone.py__init__,   s    zServerManager.__init__ c              
   C   s   |t jkst|| jkr"| j| S ||f}zt|| j}W n0 tjk
rl } zt	
||W 5 d}~X Y nX |  | 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   HTTP01AssertionErrorr   acme_standaloneZHTTP01DualNetworkedServersr   socketerrorr   StandaloneBindErrorZserve_forevergetsocknames)r   portZchallenge_type
listenaddrZaddressserversr   Z	real_portr   r   r   run1   s    

 
zServerManager.runc                 C   sB   | j | }| D ]}tjd|dd   q|  | j |= dS )zWStop ACME server running on the specified ``port``.

        :param int port:

        Stopping server at %s:%d...N   )r&   )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                    s@   t t| j|| tt| _i | _t | _t	| j| j| _
d S r   )superr3   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>   s     z)Authenticator.perform.<locals>.<listcomp>r   )r   achallsr   r-   r   perform   s    zAuthenticator.performc              
   C   s@   z|  |W S  tjk
r8 } zt| W 5 d }~X Y q X q d S r   )_perform_singler   r    _handle_perform_error)r   rE   r   r   r   r   rC      s    z!Authenticator._try_perform_singlec                 C   s"   |  |\}}| j| | |S r   )_perform_http_01r8   r>   )r   rE   r$   responser   r   r   rI      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#   )challrL   
validation)ZconfigZhttp01_portZhttp01_addressr$   r%   r   r   Zresponse_and_validationr   ZHTTP01RequestHandlerZHTTP01ResourcerM   r   r>   )r   rE   r"   Zaddrr$   rL   rN   resourcer   r   r   rK      s      zAuthenticator._perform_http_01c                 C   sd   | j  D ]$\}}|D ]}||kr|| qq
t| j D ]\}}| j | s@| j| q@d S r   )r8   itemsremovesixZ	iteritemsr$   r.   r+   )r   rG   Zunused_serversZserver_achallsrE   r"   r$   r   r   r   cleanup   s    
zAuthenticator.cleanup)r/   r0   r1   r2   Zdescriptionr   classmethodr?   r@   rA   rB   rH   rC   rI   rK   rS   __classcell__r   r   r;   r   r3   n   s   

r3   c                 C   st   | j jtjkr"td| jnN| j jtjkrlt	j
tj}d| j}|j|dddd}|spt|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   rJ      s&     rJ   ),r2   r5   Zloggingr   r   rW   ZOpenSSLrR   Zzope.interfacerY   Zacmer   r   r   Zacme.magic_typingr   r   r   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Pluginr3   rJ   r   r   r   r   <module>   s4   $
OO