o
    bd                  
   @   s  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZmZmZmZ d dlmZ d dlmZ d d	lmZmZmZ d d
lmZ d dlmZ d dlmZ d dlm Z m!Z!m"Z" d dl#m$Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z*m+Z+ z
d dlm,Z,m-Z- W n	 e.y   Y nw e(dZ/e(dZ0e0rd dl1m2Z2 d dl3m4Z4m5Z5m6Z6 nd dl7m4Z4 G dd dZ2zd dl8m5Z9 W n e.y Z: zdZ;e<e:Z=[:W Y dZ:[:ndZ:[:ww e9Z;dd Z>e> Z?G dd dZ@G dd  d e+ZAG d!d" d"ejBZCG d#d$ d$ejDZEG d%d& d&ejFZGG d'd( d(ejFZHG d)d* d*ejBZIdBd,d-ZJG d.d/ d/ZKG d0d1 d1eKZLe	e4G d2d3 d3e2ZMG d4d5 d5ZNG d6d7 d7eKZOG d8d9 d9ZPG d:d; d;eKePe+ZQG d<d= d=eLePe+ZRG d>d? d?eOePe+ZSG d@dA dAeLe+ZTdS )C    N)count)skipIf)implementer)
ConchError)privateDSA_opensshprivateRSA_opensshpublicDSA_opensshpublicRSA_opensshConchTestRealm)portal)deferprotocolreactor)ProcessExitedAlready)LoopingCall)getProcessValue)filepathlogruntime)FilePath)which)requireModule)SkipTestTestCase)ConchTestServerFactoryconchTestPublicKeyCheckerpyasn1cryptography)	ConchUser)ISession
SSHSessionwrapProtocol)r    c                   @   s   e Zd ZdS )r   N)__name__
__module____qualname__ r&   r&   ?/usr/lib/python3/dist-packages/twisted/conch/test/test_conch.pyr   2   s    r   )r!   c                  C   sJ   d} d}zt  t j} | d d}W n	 ty   Y nw | r#|   |S )z4Returns True if the system can bind an IPv6 address.NF)::1r   T)socketAF_INET6bindOSErrorclose)sockhas_ipv6r&   r&   r'   	_has_ipv6@   s   
r0   c                   @   s   e Zd ZdZdZdd ZdS )	FakeStdioz
    A fake for testing L{twisted.conch.scripts.conch.SSHSession.eofReceived} and
    L{twisted.conch.scripts.cftp.SSHSession.eofReceived}.

    @ivar writeConnLost: A flag which records whether L{loserWriteConnection}
        has been called.
    Fc                 C   s
   d| _ dS )z9
        Record the call to loseWriteConnection.
        TN)writeConnLostselfr&   r&   r'   loseWriteConnection_   s   
zFakeStdio.loseWriteConnectionN)r#   r$   r%   __doc__r2   r5   r&   r&   r&   r'   r1   T   s    r1   c                   @   s$   e Zd ZdZedu reZdd ZdS )StdioInteractingSessionTestsz>
    Tests for L{twisted.conch.scripts.conch.SSHSession}.
    Nc                 C   s*   t  }t }||_|  | |j dS )z}
        L{twisted.conch.scripts.conch.SSHSession.eofReceived} loses the
        write half of its stdio connection.
        N)r1   StdioInteractingSessionstdioeofReceived
