U
     T‚g÷Ú  ã                   @   sˆ  d 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mZ ddl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mZmZmZ ddl m!Z!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z' ddl(m)Z)m*Z* ddl+m,Z,m-Z-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z= e;dƒ�r$ddl>m?Z? ddl@mAZAmBZB ddlCmDZDmEZE ddlFmGZGmHZHmIZImJZJmKZKmLZL ddlMmNZN ddlOmPZP dd lQmRZR dd!lSmTZT dd"lUmVZV dd#lWmXZX dd$lYmZZZ dd%l[m\Z\ dd&l]m^Z^m_Z_m`Z`maZa n(d'ZbecZVecZ\ecZTecZXecZRecZPecZEecZBecZ?dd(ldmeZemfZf G d)d*„ d*eeƒZgG d+d,„ d,eRƒZhG d-d.„ d.eRƒZiG d/d0„ d0eRƒZjG d1d2„ d2ƒZkG d3d4„ d4e)ƒZlG d5d6„ d6ƒZmG d7d8„ d8e\ƒZnG d9d:„ d:eVƒZoe
e&ƒG d;d<„ d<ƒƒZpe
e'ƒG d=d>„ d>ƒƒZqG d?d@„ d@ƒZrG dAdB„ dBe=erƒZsG dCdD„ dDe=erƒZtG dEdF„ dFe=ƒZuG dGdH„ dHeƒZvG dIdJ„ dJƒZwG dKdL„ dLe=ƒZxdS )Mz'
Tests for L{twisted.conch.endpoints}.
é    N)ÚBytesIO)Úpack)ÚIO)Úimplementer)ÚverifyClassÚverifyObject)Ú
ConchErrorÚHostKeyChangedÚUserRejectedKey)Ú
IConchUser)Ú'InMemoryUsernamePasswordDatabaseDontUse)ÚPortal)ÚIPv4Address)ÚCancelledErrorÚDeferredÚfailÚsucceed)ÚConnectingCancelledErrorÚConnectionDoneÚConnectionRefusedErrorÚProcessTerminated)ÚIAddressÚIStreamClientEndpoint)ÚFactoryÚProtocol)ÚEventLoggingObserverÚMemoryReactorClockÚStringTransport)ÚLogLevelÚglobalLogPublisher)ÚnetworkString)ÚFailure)ÚFilePath)Úmsg)ÚrequireModule)ÚTestCaseZcryptography)Ú	ConchUser)ÚInMemorySSHKeyDBÚSSHPublicKeyChecker)Ú	ConsoleUIÚKnownHostsFile)ÚAuthenticationFailedÚSSHCommandAddressÚSSHCommandClientEndpointÚ_ExistingConnectionHelperÚ_ISSHConnectionCreatorÚ_NewConnectionHelper)Úcommon)ÚSSHAgentServer)Ú
SSHChannel)ÚSSHConnection)Ú
SSHFactory)ÚKey)ÚSSHClientTransport)ÚSSHUserAuthServer)ÚprivateDSA_opensshÚprivateRSA_opensshÚ privateRSA_openssh_encrypted_aesÚpublicRSA_opensshzcan't run w/o cryptography)ÚFakeTransportÚconnectc                   @   s   e Zd ZdZdZdd„ ZdS )ÚAbortableFakeTransportzC
    A L{FakeTransport} with added C{abortConnection} support.
    Fc                 C   s
   d| _ dS )z}
        Abort the connection in a fake manner.

        This should really be implemented in the underlying module.
        TN©Úaborted©Úself© rD   úE/tmp/pip-unpacked-wheel-1_7di8ic/twisted/conch/test/test_endpoints.pyÚabortConnection]   s    z&AbortableFakeTransport.abortConnectionN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rA   rF   rD   rD   rD   rE   r?   V   s   r?   c                   @   s   e Zd ZdZdd„ ZdS )ÚBrokenExecSessionzO
    L{BrokenExecSession} is a session on which exec requests always fail.
    c                 C   s   dS )zÈ
        Fail all exec requests.

        @param data: Information about what is being executed.
        @type data: L{bytes}

        @return: C{0} to indicate failure
        @rtype: L{int}
        r   rD   ©rC   ÚdatarD   rD   rE   Úrequest_execk   s    
zBrokenExecSession.request_execN©rG   rH   rI   rJ   rN   rD   rD   rD   rE   rK   f   s   rK   c                   @   s   e Zd ZdZdd„ ZdS )ÚWorkingExecSessionzS
    L{WorkingExecSession} is a session on which exec requests always succeed.
    c                 C   s   dS )zË
        Succeed all exec requests.

        @param data: Information about what is being executed.
        @type data: L{bytes}

        @return: C{1} to indicate success
        @rtype: L{int}
        é   rD   rL   rD   rD   rE   rN   }   s    
zWorkingExecSession.request_execNrO   rD   rD   rD   rE   rP   x   s   rP   c                   @   s   e Zd ZdZdd„ ZdS )ÚUnsatisfiedExecSessionz‰
    L{UnsatisfiedExecSession} is a session on which exec requests are always
    delayed indefinitely, never succeeding or failing.
    c                 C   s   t ƒ S )zç
        Delay all exec requests indefinitely.

        @param data: Information about what is being executed.
        @type data: L{bytes}

        @return: A L{Deferred} which will never fire.
        @rtype: L{Deferred}
        )r   rL   rD   rD   rE   rN   �   s    
z#UnsatisfiedExecSession.request_execNrO   rD   rD   rD   rE   rR   Š   s   rR   c                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚTrivialRealmc                 C   s
   i | _ d S ©N)ÚchannelLookuprB   rD   rD   rE   Ú__init__ž   s    zTrivialRealm.__init__c                 G   s   t ƒ }| j|_t|dd„ fS )Nc                   S   s   d S rT   rD   rD   rD   rD   rE   Ú<lambda>¤   ó    z,TrivialRealm.requestAvatar.<locals>.<lambda>)r&   rU   r   )rC   ZavatarIdZmindZ
