o
    ¯bŒd  ã                
   @   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ƒZ0e0r¯d 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r–tdƒ‚td	dƒ�}| d
t ¡ W d   ƒ d S 1 s®w   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{®Gáz„?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¡   zŠssh -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\