assertTruer2   )r4   r9   channelr&   r&   r'   test_eofReceivedn   s
   z-StdioInteractingSessionTests.test_eofReceived)r#   r$   r%   r6   r8   _reasonskipr=   r&   r&   r&   r'   r7   f   s
    r7   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )Echoc                 C      t d d S )NzECHO CONNECTION MADEr   msgr3   r&   r&   r'   connectionMade{      zEcho.connectionMadec                 C   rA   )NzECHO CONNECTION DONErB   r4   reasonr&   r&   r'   connectionLost~   rE   zEcho.connectionLostc                 C   s&   | j | d|v r| j   d S d S )N   
)	transportwriteloseConnectionr4   datar&   r&   r'   dataReceived   s   zEcho.dataReceivedN)r#   r$   r%   rD   rH   rO   r&   r&   r&   r'   r@   z   s    r@   c                   @   s   e Zd ZeZdS )EchoFactoryN)r#   r$   r%   r@   r   r&   r&   r&   r'   rP          rP   c                   @   s<   e Zd ZdZdZdZdZdd Zdd Zdd	 Z	d
d Z
dS )ConchTestOpenSSHProcessa  
    Test protocol for launching an OpenSSH client process.

    @ivar deferred: Set by whatever uses this object. Accessed using
    L{_getDeferred}, which destroys the value so the Deferred is not
    fired twice. Fires when the process is terminated.
    N    c                 C      | j d }| _ |S Ndeferredr4   dr&   r&   r'   _getDeferred      z$ConchTestOpenSSHProcess._getDeferredc                 C      |  j |7  _ d S rU   )bufrM   r&   r&   r'   outReceived      z#ConchTestOpenSSHProcess.outReceivedc                 C   r\   rU   )problemsrM   r&   r&   r'   errReceived   r_   z#ConchTestOpenSSHProcess.errReceivedc              	   C   sV   |j jdkr|  td|j j| jd dS | j	dd}|  
| dS )z~
        Called when the process has ended.

        @param reason: a Failure giving the reason for the process' end.
        r   zexit code was not 0: {} ({})charmaps   
rI   N)valueexitCoderZ   errbackr   formatr`   decoder]   replacecallback)r4   rG   r]   r&   r&   r'   processEnded   s   
	z$ConchTestOpenSSHProcess.processEnded)r#   r$   r%   r6   rW   r]   r`   rZ   r^   ra   rj   r&   r&   r&   r'   rR      s    rR   c                   @   sT   e Zd 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S )ConchTestForwardingProcessa  
    Manages a third-party process which launches a server.

    Uses L{ConchTestForwardingPort} to connect to the third-party server.
    Once L{ConchTestForwardingPort} has disconnected, kill the process and fire
    a Deferred with the data received by the L{ConchTestForwardingPort}.

    @ivar deferred: Set by whatever uses this object. Accessed using
    L{_getDeferred}, which destroys the value so the Deferred is not
    fired twice. Fires when the process is terminated.
    Nc                 C   s   || _ d| _|| _dS )aF  
        @type port: L{int}
        @param port: The port on which the third-party server is listening.
        (it is assumed that the server is running on localhost).

        @type data: L{str}
        @param data: This is sent to the third-party server. Must end with '
'
        in order to trigger a disconnect.
        N)portbufferrN   )r4   rl   rN   r&   r&   r'   __init__   s   

z#ConchTestForwardingProcess.__init__c                 C   rT   rU   rV   rX   r&   r&   r'   rZ      r[   z'ConchTestForwardingProcess._getDeferredc                 C   s   |    d S rU   )_connectr3   r&   r&   r'   rD      s   z)ConchTestForwardingProcess.connectionMadec                 C   s0   t tt| | j}|d| j}|| j |S )a  
        Connect to the server, which is often a third-party process.
        Tries to reconnect if it fails because we have no way of determining
        exactly when the port becomes available for listening -- we can only
        know when the process starts.
        	127.0.0.1)	r   ClientCreatorr   ConchTestForwardingPortrN   
connectTCPrl   
addErrback
_ebConnect)r4   ccrY   r&   r&   r'   ro      s   z#ConchTestForwardingProcess._connectc                 C   s   t d| j d S )Ng?)r   	callLaterro   )r4   fr&   r&   r'   ru      r_   z%ConchTestForwardingProcess._ebConnectc                 C   s.   || _ | jd | j  td| j dS )z
        The network connection has died; save the buffer of output
        from the network and attempt to quit the process gracefully,
        and then (after the reactor has spun) send it a KILL signal.
           r   N)rm   rJ   rK   rL   r   rw   