interfacesZavatarrD   rD   rE   ÚrequestAvatar¡   s    zTrivialRealm.requestAvatarN)rG   rH   rI   rV   rY   rD   rD   rD   rE   rS   �   s   rS   c                   @   s   e Zd ZdZdd„ ZdS )ÚAddressSpyFactoryNc                 C   s   || _ t | |¡S rT   )Úaddressr   ÚbuildProtocol)rC   r[   rD   rD   rE   r\   ª   s    zAddressSpyFactory.buildProtocol)rG   rH   rI   r[   r\   rD   rD   rD   rE   rZ   §   s   rZ   c                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚFixedResponseUIc                 C   s
   || _ d S rT   ©Úresult)rC   r_   rD   rD   rE   rV   °   s    zFixedResponseUI.__init__c                 C   s
   t | jƒS rT   )r   r_   ©rC   ÚtextrD   rD   rE   Úprompt³   s    zFixedResponseUI.promptc                 C   s   d S rT   rD   r`   rD   rD   rE   Úwarn¶   s    zFixedResponseUI.warnN)rG   rH   rI   rV   rb   rc   rD   rD   rD   rE   r]   ¯   s   r]   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )ÚFakeClockSSHUserAuthServerc                 C   s
   | j jjS )zy
        Use the C{attemptsBeforeDisconnect} value defined by the factory to make
        it easier to override.
        )Ú	transportÚfactoryÚattemptsBeforeDisconnectrB   rD   rD   rE   rg   ¼   s    z3FakeClockSSHUserAuthServer.attemptsBeforeDisconnectc                 C   s
   | j jjS )zÈ
        Use the reactor defined by the factory, rather than the default global
        reactor, to simplify testing (by allowing an alternate implementation
        to be supplied by tests).
        )re   rf   ÚreactorrB   rD   rD   rE   ÚclockÄ   s    z FakeClockSSHUserAuthServer.clockN)rG   rH   rI   Úpropertyrg   ri   rD   rD   rD   rE   rd   º   s   
rd   c                   @   s2   e Zd Zedd„ ƒZedd„ ƒZeedœZdZ	dS )ÚCommandFactoryc                 C   s   dt jtd�iS ©Nó   ssh-rsa)rM   )r6   Ú
fromStringr<   rB   rD   rD   rE   Ú
publicKeysÏ   s    zCommandFactory.publicKeysc                 C   s   dt jtd�iS rl   )r6   rn   r:   rB   rD   rD   rE   ÚprivateKeysÓ   s    zCommandFactory.privateKeys)s   ssh-userauths   ssh-connectionr   N)
rG   rH   rI   rj   ro   rp   rd   r4   Zservicesrg   rD   rD   rD   rE   rk   Î   s   

þ	rk   c                   @   s   e Zd ZdS )ÚMemoryAddressN)rG   rH   rI   rD   rD   rD   rE   rq   ã   s   rq   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚSingleUseMemoryEndpointa]  
    L{SingleUseMemoryEndpoint} is a client endpoint which allows one connection
    to be set up and then exposes an API for moving around bytes related to
    that connection.

    @ivar pump: L{None} until a connection is attempted, then a L{IOPump}
        instance associated with the protocol which is connected.
    @type pump: L{IOPump}
    c                 C   s   d| _ || _dS )z˜
        @param server: An L{IProtocol} provider to which the client will be
            connected.
        @type server: L{IProtocol} provider
        N)ÚpumpÚ_server)rC   ÚserverrD   rD   rE   rV   ô   s    z SingleUseMemoryEndpoint.__init__c                 C   sn   | j d k	rtdƒ‚z| tƒ ¡}W n tk
r<   tƒ  Y S X t| jt| jdd�|t|dd�ƒ| _ t	|ƒS d S )Nz(SingleUseMemoryEndpoint was already usedT©ÚisServerF)
rs   Ú	Exceptionr\   rq   ÚBaseExceptionr   r>   rt   r?   r   )rC   rf   ÚprotocolrD   rD   rE   r>   ý   s    

üzSingleUseMemoryEndpoint.connectN)rG   rH   rI   rJ   rV   r>   rD   rD   rD   rE   rr   è   s   
	rr   c                   @   sª   e Zd Z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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#d$„Zd%d&„ Zd'd(„ Zd)S )+Ú"SSHCommandClientEndpointTestsMixinaà  
    Tests for L{SSHCommandClientEndpoint}, an L{IStreamClientEndpoint}
    implementations which connects a protocol with the stdin and stdout of a
    command running in an SSH session.

    These tests apply to L{SSHCommandClientEndpoint} whether it is constructed
    using L{SSHCommandClientEndpoint.existingConnection} or
    L{SSHCommandClientEndpoint.newConnection}.

    Subclasses must override L{create}, L{assertClientTransportState}, and
    L{finishConnection}.
    c                 C   s°   d| _ d| _d| _d| _tƒ | _tƒ | _t| jƒ| _	t
ƒ | _| j | j| j¡ | j	 | j¡ tƒ | _| j| j_| j	| j_	| j ¡  |  | jj¡ tdddƒ| _tddd	ƒ| _d S )
Ns   ssh.example.comi&¤  s   users   passwordZTCPz10.0.0.1i90  z192.168.100.200i1Ô  )ÚhostnameÚportÚuserÚpasswordr   rh   rS   Úrealmr   Úportalr   ZpasswdDBZaddUserÚregisterCheckerrk   rf   ZdoStartÚ
addCleanupZdoStopr   ÚclientAddressÚserverAddressrB   rD   rD   rE   ÚsetUp  s"    


z(SSHCommandClientEndpointTestsMixin.setUpc                 C   s   t | jj›d�ƒ‚dS )z£
        Create and return a new L{SSHCommandClientEndpoint} to be tested.
        Override this to implement creation in an interesting way the endpoint.
        z did not implement createN©ÚNotImplementedErrorÚ	__class__rG   rB   rD   rD   rE   Úcreate1  s    ÿz)SSHCommandClientEndpointTestsMixin.createc                 C   s   t d| jjf ƒ‚dS )a™  
        Make an assertion about the connectedness of the given protocol's
        transport.  Override this to implement either a check for the
        connection still being open or having been closed as appropriate.

        @param client: The client whose state is being checked.

        @param immediateClose: Boolean indicating whether the connection was
            closed immediately or not.
        z/%r did not implement assertClientTransportStateNr‡   ©rC   ÚclientZimmediateCloserD   rD   rE   ÚassertClientTransportState:  s
    ÿÿz=SSHCommandClientEndpointTestsMixin.assertClientTransportStatec                 C   s   t | jj›d�ƒ‚dS )zˆ
        Do any remaining work necessary to complete an in-memory connection
        attempted initiated using C{self.reactor}.
        z# did not implement finishConnectionNr‡   rB   rD   rD   rE   ÚfinishConnectionJ  s    ÿz3SSHCommandClientEndpointTestsMixin.finishConnectionc                 C   sT   |  d¡}|  d¡}t|d| j| jd�}t|d| j| jd�}t||||ƒ}|||fS )aw  
        Set up an in-memory connection between protocols created by
        C{serverFactory} and C{clientFactory}.

        @return: A three-tuple.  The first element is the protocol created by
            C{serverFactory}.  The second element is the protocol created by
            C{clientFactory}.  The third element is the L{IOPump} connecting
            them.
        NF)rw   ZhostAddressZpeerAddressT)r\   r?   r„   r…   r>   )rC   ZserverFactoryZclientFactoryZclientProtocolZserverProtocolZclientTransportZserverTransportrs   rD   rD   rE   ÚconnectedServerAndClientS  s     


üüz;SSHCommandClientEndpointTestsMixin.connectedServerAndClientc           	      C   sš   |   ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  t¡}|  d|d j	j
|d j	j	f¡ |  dt|ƒ¡ |  |¡}| t¡ |  d|j	j	¡ |  |d¡ dS )zå
        If a channel cannot be opened on the authenticated SSH connection, the
        L{Deferred} returned by L{SSHCommandClientEndpoint.connect} fires with
        a L{Failure} wrapping the reason given by the server.
        úunknown channelr   rQ   ó   unknown channelFN)rŠ   r   r   rz   r>   rŽ   ÚflushLoggedErrorsr   ÚassertInÚvaluerM   ÚassertEqualÚlenÚfailureResultOfÚtrapr�   )	rC   Úendpointrf   Ú	connectedru   rŒ   rs   ÚerrorsÚfrD   rD   rE   Útest_channelOpenFailurep  s    

 

z:SSHCommandClientEndpointTestsMixin.test_channelOpenFailurec                 C   sl   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}| 
t¡ |  d|jj¡ |  |d¡ dS )zÅ
        If execution of the command fails, the L{Deferred} returned by
        L{SSHCommandClientEndpoint.connect} fires with a L{Failure} wrapping
        the reason given by the server.
        ó   sessionzchannel request failedFN)rK   r€   rU   rŠ   r   r   rz   r>   rŽ   r—   r˜   r   r•   r”   r�   ©rC   r™   rf   rš   ru   rŒ   rs   rœ   rD   rD   rE   Útest_execFailureŠ  s    


z3SSHCommandClientEndpointTestsMixin.test_execFailurec                 C   sd   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}| 	¡  |  
|¡}| t¡ |  |d¡ dS )zµ
        If execution of the command is cancelled via the L{Deferred} returned
        by L{SSHCommandClientEndpoint.connect}, the connection is closed
        immediately.
        rž   TN)rR   r€   rU   rŠ   r   r   rz   r>   rŽ   Úcancelr—   r˜   r   r�   rŸ   rD   rD   rE   Útest_execCancelledŸ  s    


z5SSHCommandClientEndpointTestsMixin.test_execCancelledc                 C   s‚   t | jjd< |  ¡ }tƒ }t|_| |¡ |  ¡ \}}}|  	|j
t¡ |  |j ¡ |j
j¡ |  | j|j
j¡ |  d|j
j¡ dS )aD  
        Once the necessary SSH actions have completed successfully,
        L{SSHCommandClientEndpoint.connect} uses the factory passed to it to
        construct a protocol instance by calling its C{buildProtocol} method
        with an address object representing the SSH connection and command
        executed.
        rž   ó
   /bin/ls -lN)rP   r€   rU   rŠ   rZ   r   rz   r>   rŽ   ÚassertIsInstancer[   r,   r•   re   ZgetHostru   r~   ÚusernameÚcommand)rC   r™   rf   ru   rŒ   rs   rD   rD   rE   Útest_buildProtocol´  s    
z5SSHCommandClientEndpointTestsMixin.test_buildProtocolc                 C   sR   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}|  
|j¡ dS )a  
        L{SSHCommandClientEndpoint} establishes an SSH connection, creates a
        channel in it, runs a command in that channel, and uses the protocol's
        C{makeConnection} to associate it with a protocol representing that
        command's stdin and stdout.
        rž   N)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   ÚsuccessResultOfÚassertIsNotNonere   ©rC   r™   rf   rš   ru   rŒ   rs   rz   rD   rD   rE   Útest_makeConnectionË  s    

z6SSHCommandClientEndpointTestsMixin.test_makeConnectionc           
      C   s†   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}g }|j
|_|jj}	|jj|	  d¡ | ¡  |  dd |¡¡ dS )z²
        After establishing the connection, when the command on the SSH server
        produces output, it is delivered to the protocol's C{dataReceived}
        method.
        rž   ó   hello, worldrX   N)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   ÚappendÚdataReceivedre   ÚidÚserviceÚchannelsÚwriters   r•   Újoin)
rC   r™   rf   rš   ru   rŒ   rs   rz   r®   Ú	channelIdrD   rD   rE   Útest_dataReceivedÞ  s    

z4SSHCommandClientEndpointTestsMixin.test_dataReceivedc           
      C   sŒ   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}g }|j
|_|jj}	|jj|	  ¡  | ¡  |d  t¡ |  |d¡ dS )zq
        When the command closes the channel, the protocol's C{connectionLost}
        method is called.
        rž   r   FN)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   r­   ÚconnectionLostre   r¯   r°   r±   ÚloseConnectionrs   r˜   r   r�   )
rC   r™   rf   rš   ru   rŒ   rs   rz   r¶   r´   rD   rD   rE   Útest_connectionLostù  s    

z6SSHCommandClientEndpointTestsMixin.test_connectionLostc                 C   s–   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}	g }
|
j
|	_|	jj}|jj| }|j |||¡ | ¡  | ¡  |  |d¡ |
d S )zJ
        Test handling of non-zero exit statuses or exit signals.
        rž   Fr   )rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   r­   r¶   re   r¯   r°   r±   ZsendRequestr·   rs   r�   )rC   ÚrequestZ
requestArgr™   rf   rš   ru   rŒ   rs   rz   r¶   r´   ZchannelrD   rD   rE   Ú_exitStatusTest  s     

z2SSHCommandClientEndpointTestsMixin._exitStatusTestc                 C   s$   d}|   dtd|ƒ¡}| t¡ dS )úÊ
        When the command exits with a non-zero status, the protocol's
        C{connectionLost} method is called with a L{Failure} wrapping an
        exception which encapsulates that status.
        r   ó   exit-statusú>LN)rº   r   r˜   r   )rC   ÚexitCodeÚexcrD   rD   rE   Útest_zeroExitCode2  s    z4SSHCommandClientEndpointTestsMixin.test_zeroExitCodec                 C   sH   d}d}|   dtd|ƒ¡}| t¡ |  ||jj¡ |  ||jj¡ dS )r»   é{   Nr¼   r½   )rº   r   r˜   r   r•   r”   r¾   Úsignal)rC   r¾   rÂ   r¿   rD   rD   rE   Útest_nonZeroExitStatus<  s    
z9SSHCommandClientEndpointTestsMixin.test_nonZeroExitStatusc                 C   s¶   t ƒ }t |¡ |  tj|¡ d}d}d t d¡dt d¡t d¡g¡}|  d|¡}| 	t
¡ |  ||jj¡ |  ||jj¡ d	}t |t t t tj¡|dd
dddœ¡¡¡ dS )a  
        When the command exits with a non-zero signal, the protocol's
        C{connectionLost} method is called with a L{Failure} wrapping an
        exception which encapsulates that status.

        Additional packet contents are logged at the C{info} level.
        Né   rX   s   TERMó   s   messages   en-USs   exit-signalz'twisted.conch.endpoints._CommandChannelTÚmessage)Z	log_levelZlog_namespaceZshortSignalNameZ
coreDumpedZerrorMessageZlanguageTag)r   r   ZaddObserverrƒ   ZremoveObserverr³   r1   ZNSrº   r˜   r   r•   r”   r¾   rÂ   ÚhamcrestZassert_thatZhas_itemZhas_entriesZequal_tor   Úinfo)rC   ZlogObserverr¾   rÂ   Úpacketr¿   ZlogNamespacerD   rD   rE   Útest_nonZeroExitSignalI  s>    
ûÿ	

úÿÿþz9SSHCommandClientEndpointTestsMixin.test_nonZeroExitSignalFc                    s<   |j j}g ‰ |r‡ fdd„}nˆ j}t|jj| ||ƒ ˆ S )a  
        Hook into and record events which happen to C{protocol}.

        @param server: The SSH server protocol over which C{protocol} is
            running.
        @type server: L{IProtocol} provider

        @param protocol:

        @param event:

        @param noArgs:
        c                      s
   ˆ   d ¡S rT   )r­   rD   ©ZrecorderrD   rE   rW   ‹  rX   z;SSHCommandClientEndpointTestsMixin.record.<locals>.<lambda>)re   r¯   r­   Úsetattrr°   r±   )rC   ru   rz   ÚeventÚnoArgsr´   rœ   rD   rË   rE   Úrecordw  s    z)SSHCommandClientEndpointTestsMixin.recordc           	      C   sz   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}|  
||d¡}|j d¡ | ¡  |  dd |¡¡ dS )z¢
        The transport connected to the protocol has a C{write} method which
        sends bytes to the input of the command executing on the SSH server.
        rž   r®   r¬   rX   N)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   rÏ   re   r²   rs   r•   r³   ©	rC   r™   rf   rš   ru   rŒ   rs   rz   r®   rD   rD   rE   Ú
test_write’  s    

z-SSHCommandClientEndpointTestsMixin.test_writec           	      C   s|   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}|  
||d¡}|j dg¡ | ¡  |  dd |¡¡ dS )zª
        The transport connected to the protocol has a C{writeSequence} method which
        sends bytes to the input of the command executing on the SSH server.
        rž   r®   r¬   rX   N)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   rÏ   re   ZwriteSequencers   r•   r³   rÐ   rD   rD   rE   Útest_writeSequence§  s    

z5SSHCommandClientEndpointTestsMixin.test_writeSequenceN)F)rG   rH   rI   rJ   r†   rŠ   r�   rŽ   r�   r�   r    r¢   r§   r«   rµ   r¸   rº   rÀ   rÃ   rÊ   rÏ   rÑ   rÒ   rD   rD   rD   rE   r{     s(   		
.
r{   c                   @   sÈ   e Zd Z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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d$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0S )1ÚNewConnectionTestsz`
    Tests for L{SSHCommandClientEndpoint} when using the C{newConnection}
    constructor.
    c                 C   sh   t  | ¡ t|  ¡ ƒ| _t| jƒ| _| j | j| j	j
d ¡ | j t| jjƒ| j	j
d ¡ | j ¡  dS )ú
        Configure an SSH server with password authentication enabled for a
        well-known (to the tests) account.
        rm   N)r{   r†   r"   ÚmktempZhostKeyPathr*   Ú
knownHostsÚ
addHostKeyr|   rf   ro   r    r…   ÚhostÚsaverB   rD   rD   rE   r†   Ã  s    

 
ÿzNewConnectionTests.setUpc              
   C   s*   t j| jd| j| j| j| j| jtdƒd�S )zu
        Create and return a new L{SSHCommandClientEndpoint} using the
        C{newConnection} constructor.
        r£   F©r   rÖ   Úui)	r-   ÚnewConnectionrh   r~   r|   r}   r   rÖ   r]   rB   rD   rD   rE   rŠ   Ò  s    øzNewConnectionTests.createc                 C   s   |   | j| jjd d ¡S )z}
        Establish the first attempted TCP connection using the SSH server which
        C{self.factory} can create.
        r   é   )r�   rf   rh   Ú
tcpClientsrB   rD   rD   rE   rŽ   â  s     ÿz#NewConnectionTests.finishConnectionc                 C   sH   | j ||ddd�}|j ¡  | ¡  |  dg|¡ | ¡  |j ¡  dS )a×  
        Lose the connection to a server and pump the L{IOPump} sufficiently for
        the client to handle the lost connection. Asserts that the client
        disconnects its transport.

        @param server: The SSH server protocol over which C{protocol} is
            running.
        @type server: L{IProtocol} provider

        @param client: The SSH client protocol over which C{protocol} is
            running.
        @type client: L{IProtocol} provider

        @param protocol: The protocol created by calling connect on the ssh
            endpoint under test.
        @type protocol: L{IProtocol} provider

        @param pump: The L{IOPump} connecting client to server.
        @type pump: L{IOPump}
        ÚclosedT)rÎ   N)rÏ   re   r·   rs   r•   ZreportDisconnect)rC   ru   rŒ   rz   rs   rß   rD   rD   rE   ÚloseConnectionToServerë  s    