_reallyDie)r4   rm   r&   r&   r'   forwardingPortDisconnected   s   
z5ConchTestForwardingProcess.forwardingPortDisconnectedc                 C   s(   z	| j d W d S  ty   Y d S w )NKILL)rJ   signalProcessr   r3   r&   r&   r'   rz      s
   z%ConchTestForwardingProcess._reallyDiec                 C   s   |   | j dS )z
        Fire the Deferred at self.deferred with the data collected
        from the L{ConchTestForwardingPort} connection, if any.
        N)rZ   ri   rm   rF   r&   r&   r'   rj      s   z'ConchTestForwardingProcess.processEnded)r#   r$   r%   r6   rW   rn   rZ   rD   ro   ru   r{   rz   rj   r&   r&   r&   r'   rk      s    rk   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )rr   z
    Connects to server launched by a third-party process (managed by
    L{ConchTestForwardingProcess}) sends data, then reports whatever it
    received back to the L{ConchTestForwardingProcess} once the connection
    is ended.
    c                 C   s   || _ || _dS )z
        @type protocol: L{ConchTestForwardingProcess}
        @param protocol: The L{ProcessProtocol} which made this connection.

        @type data: str
        @param data: The data to be sent to the third-party server.
        N)r   rN   )r4   r   rN   r&   r&   r'   rn   
  s   
z ConchTestForwardingPort.__init__c                 C   s   d| _ | j| j d S )NrS   )rm   rJ   rK   rN   r3   r&   r&   r'   rD     s   z&ConchTestForwardingPort.connectionMadec                 C   r\   rU   )rm   rM   r&   r&   r'   rO     r_   z$ConchTestForwardingPort.dataReceivedc                 C   s   | j | j d S rU   )r   r{   rm   rF   r&   r&   r'   rH     r_   z&ConchTestForwardingPort.connectionLostN)r#   r$   r%   r6   rn   rD   rO   rH   r&   r&   r&   r'   rr     s    rr   conchc                 C   sF   t jd| g}g }|t|  D ]}t|tr|d}|| q|S )Na$  -c
### Twisted Preamble
import sys, os
path = os.path.abspath(sys.argv[0])
while os.path.dirname(path) != path:
    if os.path.basename(path).startswith('Twisted'):
        sys.path.insert(0, path)
        break
    path = os.path.dirname(path)

from twisted.conch.scripts.%s import run
run()utf-8)sys
executablelist
isinstancestrencodeappend)argsmodstartmadeArgsargr&   r&   r'   	_makeArgs   s   

r   c                   @   sP   e Zd ZesdZesdZedd Zdd Zdd Z	d	d
 Z
dd Zdd ZdS )ConchServerSetupMixinzcan't run without cryptographyzCannot run without PyASN1c                   C   s   t dS )Ns   testuserr
   r&   r&   r&   r'   realmFactoryA  s   z"ConchServerSetupMixin.realmFactoryc                 C   sj  dD ]}t j|rt | qtdd}|t W d    n1 s%w   Y  tdd}|t W d    n1 s?w   Y  tdd}|t W d    n1 sYw   Y  tdd}|t	 W d    n1 ssw   Y  t 
dd t 
dd td }|jjs|jjrtdtd	d}|d
t  W d    d S 1 sw   Y  d S )N)rsa_testrsa_test.pubdsa_testdsa_test.pubkh_testr   wbr   r   r   i  zgprivate key readable by others despite chmod; possible windows permission issue? see https://tm.tl/9767r   s
   127.0.0.1 )ospathexistsremoveopenrK   r   r	   r   r   chmodr   getPermissionsgroupreadotherr   )r4   rx   permissionsr&   r&   r'   _createFilesE  s4   
"z"ConchServerSetupMixin._createFilesc                 C   s*   t   }|d | d }|  |S )N) r      )r)   r+   getsocknamer-   )r4   srl   r&   r&   r'   _getFreePort]  s
   
z"ConchServerSetupMixin._getFreePortc                 C   s.   |   }t|}|t  t }||_|S )z
        Make a L{ConchTestServerFactory}, which allows us to start a
        L{ConchTestServer} -- i.e. an actually listening conch.
        )r   r   PortalregisterCheckerr   r   )r4   realmpfactoryr&   r&   r'   _makeConchFactoryd  s   
z'ConchServerSetupMixin._makeConchFactoryc                 C   sz   |    |  | _d| j_tjd| jdd| _tdt | _| j	 j
| _tr;tjdt dd| _| j	 j
| _d S d S )Nr   r   rp   )	interfacer(   )r   r   conchFactoryexpectedLoseConnectionr   	listenTCPconchServerrP   
echoServergetHostrl   echoPortHAS_IPV6echoServerV6
echoPortV6r3   r&   r&   r'   setUpp  s   
zConchServerSetupMixin.setUpc                 C   sn   zd| j j_W n	 ty   Y nw | j jj  t| jj	t| j
j	g}tr2|t| jj	 t|S )Nr   )r   protodoneAttributeErrorrJ   rL   r   maybeDeferredr   stopListeningr   r   r   r   gatherResults)r4   	deferredsr&   r&   r'   tearDown}  s   
zConchServerSetupMixin.tearDownN)r#   r$   r%   r   r?   r   staticmethodr   r   r   r   r   r   r&   r&   r&   r'   r   :  s    
r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	ForwardingMixina  
    Template class for tests of the Conch server's ability to forward arbitrary
    protocols over SSH.

    These tests are integration tests, not unit tests. They launch a Conch
    server, a custom TCP server (just an L{EchoProtocol}) and then call
    L{execute}.

    L{execute} is implemented by subclasses of L{ForwardingMixin}. It should
    cause an SSH client to connect to the Conch server, asking it to forward
    data to the custom TCP server.
    c                 C   s   |  dt }|| jdS )z
        Test that we can use whatever client to send the command "echo goodbye"
        to the Conch server. Make sure we receive "goodbye" back from the
        server.
        echo goodbye   goodbye
executerR   addCallbackassertEqualrX   r&   r&   r'   	test_exec  s   zForwardingMixin.test_execc                 C   >   |   }t|d}| jd|d|| jf d}|| jd |S )zy
        Test that we can use whatever client to forward a local port to a
        specified port on the server.
           test
r   z-N -L%i:127.0.0.1:%isshArgsr   rk   r   r   r   r   r4   	localPortprocessrY   r&   r&   r'   test_localToRemoteForwarding     
z,ForwardingMixin.test_localToRemoteForwardingc                 C   r   )zs
        Test that we can use whatever client to forward a port from the server
        to a port locally.
        r   r   z-N -R %i:127.0.0.1:%ir   r   r   r&   r&   r'   test_remoteToLocalForwarding  r   z,ForwardingMixin.test_remoteToLocalForwardingN)r#   r$   r%   r6   r   r   r   r&   r&   r&   r'   r     s
    	r   c                   @   sH   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S )RekeyAvatara#  
    This avatar implements a shell which sends 60 numbered lines to whatever
    connects to it, then closes the session with a 0 exit status.

    60 lines is selected as being enough to send more than 2kB of traffic, the
    amount the client is configured to initiate a rekey after.
    c                 C   s   t |  t| jd< d S )Ns   session)r   rn   r!   channelLookupr3   r&   r&   r'   rn     s   
zRekeyAvatar.__init__c                    sH   t  }| t|  fdd}t|t   d dS )zE
        Write 60 lines of data to the transport, then exit.
        c                    sZ   t | }|dkr   jjjdd   d S d|f }|d}| d S )N<   s   exit-statuss       zline #%02d
r   )nextstopsessionconnsendRequestrL   r   rK   )counterilinecallrJ   r&   r'   rK     s   