z)NewConnectionTests.loseConnectionToServerc                 C   s&   |r|   |jj¡ n|   |jj¡ dS )zä
        Assert that the transport for the given protocol has been disconnected.
        L{SSHCommandClientEndpoint.newConnection} creates a new dedicated SSH
        connection and cleans it up after the command exits.
        N)Ú
assertTruere   rA   Údisconnectingr‹   rD   rD   rE   r�     s    z-NewConnectionTests.assertClientTransportStatec                 C   s,   t  | jdd| j| j¡}|  tt|ƒ¡ dS )zY
        L{SSHCommandClientEndpoint} instances provide L{IStreamClientEndpoint}.
        ó   dummy commandó
   dummy userN)r-   rÜ   rh   r|   r}   rá   r   r   ©rC   r™   rD   rD   rE   Útest_interface  s        ÿz!NewConnectionTests.test_interfacec                 C   s(   t  | jdd| j¡}|  d|jj¡ dS )z†
        L{SSHCommandClientEndpoint} uses the default port number for SSH when
        the C{port} argument is not specified.
        rã   rä   é   N©r-   rÜ   rh   r|   r•   Z_creatorr}   rå   rD   rD   rE   Útest_defaultPort$  s       ÿz#NewConnectionTests.test_defaultPortc                 C   s,   t j| jdd| jdd�}|  d|jj¡ dS )zU
        L{SSHCommandClientEndpoint} uses the C{port} argument if specified.
        rã   rä   i®  )r}   Nrè   rå   rD   rD   rE   Útest_specifiedPort.  s        ÿz%NewConnectionTests.test_specifiedPortc              
   C   sŽ   t j| jd| j| j| j| j| jtdƒd�}t	ƒ }t