z$RekeyAvatar.openShell.<locals>.writeg{Gz?N)r   ProtocolmakeConnectionr"   r   r   r   )r4   rJ   r   rK   r&   r   r'   	openShell  s   
zRekeyAvatar.openShellc                 C   s   dS )z2
        Ignore the close of the session.
        Nr&   r3   r&   r&   r'   closed      zRekeyAvatar.closedc                 C      d S rU   r&   r3   r&   r&   r'   r:        zRekeyAvatar.eofReceivedc                 C   r   rU   r&   )r4   r   commandr&   r&   r'   execCommand  r   zRekeyAvatar.execCommandc                 C   r   rU   r&   )r4   term
windowSizemodesr&   r&   r'   getPty  r   zRekeyAvatar.getPtyc                 C   r   rU   r&   )r4   newWindowSizer&   r&   r'   windowChanged  r   zRekeyAvatar.windowChangedN)r#   r$   r%   r6   rn   r   r   r:   r   r   r   r&   r&   r&   r'   r     s    !r   c                   @   s   e Zd ZdZdd ZdS )
RekeyRealmzS
    This realm gives out new L{RekeyAvatar} instances for any avatar request.
    c                 G   s   |d t  dd fS )Nr   c                   S   r   rU   r&   r&   r&   r&   r'   <lambda>  r   z*RekeyRealm.requestAvatar.<locals>.<lambda>)r   )r4   avatarIDmind
interfacesr&   r&   r'   requestAvatar  s   zRekeyRealm.requestAvatarN)r#   r$   r%   r6   r   r&   r&   r&   r'   r     s    r   c                   @   s   e Zd ZdZeZdd ZdS )RekeyTestsMixinzp
    TestCase mixin which defines tests exercising L{SSHTransportBase}'s handling
    of rekeying messages.
    c                    s.   t  } d|d} fdd}|| |S )z
        After a client-initiated rekey is completed, application data continues
        to be passed over the SSH connection.
        r   z-o RekeyLimit=2Kc                    s6   d dd tdD d }|d} | | d S )N
c                 S   s   g | ]}d |f qS )z
line #%02dr&   ).0r   r&   r&   r'   
<listcomp>"  s    zFRekeyTestsMixin.test_clientRekey.<locals>.finished.<locals>.<listcomp>r   r   )joinranger   r   )resultexpectedResultr3   r&   r'   finished!  s   
z2RekeyTestsMixin.test_clientRekey.<locals>.finished)rR   r   r   )r4   r   rY   r   r&   r3   r'   test_clientRekey  s
   
z RekeyTestsMixin.test_clientRekeyN)r#   r$   r%   r6   r   r   r   r&   r&   r&   r'   r     s    r   c                   @   s"   e Zd Zeds
dZdddZdS )OpenSSHClientMixinsshz$no ssh command-line client availabler   c                    s.   t tdd d} fdd}||S )a  
        Connects to the SSH server started in L{ConchServerSetupMixin.setUp} by
        running the 'ssh' command line tool.

        @type remoteCommand: str
        @param remoteCommand: The command (with arguments) to run on the
        remote end.

        @type process: L{ConchTestOpenSSHProcess}

        @type sshArgs: str
        @param sshArgs: Arguments to pass to the 'ssh' process.

        @return: L{defer.Deferred}
        r  r   )z-ozPubkeyAcceptedKeyTypes=ssh-dssz-Vc                    s   | dkrd}nd}t   _d|  d  }j j}||  }g }|D ]}t|tr4|	d}|
| q(t tdd |  jS )Nr   z!-oPubkeyAcceptedKeyTypes=ssh-dss r   zssh -2 -l testuser -p %i -F /dev/null -oUserKnownHostsFile=kh_test -oPasswordAuthentication=no -oHostKeyAlgorithms=ssh-rsa -a -i dsa_test  127.0.0.1 r   r  )r   DeferredrW   r   r   rl   splitr   r   r   r   r   spawnProcessr   )statusoptscmdlinerl   cmdsencodedCmdscmdr   remoteCommandr4   r   r&   r'   hasPAKTF  s.   
	