|_| |¡ | jjd \}}}}}|  | jt|ƒ¡ |  | j|¡ |  dt| jjƒ¡ dS )zž
        L{SSHCommandClientEndpoint} uses the L{IReactorTCP} passed to it to
        attempt a connection to the host/port address also passed to it.
        r£   FrÚ   r   rQ   N)r-   rÜ   rh   r~   r|   r}   r   rÖ   r]   r   r   rz   r>   rÞ   r•   r    r–   )rC   r™   rf   rØ   r}   ÚtimeoutZbindAddressrD   rD   rE   Útest_destination7  s"    ø

z#NewConnectionTests.test_destinationc              	   C   sp   t j| jdd| j| j| jtdƒd�}tƒ }t|_	| 
|¡}| jjd d }| dttƒ ƒ¡ |  |¡ t¡ dS )zÚ
        If a connection cannot be established, the L{Deferred} returned by
        L{SSHCommandClientEndpoint.connect} fires with a L{Failure}
        representing the reason for the connection setup failure.
        r£   rä   F©rÖ   rÛ   r   rÝ   N)r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   rÞ   ZclientConnectionFailedr!   r   r—   r˜   ©rC   r™   rf   ÚdrD   rD   rE   Útest_connectionFailedO  s    ù	
z(NewConnectionTests.test_connectionFailedc              	   C   sx   t j| jdd| j| jt|  ¡ ƒtdƒd�}tƒ }t	|_
| |¡}|  | j| jjd d ¡\}}}|  |¡}| t¡ dS )a"  
        If the L{KnownHostsFile} instance used to construct
        L{SSHCommandClientEndpoint} rejects the SSH public key presented by the
        server, the L{Deferred} returned by L{SSHCommandClientEndpoint.connect}
        fires with a L{Failure} wrapping L{UserRejectedKey}.
        r£   rä   Frí   r   rÝ   N)r-   rÜ   rh   r|   r}   r*   rÕ   r]   r   r   rz   r>   r�   rf   rÞ   r—   r˜   r
   rŸ   rD   rD   rE   Útest_userRejectedHostKeyg  s$    
ù

 ÿ

z+NewConnectionTests.test_userRejectedHostKeyc              
   C   sÈ   t  t¡ ¡ }tt|  ¡ ƒƒ}| t| j	j
ƒ|¡ t jtdd� ¡ }| | j|¡ tdƒ}tj| jdd| j| jd||d�}tƒ }t|_| |¡}|  | j| jjd d	 ¡\}}	}
|  |¡}| t¡ d
S )ac  
        If the SSH public key presented by the SSH server does not match the
        previously remembered key, as reported by the L{KnownHostsFile}
        instance use to construct the endpoint, for that server, the
        L{Deferred} returned by L{SSHCommandClientEndpoint.connect} fires with
        a L{Failure} wrapping L{HostKeyChanged}.
        s   testxp)Z
passphraseTr£   rä   ó   dummy passwordrÚ   r   rÝ   N)r6   rn   r:   Úpublicr*   r"   rÕ   r×   r    r…   rØ   r;   r|   r]   r-   rÜ   rh   r}   r   r   rz   r>   r�   rf   rÞ   r—   r˜   r	   )rC   ZfirstKeyrÖ   ZdifferentKeyrÛ   r™   rf   rš   ru   rŒ   rs   rœ   rD   rD   rE   Útest_mismatchedHostKeyƒ  s8     ÿ
ø
 ÿ

z)NewConnectionTests.test_mismatchedHostKeyc              	   C   sˆ   t j| jdd| j| j| jtdƒd�}tƒ }t|_	| 
|¡}tƒ }| jjd d }| d¡}| |¡ | ttƒ ƒ¡ |  |¡ t¡ dS )aU  
        If the connection closes at any point before the SSH transport layer
        has finished key exchange (ie, gotten to the point where we may attempt
        to authenticate), the L{Deferred} returned by
        L{SSHCommandClientEndpoint.connect} fires with a L{Failure} wrapping
        the reason for the lost connection.
        r£   rä   Frí   r   rÝ   N)r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r   rÞ   r\   ÚmakeConnectionr¶   r!   r   r—   r˜   ©rC   r™   rf   rï   re   rŒ   rD   rD   rE   Ú!test_connectionClosedBeforeSecure¯  s$    ù



z4NewConnectionTests.test_connectionClosedBeforeSecurec              	   C   s¢   t j| jdd| j| j| jtdƒd�}tƒ }t|_	| 
|¡}tddd�}| jjd d }| d¡}| |¡ | ¡  |  |¡ t¡ |  |j¡ | ttƒ ƒ¡ dS )	a[  
        If the connection is cancelled before the SSH transport layer has
        finished key exchange (ie, gotten to the point where we may attempt to
        authenticate), the L{Deferred} returned by
        L{SSHCommandClientEndpoint.connect} fires with a L{Failure} wrapping
        L{CancelledError} and the connection is aborted.
        r£   rä   Frí   Nrv   r   rÝ   )r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r?   rÞ   r\   rõ   r¡   r—   r˜   r   rá   rA   r¶   r!   r   rö   rD   rD   rE   Ú$test_connectionCancelledBeforeSecureÍ  s(    ù



z7NewConnectionTests.test_connectionCancelledBeforeSecurec              	   C   sj   t j| jdd| j| j| jtdƒd�}tƒ }t|_	| 
|¡}| ¡  |  |¡ t¡ |  | jjd j¡ dS )zz
        If the connection is cancelled before it finishes connecting, the
        connection attempt is stopped.
        r£   rä   Frí   r   N)r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r¡   r—   r˜   r   rá   Z
connectorsZstoppedConnectingrî   rD   rD   rE   Ú'test_connectionCancelledBeforeConnectedï  s    ù

z:NewConnectionTests.test_connectionCancelledBeforeConnectedc              
   C   s˜   t j| jdd| j| jd| jtdƒd�}tƒ }t|_	| 
|¡}|  | j| jjd d ¡\}}}| j |jj¡ | ¡  |  |¡}| t¡ |  |d¡ dS )	zã
        If the SSH server rejects the password presented during authentication,
        the L{Deferred} returned by L{SSHCommandClientEndpoint.connect} fires
        with a L{Failure} wrapping L{AuthenticationFailed}.
        r£   rä   rò   FrÚ   r   rÝ   N)r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r�   rf   rÞ   Zadvancer°   ZpasswordDelayÚflushr—   r˜   r+   r�   rŸ   rD   rD   rE   Ú"test_passwordAuthenticationFailure  s,    ø
 ÿ