z+OpenSSHClientMixin.execute.<locals>.hasPAKT)r   r   r   )r4   r  r   r   rY   r  r&   r  r'   r   .  s
   
$zOpenSSHClientMixin.executeN)r   )r#   r$   r%   r   r?   r   r&   r&   r&   r'   r   *  s    r   c                   @   sP   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S )OpenSSHKeyExchangeTestsz\
    Tests L{SSHTransportBase}'s key exchange algorithm compatibility with
    OpenSSH.
    c                 C   s   g }zt jtdd ddgt jd}t|ts|d}| }W n	 ty*   Y nw ||vr6t	| d| 
dt d	| }|| jd
S )aI  
        Call execute() method of L{OpenSSHClientMixin} with an ssh option that
        forces the exclusive use of the key exchange algorithm specified by
        keyExchangeAlgo

        @type keyExchangeAlgo: L{str}
        @param keyExchangeAlgo: The key exchange algorithm to use

        @return: L{defer.Deferred}
        r  r   z-Qkex)stderrr   z not supported by ssh clientz
echo helloz-oKexAlgorithms=s   hello
)
subprocesscheck_outputr   STDOUTr   r   rg   r  BaseExceptionr   r   rR   r   r   )r4   keyExchangeAlgokexAlgorithmsoutputrY   r&   r&   r'   assertExecuteWithKexAlgorithms  s&   

z5OpenSSHKeyExchangeTests.assertExecuteWithKexAlgorithmc                 C   
   |  dS )zb
        The ecdh-sha2-nistp256 key exchange algorithm is compatible with
        OpenSSH
        zecdh-sha2-nistp256r  r3   r&   r&   r'   test_ECDHSHA256     
z'OpenSSHKeyExchangeTests.test_ECDHSHA256c                 C   r  )zb
        The ecdh-sha2-nistp384 key exchange algorithm is compatible with
        OpenSSH
        zecdh-sha2-nistp384r  r3   r&   r&   r'   test_ECDHSHA384  r  z'OpenSSHKeyExchangeTests.test_ECDHSHA384c                 C   r  )zb
        The ecdh-sha2-nistp521 key exchange algorithm is compatible with
        OpenSSH
        zecdh-sha2-nistp521r  r3   r&   r&   r'   test_ECDHSHA521  r  z'OpenSSHKeyExchangeTests.test_ECDHSHA521c                 C   r  )zl
        The diffie-hellman-group14-sha1 key exchange algorithm is compatible
        with OpenSSH.
        zdiffie-hellman-group14-sha1r  r3   r&   r&   r'   test_DH_GROUP14  r  z'OpenSSHKeyExchangeTests.test_DH_GROUP14c                 C   r  )zs
        The diffie-hellman-group-exchange-sha1 key exchange algorithm is
        compatible with OpenSSH.
        z"diffie-hellman-group-exchange-sha1r  r3   r&   r&   r'   test_DH_GROUP_EXCHANGE_SHA1  r  z3OpenSSHKeyExchangeTests.test_DH_GROUP_EXCHANGE_SHA1c                 C   r  )zu
        The diffie-hellman-group-exchange-sha256 key exchange algorithm is
        compatible with OpenSSH.
        z$diffie-hellman-group-exchange-sha256r  r3   r&   r&   r'   test_DH_GROUP_EXCHANGE_SHA256  s   z5OpenSSHKeyExchangeTests.test_DH_GROUP_EXCHANGE_SHA256c                 C   s   |  t| jd dS )zy
        The list of key exchange algorithms supported
        by OpenSSH client is obtained with C{ssh -Q kex}.
        zunsupported-algorithmN)assertRaisesr   r  r3   r&   r&   r'   test_unsupported_algorithm  s   z2OpenSSHKeyExchangeTests.test_unsupported_algorithmN)r#   r$   r%   r6   r  r  r  r  r   r!  r"  r$  r&   r&   r&   r'   r  m  s     	r  c                   @   s$   e Zd ZdZee ddd ZdS )OpenSSHClientForwardingTestszR
    Connection forwarding tests run against the OpenSSL command line client.
    zRequires IPv6 supportc                 C   r   )zG
        Forwarding of arbitrary IPv6 TCP connections via SSH.
        r   r   z-N -L%i:[::1]:%ir   )r   rk   r   r   r   r   r   r&   r&   r'   test_localToRemoteForwardingV6  r   z;OpenSSHClientForwardingTests.test_localToRemoteForwardingV6N)r#   r$   r%   r6   r   r   r&  r&   r&   r&   r'   r%    s    