z5NewConnectionTests.test_passwordAuthenticationFailurec                 C   s,   dd„ |  ¡ D ƒ}tt|ƒƒ}| |¡ dS )a¼  
        Create an L{ISSHPrivateKey} checker which recognizes C{users} and add it
        to C{portal}.

        @param portal: A L{Portal} to which to add the checker.
        @type portal: L{Portal}

        @param users: The users and their keys the checker will recognize.  Keys
            are byte strings giving user names.  Values are byte strings giving
            OpenSSH-formatted private keys.
        @type users: L{dict}
        c                 S   s"   i | ]\}}|t  |¡ ¡ g“qS rD   )r6   rn   ró   )Ú.0ÚkÚvrD   rD   rE   Ú
<dictcomp>:  s      z6NewConnectionTests.setupKeyChecker.<locals>.<dictcomp>N)Úitemsr(   r'   r‚   )rC   r�   ZusersÚmappingÚcheckerrD   rD   rE   ÚsetupKeyChecker-  s    z"NewConnectionTests.setupKeyCheckerc           	   
   C   s¤   t  t¡}|  | j| jti¡ tj| j	d| j| j
| j|g| jtdƒd�}tƒ }t|_| |¡}|  | j| j	jd d ¡\}}}|  |¡}| t¡ |  |jj¡ dS )zã
        If the SSH server rejects the key pair presented during authentication,
        the L{Deferred} returned by L{SSHCommandClientEndpoint.connect} fires
        with a L{Failure} wrapping L{AuthenticationFailed}.
        r£   F©ÚkeysrÖ   rÛ   r   rÝ   N)r6   rn   r:   r  r�   r~   r9   r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r�   rf   rÞ   r—   r˜   r+   rá   re   râ   )	rC   ÚbadKeyr™   rf   rš   ru   rŒ   rs   rœ   rD   rD   rE   Ú#test_publicKeyAuthenticationFailure>  s,    
ø
 ÿ


z6NewConnectionTests.test_publicKeyAuthenticationFailurec           
      C   s
  t  t¡}|  | j| jti¡ tj| j	d| j| j
| j|g| j| jtdƒd�	}tƒ }t|_| |¡}| j jd7  _|  | j| j	jd d ¡\}}}| ¡  |  t¡}|  d|d jj|d jjf¡ |  dt|ƒ¡ |  |¡}	|	  t¡ |  d|	jj¡ |  !|j"j#¡ d	S )
z{
        If the SSH server does not accept any of the specified SSH keys, the
        specified password is tried.
        r£   F)r  r   rÖ   rÛ   rQ   r   rÝ   r�   r‘   N)$r6   rn   r:   r  r�   r~   r9   r-   rÜ   rh   r|   r}   r   rÖ   r]   r   r   rz   r>   rf   rg   r�   rÞ   rs   r’   r   r“   r”   rM   r•   r–   r—   r˜   rá   re   râ   )
rC   r  r™   rf   rš   ru   rŒ   rs   r›   rœ   rD   rD   rE   Útest_authenticationFallbackc  s:    
÷
 ÿ

 

z.NewConnectionTests.test_authenticationFallbackc           	   
   C   s¤   t  t¡}|  | j| jti¡ t| jjd< t	j
| jd| j| j| j|g| jtdƒd�}tƒ }t|_| |¡}|  | j| jjd d ¡\}}}|  |¡}|  |j¡ dS )z›
        If L{SSHCommandClientEndpoint} is initialized with any private keys, it
        will try to use them to authenticate with the SSH server.
        rž   r£   Fr  r   rÝ   N)r6   rn   r9   r  r�   r~   rP   r€   rU   r-   rÜ   rh   r|   r}   rÖ   r]   r   r   rz   r>   r�   rf   rÞ   r¨   r©   re   )	rC   Úkeyr™   rf   rš   ru   rŒ   rs   rz   rD   rD   rE   Útest_publicKeyAuthentication“  s,    
ø
 ÿ

z/NewConnectionTests.test_publicKeyAuthenticationc              	   C   sŠ   t j| jd| j| j| j| jtdƒd�}tƒ }t	|_
| |¡}|  | j| jjd d ¡\}}}| ¡  |  |¡}| t¡ |  |jj¡ dS )z†
        If the password is not specified, L{SSHCommandClientEndpoint} doesn't
        try it as an authentication mechanism.
        r£   Frí   r   rÝ   N)r-   rÜ   rh   r~   r|   r}   rÖ   r]   r   r   rz   r>   r�   rf   rÞ   rs   r—   r˜   r+   rá   re   râ   rŸ   rD   rD   rE   Útest_skipPasswordAuthentication²  s(    ù

 ÿ


z2NewConnectionTests.test_skipPasswordAuthenticationc              
   C   s  t  t¡}tƒ }tƒ |_| ¡ |dfi|j_|  | j	| j
ti¡ t|ƒ}tj| jd| j
| j| j| jtdƒ|d�}t| jjd< tƒ }t|_| |¡}|  | j| jjd d ¡\}}}	tdƒD ]}
|j ¡  |	 ¡  qº|  |¡}|  |j¡ |   ||||	¡ |  !|jj"¡ |  !|jj#j"¡ d	S )
a  
        If L{SSHCommandClientEndpoint} is initialized with an
        L{SSHAgentClient}, the agent is used to authenticate with the SSH
        server. Once the connection with the SSH server has concluded, the
        connection to the agent is disconnected.
        rX   r£   F)rÖ   rÛ   ÚagentEndpointrž   r   rÝ   é   N)$r6   rn   r:   r2   r   rf   Zblobr  r  r�   r~   rr   r-   rÜ   rh   r|   r}   rÖ   r]   rP   r€   rU   r   rz   r>   r�   rÞ   Úrangers   r¨   r©   re   rà   rá   râ   ZclientIO)rC   r	  ZagentServerr  r™   rf   rš   ru   rŒ   rs   Úirz   rD   rD   rE   Útest_agentAuthenticationÓ  s@    
ø
 ÿ



z+NewConnectionTests.test_agentAuthenticationc                 C   sd   t | jjd< |  ¡ }tƒ }t|_| |¡}|  ¡ \}}}|  	|¡}|  
||||¡ |  |jj¡ dS )zÓ
        The transport connected to the protocol has a C{loseConnection} method
        which causes the channel in which the command is running to close and
        the overall connection to be closed.
        rž   N)rP   r€   rU   rŠ   r   r   rz   r>   rŽ   r¨   rà   rá   re   râ   rª   rD   rD   rE   Útest_loseConnection  s    