r%  c                   @   s   e Zd ZdZdS )OpenSSHClientRekeyTestszE
    Rekeying tests run against the OpenSSL command line client.
    N)r#   r$   r%   r6   r&   r&   r&   r'   r'    rQ   r'  c                   @   s8   e Zd ZdZejdkrdZdddZdd	 Zd
d Z	dS )CmdLineClientTestszP
    Connection forwarding tests run against the Conch command line client.
    win32z!can't run cmdline client on win32r   Nc                 C   s   |du rg }t  |_| j j}d|| d | }t||  }t	j
 }t	jtj|d< g }	i }
|D ]}t|trD|d}|	| q8|D ]}|| }t|tr\|d}t|trf|d}||
|< qLtj|tj|	|
d |jS )z{
        As for L{OpenSSHClientTestCase.execute}, except it runs the 'conch'
        command line tool, not 'ssh'.
        Nz[-p {} -l testuser --known-hosts kh_test --user-authentications publickey -a -i dsa_test -v r  
PYTHONPATHr   )env)r   r  rW   r   r   rl   rf   r   r  r   environcopypathsepr   r   r   r   r   r   r   r   r  r   )r4   r  r   r   	conchArgsrl   r  r	  r+  r
  
encodedEnvvarvalr&   r&   r'   r     s<   








zCmdLineClientTests.executec                    sV    fdd}t   jdt dd jddgd}|jd	 || |S )
z4
        It can store logs to a local file.
        c                    s      }d| d S )Ns   Log opened.)
getContentassertIn)r   
logContentlogPathr4   r&   r'   cb_check_log  s   z<CmdLineClientTests.test_runWithLogFile.<locals>.cb_check_logr   z--logz	--logfilez--host-key-algorithmszssh-rsa)r  r   r/  r   )r   r   mktempr   rR   r   r   r   )r4   r8  rY   r&   r6  r'   test_runWithLogFile  s   
z&CmdLineClientTests.test_runWithLogFilec                 C   s"   | j dt d}|| jd |S )zH
        Do not use --host-key-algorithms flag on command line.
        r   )r  r   r   r   rX   r&   r&   r'   %test_runWithNoHostAlgorithmsSpecified*  s
   z8CmdLineClientTests.test_runWithNoHostAlgorithmsSpecified)r   N)
r#   r$   r%   r6   r   platformTyper?   r   r:  r;  r&   r&   r&   r'   r(    s    

%r(  )r~   )Ur   r)   r  r   	itertoolsr   unittestr   zope.interfacer   twisted.conch.errorr   twisted.conch.test.keydatar   r   r   r	   twisted.conch.test.test_sshr   twisted.credr   twisted.internetr   r   r   twisted.internet.errorr   twisted.internet.taskr   twisted.internet.utilsr   twisted.pythonr   r   r   twisted.python.filepathr   twisted.python.procutilsr   twisted.python.reflectr   twisted.trial.unittestr   r   r   r   ImportErrorr   r   twisted.conch.avatarr   twisted.conch.ssh.sessionr    r!   r"   twisted.conch.interfacestwisted.conch.scripts.conch_StdioInteractingSessioner8   r   r>   r0   r   r1   r7   r   r@   FactoryrP   ProcessProtocolrR   rk   rr   r   r   r   r   r   r   r   r  r%  r'  r(  r&   r&   r&   r'   <module>   s|   +L
S6D	C\