z&NewConnectionTests.test_loseConnectionN)rG   rH   rI   rJ   r†   rŠ   rŽ   rà   r�   ræ   ré   rê   rì   rð   rñ   rô   r÷   rø   rù   rû   r  r  r  r
  r  r  r  rD   rD   rD   rE   rÓ   ½  s0   	#	
	,"(%0!3rÓ   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚExistingConnectionTestsze
    Tests for L{SSHCommandClientEndpoint} when using the C{existingConnection}
    constructor.
    c              
   C   sz   t  | ¡ tt|  ¡ ƒƒ}| | j| jjd ¡ | t	| j
jƒ| jjd ¡ tj| jd| j| j| j| j|tdƒd�| _dS )rÔ   rm   r£   FrÚ   N)r{   r†   r*   r"   rÕ   r×   r|   rf   ro   r    r…   rØ   r-   rÜ   rh   r~   r}   r   r]   r™   )rC   rÖ   rD   rD   rE   r†   #  s"    

 
ÿøzExistingConnectionTests.setUpc           	   	   C   s¢   t ƒ }t|_| j |¡}| jj ¡ }z0t
| jjd< |  | j| jjd d ¡\}}}W 5 | jj ¡  | jj 	|¡ X || _|| _|| _|  |¡}|jj}t |d¡S )zz
        Create and return a new L{SSHCommandClientEndpoint} using the
        C{existingConnection} constructor.
        rž   r   rÝ   r£   )r   r   rz   r™   r>   r€   rU   ÚcopyÚclearÚupdaterP   r�   rf   rh   rÞ   rt   Ú_clientÚ_pumpr¨   re   Úconnr-   ZexistingConnection)	rC   rf   rš   rU   ru   rŒ   rs   rz   Ú
connectionrD   rD   rE   rŠ   ;  s$     ÿ
zExistingConnectionTests.createc                 C   s8   | j  ¡  | j  ¡  | j  ¡  | j  ¡  | j| j| j fS )z�
        Give back the connection established in L{create} over which the new
        command channel being tested will exchange data.
        )r  rs   rt   r  rB   rD   rD   rE   rŽ   Y  s
    



z(ExistingConnectionTests.finishConnectionc                 C   s    |   |jj¡ |   |jj¡ dS )a  
        Assert that the transport for the given protocol is still connected.
        L{SSHCommandClientEndpoint.existingConnection} re-uses an SSH connected
        created by some other code, so other code is responsible for cleaning
        it up.
        N)ÚassertFalsere   râ   rA   r‹   rD   rD   rE   r�   g  s    z2ExistingConnectionTests.assertClientTransportStateN)rG   rH   rI   rJ   r†   rŠ   rŽ   r�   rD   rD   rD   rE   r    s
   r  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚExistingConnectionHelperTestsz1
    Tests for L{_ExistingConnectionHelper}.
    c                 C   s   |   tttƒ¡ dS )zT
        L{_ExistingConnectionHelper} implements L{_ISSHConnectionCreator}.
        N)rá   r   r/   r.   rB   rD   rD   rE   ræ   w  s    z,ExistingConnectionHelperTests.test_interfacec                 C   s(   t ƒ }t|ƒ}|  ||  | ¡ ¡¡ dS )z¸
        L{_ExistingConnectionHelper.secureConnection} returns a L{Deferred}
        which fires with whatever object was fed to
        L{_ExistingConnectionHelper.__init__}.
        N)Úobjectr.   ÚassertIsr¨   ZsecureConnection)rC   r_   ÚhelperrD   rD   rE   Útest_secureConnection}  s    z3ExistingConnectionHelperTests.test_secureConnectionc                 C   s   t tƒ ƒ}| tƒ d¡ dS )z�
        L{_ExistingConnectionHelper.cleanupConnection} does nothing to the
        existing connection if called with C{immediate} set to C{False}.
        FN©r.   r  ÚcleanupConnection©rC   r  rD   rD   rE   Ú$test_cleanupConnectionNotImmediately‡  s    
zBExistingConnectionHelperTests.test_cleanupConnectionNotImmediatelyc                 C   s   t tƒ ƒ}| tƒ d¡ dS )zœ
        L{_ExistingConnectionHelper.cleanupConnection} does nothing to the
        existing connection if called with C{immediate} set to C{True}.
        TNr   r"  rD   rD   rE   Ú!test_cleanupConnectionImmediately’  s    
z?ExistingConnectionHelperTests.test_cleanupConnectionImmediatelyN)rG   rH   rI   rJ   ræ   r  r#  r$  rD   rD   rD   rE   r  r  s
   
r  c                   @   s   e Zd Zeedœdd„ZdS )Ú_WriteDiscarder)rM   Úreturnc                C   s   dS )z§
        Discard writes because we are emulating a console object, where they'd
        go to the screen, not back into the buffer to be read like an a+ file.
        r   rD   rL   rD   rD   rE   r²   Ÿ  s    z_WriteDiscarder.writeN)rG   rH   rI   r  Úintr²   rD   rD   rD   rE   r%  ž  s   r%  c                   @   s4   e Zd ZdZeddœdd„Zeee dœdd„ZdS )	Ú_PTYPathzk
    A L{FilePath}-like object which can be opened to create a L{_ReadFile} with
    certain contents.
    N)Úcontentsr&  c                 C   s
   || _ dS )zz
        @param contents: L{bytes} which will be the contents of the
            L{_ReadFile} this path can open.
        N)r)  )rC   r)  rD   rD   rE   rV   ­  s    z_PTYPath.__init__)Úmoder&  c                 C   s   |dkst ‚t| jƒS )z¾
        If the mode is r+, return a file with the given contents as a line.

        @return: a buffer of the given contents, which will discard any writes
            given to it.
        zr+)ÚAssertionErrorr%  r)  )rC   r*  rD   rD   rE   Úopen´  s    z_PTYPath.open)	rG   rH   rI   rJ   ÚbytesrV   Ústrr   r,  rD   rD   rD   rE   r(  §  s   r(  c                   @   s`   e Zd Z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dd„ Zdd„ ZdS )ÚNewConnectionHelperTestsz,
    Tests for L{_NewConnectionHelper}.
    c                 C   s   |   tttƒ¡ dS )zO
        L{_NewConnectionHelper} implements L{_ISSHConnectionCreator}.
        N)rá   r   r/   r0   rB   rD   rD   rE   ræ   Ä  s    z'NewConnectionHelperTests.test_interfacec                 C   s   |   dtj¡ dS )zK
        The default I{known_hosts} path is I{~/.ssh/known_hosts}.
        z~/.ssh/known_hostsN)r•   r0   Ú_KNOWN_HOSTSrB   rD   rD   rE   Útest_defaultPathÊ  s    z)NewConnectionHelperTests.test_defaultPathc                    sH   t ƒ ‰ |  td‡ fdd„¡ tddddddddddƒ
}|  ˆ |j¡ dS )zŒ
        L{_NewConnectionHelper._knownHosts} is used to create a
        L{KnownHostsFile} if one is not passed to the initializer.
        Ú_knownHostsc                    s   ˆ S rT   rD   )Úclsr^   rD   rE   rW   Ö  rX   zANewConnectionHelperTests.test_defaultKnownHosts.<locals>.<lambda>N)r  Úpatchr0   r  rÖ   r"  rD   r^   rE   Útest_defaultKnownHostsÐ  s             ÿz/NewConnectionHelperTests.test_defaultKnownHostsc                 C   s˜   t ƒ jd }t|  ¡ ƒ}t|ƒ}| d|¡ | ¡  td|j›�ƒ t	j 
d¡}|j |d¡}|  td|¡ td|›�ƒ t ¡ }|  | d|¡¡ dS )z´
        Existing entries in the I{known_hosts} file are reflected by the
        L{KnownHostsFile} created by L{_NewConnectionHelper} when none is
        supplied to it.
        rm   s	   127.0.0.1zCreated known_hosts file at z~/r0  zPatched _KNOWN_HOSTS with N)rk   ro   r"   rÕ   r*   r×   rÙ   r#   ÚpathÚosÚ
expanduserÚreplacer4  r0   r2  rá   Z
hasHostKey)rC   r	  r6  rÖ   ÚhomeÚdefaultZloadedrD   rD   rE   Útest_readExistingÞ  s    z*NewConnectionHelperTests.test_readExistingc                 C   s,   t ddddddddddƒ
}|  |jt¡ dS )zz
        If L{None} is passed for the C{ui} parameter to
        L{_NewConnectionHelper}, a L{ConsoleUI} is used.
        N)r0   r¤   rÛ   r)   r"  rD   rD   rE   Útest_defaultConsoleUIõ  s             ÿz.NewConnectionHelperTests.test_defaultConsoleUIc                 C   sD   t dƒ}tdddddddddd|ƒ}|  |j d¡¡}|  |¡ dS )z·
        If L{None} is passed for the C{ui} parameter to L{_NewConnectionHelper}
        and /dev/tty is available, the L{ConsoleUI} used is associated with
        /dev/tty.
        s   yesNs   does this work?)r(  r0   r¨   rÛ   rb   rá   ©rC   Úttyr  r_   rD   rD   rE   Útest_ttyConsoleUIÿ  s               ÿz*NewConnectionHelperTests.test_ttyConsoleUIc                 C   sH   t |  ¡ ƒ}tdddddddddd|ƒ}|  |j d¡¡}|  |¡ dS )zæ
        If L{None} is passed for the C{ui} parameter to L{_NewConnectionHelper}
        and /dev/tty is not available, the L{ConsoleUI} used is associated with
        some file which always produces a C{b"no"} response.
        Ns   did this break?)r"   rÕ   r0   r¨   rÛ   rb   r  r>  rD   rD   rE   Útest_nottyUI  s               ÿz%NewConnectionHelperTests.test_nottyUIc                 C   s0   t ddddddddddƒ
}|  tdƒ|j¡ dS )zy
        If not passed the name of a tty in the filesystem,
        L{_NewConnectionHelper} uses C{b"/dev/tty"}.
        Ns   /dev/tty)r0   r•   r"   r?  r"  rD   rD   rE   Útest_defaultTTYFilename  s             ÿz0NewConnectionHelperTests.test_defaultTTYFilenamec                 C   sF   t ddddddddddƒ
}tƒ }tƒ |_| |d¡ |  |jj¡ dS )z�
        L{_NewConnectionHelper.cleanupConnection} closes the transport cleanly
        if called with C{immediate} set to C{False}.
        NF)r0   r4   r   re   r!  rá   râ   )rC   r  r  rD   rD   rE   r#  #  s              ÿz=NewConnectionHelperTests.test_cleanupConnectionNotImmediatelyc                 C   s`   G dd„ dƒ}t ddddddddddƒ
}tƒ }tƒ |_|ƒ |j_| |d¡ |  |jjj¡ dS )zœ
        L{_NewConnectionHelper.cleanupConnection} closes the transport with
        C{abortConnection} if called with C{immediate} set to C{True}.
        c                   @   s   e Zd ZdZdd„ ZdS )zMNewConnectionHelperTests.test_cleanupConnectionImmediately.<locals>.AbortableFc                 S   s
   d| _ dS )z7
                Abort the connection.
                TNr@   rB   rD   rD   rE   rF   9  s    z]NewConnectionHelperTests.test_cleanupConnectionImmediately.<locals>.Abortable.abortConnectionN)rG   rH   rI   rA   rF   rD   rD   rD   rE   Ú	Abortable6  s   rC  NT)r0   r4   r7   re   r!  rá   rA   )rC   rC  r  r  rD   rD   rE   r$  0  s$    	         ÿ
z:NewConnectionHelperTests.test_cleanupConnectionImmediatelyN)rG   rH   rI   rJ   ræ   r1  r5  r<  r=  r@  rA  rB  r#  r$  rD   rD   rD   rE   r/  ¿  s   

r/  )yrJ   Úos.pathr7  Úior   Ústructr   Útypingr   Zzope.interfacer   Zzope.interface.verifyr   r   rÇ   Ztwisted.conch.errorr   r	   r
   Ztwisted.conch.interfacesr   Ztwisted.cred.checkersr   Ztwisted.cred.portalr   Ztwisted.internet.addressr   Ztwisted.internet.deferr   r   r   r   Ztwisted.internet.errorr   r   r   r   Ztwisted.internet.interfacesr   r   Ztwisted.internet.protocolr   r   Ztwisted.internet.testingr   r   r   Ztwisted.loggerr   r   Ztwisted.python.compatr    Ztwisted.python.failurer!   Ztwisted.python.filepathr"   Ztwisted.python.logr#   Ztwisted.python.reflectr$   Ztwisted.trial.unittestr%   Ztwisted.conch.avatarr&   Ztwisted.conch.checkersr'   r(   Ztwisted.conch.client.knownhostsr)   r*   Ztwisted.conch.endpointsr+   r,   r-   r.   r/   r0   Ztwisted.conch.sshr1   Ztwisted.conch.ssh.agentr2   Ztwisted.conch.ssh.channelr3   Ztwisted.conch.ssh.connectionr4   Ztwisted.conch.ssh.factoryr5   Ztwisted.conch.ssh.keysr6   Ztwisted.conch.ssh.transportr7   Ztwisted.conch.ssh.userauthr8   Ztwisted.conch.test.keydatar9   r:   r;   r<   Úskipr  Ztwisted.test.iosimr=   r>   r?   rK   rP   rR   rS   rZ   r]   rd   rk   rq   rr   r{   rÓ   r  r  r%  r(  r/  rD   rD   rD   rE   Ú<module>   s˜   
 
&   1    dU,	