o
    bG                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZm	Z	 d dl
mZmZ d dlmZ d dlmZ d dlmZmZmZmZmZ d dlmZmZmZ d dlmZmZ d d	lmZm Z  G d
d deZ!da"da#d a$da%d a&da'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 Z0G dd dZ1G d d! d!ej2Z2G d"d# d#ej3Z4G d$d% d%ej5Z5G d&d' d'ej6Z6d(d) Z7d*d+ Z8e9d,kre(  dS dS )-    N)ListTuple)connectdefault)ConchOptions)
ConchError)channelcommon
connection
forwardingsession)reactorstdiotask)logusage)ioTypenetworkStringc                	   @   s   e Zd ZU dZdZg dg dg dgZg dg dg dg d	g d
g dgZejdgej	ddej	ddde
 ej	ddej	dddgdZg Zeeeeeef f  ed< g Zeeeeeef f  ed< dd Zdd Zdd Zdd ZdS ) ClientOptionsz(Usage:   conch [options] host [command]
zYconch is a SSHv2 client that allows logging into a remote machine and executing commands.)escapee~)localforwardLNz<listen-port:host:port   Forward local port to remote address)remoteforwardRNz<listen-port:host:port   Forward remote port to local address)nullnzRedirect input from /dev/null.)forkfz(Fork to background after authentication.)ttytz-Tty; allocate a tty even if command is given.)nottyTzDo not allocate a tty.)noshellNz"Do not execute a shell or command.)	subsystemsz-Invoke command (mandatory) as SSH2 subsystem.)r    r"   zlisten-port:host:port)descr)r   r   commandargumentT)r(   repeat)mutuallyExclusive
optActionsextraActionslocalForwardsremoteForwardsc                 C   sv   |dkr
d| d< dS |d dkr$t |dkr$tt|d d | d< dS t |dkr0|| d< dS td	| d
 dS )z:
        Set escape character; ``none'' = disable
        noneNr   r   ^      @   zBad escape character 'z'.)lenchrordsysexit)selfesc r=   =/usr/lib/python3/dist-packages/twisted/conch/scripts/conch.py
opt_escapeP   s   zClientOptions.opt_escapec                 C   8   | d\}}}t|}t|}| j|||ff dS )zH
        Forward local port to remote address (lport:host:port)
        :N)splitintr/   append)r;   r   	localPort
remoteHost
remotePortr=   r=   r>   opt_localforward]      zClientOptions.opt_localforwardc                 C   r@   )zH
        Forward remote port to local address (rport:host:port)
        rA   N)rB   rC   r0   rD   )r;   r   rG   connHostconnPortr=   r=   r>   opt_remoteforwardf   rI   zClientOptions.opt_remoteforwardc                 G   s   || d< d || d< d S )Nhost r)   )join)r;   rM   r)   r=   r=   r>   	parseArgso   s   zClientOptions.parseArgsN)__name__
__module____qualname__synopsislongdescoptParametersoptFlagsr   Completions	CompleterCompleteUserAtHostcompDatar/   r   r   rC   __annotations__r0   r?   rH   rL   rP   r=   r=   r=   r>   r      s>   
 	


  		r   c                  C   s  t jdd  } d| v r#| d}| ||d  |  } | |d |d = | d d  D ],}z!| |}|d d dkrK| |d  d dkrKg | ||d < W q) tyU   Y q)w t azt|  W n# tjy } zt	d|  t
  t d W Y d }~nd }~ww td	 rtd
 rtd
 dkrt j}nttd
 d}nt j}t j}t| |t _nt  t  t j }zt|aW n ty   d aY nw zttjdd }W n ty   d }Y nw z0t  W trt|tjt |rttj| td rtd std sttjtj  n.trt|tjt |r)ttj| td r3td s8td sAttjtj  w w t j! rVtd sVt	d"td  t t# d S )Nr4   z-lr3      z-or   -zERROR: r   logfileza+c                  W   s   t dtS Nr   )r   	callLater	reConnect)ar=   r=   r>   <lambda>   s    zrun.<locals>.<lambda>r)   r    r"   zConnection to {} closed.rM   )$r9   argvindex
ValueErrorr   optionsparseOptionsr   
UsageErrorprintopt_helpr:   stdoutopenstderrr   startLoggingdiscardLogs	doConnectstdinfilenor    	tcgetattroldBaseExceptionsignalSIGUSR1r   run	tcsetattrTCSANOWSIGWINCHSIG_DFLisattyformat
exitStatus)argsiargur   realoutfdoldUSR1r=   r=   r>   rz   }   s   

$



rz   c                  C   s,   ddl m}  datdt t|    )Nr   failurer3   g{Gz?)	twisted.pythonr   r   r   ra   _stopReactorr   errFailurer   r=   r=   r>   handleError   s
   r   c                   C   s$   zt   W d S  ty   Y d S w N)r   stoprw   r=   r=   r=   r>   r      s
   r   c                  C   s   dt d v rt d dd\t d< t d< t jsddgt _t d } t d s*t t d< t d s3dt d< ntt d t d< t d } t d }tj}t d	 sRt| t t d	< t	t d t t
 }t| |t ||t d S )
N@rM   r4   userz~/.ssh/id_rsaz~/.ssh/id_dsaport   zhost-key-algorithms)rh   rB   	identitysgetpassgetuserrC   r   verifyHostKeygetHostKeyAlgorithmsSSHUserAuthClientSSHConnectionr   
addErrback_ebExit)rM   r   vhkuaor=   r=   r>   rr      s"   

rr   c                 C   s   d|  a tdt d S )Nzconch: exiting with error 皙?)r   r   ra   r   )r   r=   r=   r>   r      s   
r   c                  C   s.  t tjdr
tt tjr&tjD ]\} }t| t	t|t
}tj| qtjrItjD ]\}}td| d|  t|| q,tddt td rQtd rWtt  td rt rdtd	 t  td
D ](}zt| W ql ty } zd	d l}|j|jkr W Y d }~qld }~ww d S d S )N
sendIgnorez!asking for remote forwarding for rA   beforeshutdownr$   agentr   r      )hasattrconn	transport
_KeepAliverh   r/   r   	listenTCPr   SSHListenForwardingFactory SSHListenClientForwardingChannelrD   r0   r   msgrequestRemoteForwardingaddSystemEventTriggerbeforeShutdownopenChannel
SSHSessionosr   _exitsetsidrangecloseOSErrorerrnoEBADF)rE   hostportr'   rG   r   r   r   r=   r=   r>   	onConnect   sD   
r   c                   C   s   t   tjj  d S r   )r   r   r   loseConnectionr=   r=   r=   r>   rb   	  s   rb   c                  C   s8   t j} | D ]\}}td| d|  t| qd S )Nzcancelling rA   )rh   r0   r   r   r   cancelRemoteForwarding)r0   rG   r   r=   r=   r>   r     s
   r   c                   C   s   t d stdt d S d S )N	reconnectr   )rh   r   ra   r   r=   r=   r=   r>   stopConnection  s   r   c                   @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
r   c                 C   s*   || _ d | _t| j| _| jd d S )Ni,  )r   globalTimeoutr   LoopingCall
sendGloballcstart)r;   r   r=   r=   r>   __init__  s   z_KeepAlive.__init__c                 C   s2   | j jdddd}|| j td| j| _d S )Ns"   conch-keep-alive@twistedmatrix.com    r4   	wantReply   )r   sendGlobalRequestaddBoth	_cbGlobalr   ra   	_ebGlobalr   )r;   dr=   r=   r>   r   !  s
   z_KeepAlive.sendGlobalc                 C   s   | j r| j   d | _ d S d S r   )r   cancel)r;   resr=   r=   r>   r   (  s   

z_KeepAlive._cbGlobalc                 C   s    | j rd | _ | jj  d S d S r   )r   r   r   r   r;   r=   r=   r>   r   -  s   z_KeepAlive._ebGlobalN)rQ   rR   rS   r   r   r   r   r=   r=   r=   r>   r     s
    r   c                   @   sL   e 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 )r   c                 C   s   | a g | _i | _t  d S r   )r   r/   r0   r   r   r=   r=   r>   serviceStarted4  s   
zSSHConnection.serviceStartedc                 C   s(   | j }g | _ |D ]}|  qt  d S r   )r/   r   r   )r;   lfr'   r=   r=   r>   serviceStopped;  s
   

zSSHConnection.serviceStoppedc                 C   sX   t d|f}| jd|dd}td| d|  || j|| || j|| d S )N0.0.0.0s   tcpip-forwardr4   r   zrequesting remote forwarding rA   )	r   packGlobal_tcpip_forwardr   r   r   addCallback_cbRemoteForwardingr   _ebRemoteForwarding)r;   rG   r   datar   r=   r=   r>   r   B  s
   z%SSHConnection.requestRemoteForwardingc                 C   s4   t d| d|  || j|< t t| j d S )Nzaccepted remote forwarding rA   )r   r   r0   repr)r;   resultrG   r   r=   r=   r>   r   I  s   
z!SSHConnection._cbRemoteForwardingc                 C   s&   t d| d| d t | d S )Nzremote forwarding rA   z failedr   r   )r;   r   rG   r   r=   r=   r>   r   N  s   z!SSHConnection._ebRemoteForwardingc                 C   s^   t d|f}| d| td|  z| j|= W n	 ty$   Y nw tt| j d S )Nr   s   cancel-tcpip-forwardzcancelling remote forwarding )r   r   r   r   r   r0   	Exceptionr   )r;   rG   r   r=   r=   r>   r   R  s   z$SSHConnection.cancelRemoteForwardingc                 C   s|   t d| t|\}}t | j t | |d | jv r8| j|d  }t d|  t|||| dS ttjd)NzFTCP r4   zconnect forwarding )remoteWindowremoteMaxPacketr   zdon't know about that port)	r   r   r   unpackOpen_forwarded_tcpipr0   SSHConnectForwardingChannelr   r
   OPEN_CONNECT_FAILED)r;   
windowSize	maxPacketr   remoteHPorigHP	connectHPr=   r=   r>   channel_forwarded_tcpip\  s   
z%SSHConnection.channel_forwarded_tcpipc                 C   sV   t d|  t | j t| jdkrt d t  d S | jjd | | d S )Nzconnection closing r4   zstopping connectionr   )r   r   channelsr6   r   	__class__	__bases__channelClosed)r;   r   r=   r=   r>   r   l  s   

zSSHConnection.channelClosedN)rQ   rR   rS   r   r   r   r   r   r   r   r   r=   r=   r=   r>   r   3  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d Zdd Zdd Zdd ZdS )r   s   sessionc           	         s  t d j d td r jj dddd}|dd	  td
 r%d S td r-td s1td s4t  t	 }td rHtd sHd _
 j|_n j|_ fdd	|_t| _d}td rn j dttd  d S td rtd rtjd }t|tjd}td|}t||d} j d| ttj j  j dttd  d S td stjd }t|tjd}td|}t||d} j d| ttj j  j dd d S )Nzsession z openr   s   auth-agent-req@openssh.comr   r4   r   c                 S   s
   t | S r   r   xr=   r=   r>   rd     s   
 z(SSHSession.channelOpen.<locals>.<lambda>r$   r)   r    r"   r   c                    s      S r   )sendEOFr   r   r=   r>   rd     s    r   r&   s	   subsystemTERM123456784H s   pty-reqs   execs   shell)r   r   idrh   r   sendRequestr   _enterRawModer   SSHSessionClient
escapeModehandleInputdataReceivedwriteconnectionLostr   
StandardIOr	   NSr   environfcntlioctlr    
TIOCGWINSZstructunpackpackRequest_pty_reqrx   r}   _windowResized)	r;   foor   cr   termwinszwinSize
ptyReqDatar=   r   r>   channelOpen{  sJ   


zSSHSession.channelOpenc              	   C   s&  |dv rd| _ | | d S | j dkr|td krd| _ d S | j dkrd| _ |dkr4td t  d S |dkrDdd	 }td
| d S |dkrUtd | jj	
  d S |dkr| jd | jj }|  |D ]}| jtd|| jj|  qkd S | d|  d S d
| _ | | d S )N)   
   r4   r   r3      .zdisconnecting from escape   c                   S   s6   t   tj  tj  tt tj	 t
  d S r   )_leaveRawModer9   rm   flushrs   r   killgetpidrx   SIGTSTPr   r=   r=   r=   r>   _  s
   


z!SSHSession.handleInput.<locals>._r      Rzrekeying connection   #s'   
The following connections are open:
z
  #{} {}
   ~)r   r   rh   r   r   r   r   ra   r   r   sendKexInitr   r   keyssortr   r   )r;   charr  r   	channelIdr=   r=   r>   r     sF   



zSSHSession.handleInputc                 C   s   | j | d S r   )r   r   r;   r   r=   r=   r>   r        zSSHSession.dataReceivedc                 C   sT   |t jkr(tdt| d ttjtkr tjj	
| d S tj
| d S d S )Nzgot z stderr data)r
   EXTENDED_DATA_STDERRr   r   r6   r   r9   ro   strbufferr   )r;   r!   r   r=   r=   r>   extReceived  s   
zSSHSession.extReceivedc                 C   s   t d | j  d S )Nzgot eof)r   r   r   loseWriteConnectionr   r=   r=   r>   eofReceived  s   
zSSHSession.eofReceivedc                 C   s    t d|   | j|  d S )Nzremote side closed )r   r   r   	sendCloser   r=   r=   r>   closeReceived  s   zSSHSession.closeReceivedc                 C   s&   t d|   t t| jj d S )Nzclosed )r   r   r   r   r   r   r=   r=   r>   closed  s   zSSHSession.closedc                 C   s(   t td|d atdt  d S )Nz>Lr   zexit status: )rC   r  r  r   r   r   r#  r=   r=   r>   request_exit_status  s   zSSHSession.request_exit_statusc                 C   s   | j |  d S r   )r   r   r   r=   r=   r>   r     r$  zSSHSession.sendEOFc                 C      | j   d S r   )r   pauseProducingr   r=   r=   r>   stopWriting     zSSHSession.stopWritingc                 C   r/  r   )r   resumeProducingr   r=   r=   r>   startWriting  r2  zSSHSession.startWritingc                 G   sZ   t dtjd}td|}|d |d |d |d f}| j| dtjdg|R   d S )	Nr   r   r   r4   r3   r   s   window-changez!4L)	r  r  r    r  r  r  r   r   pack)r;   r   r  r  newSizer=   r=   r>   r	    s   "zSSHSession._windowResizedN)rQ   rR   rS   namer  r   r   r(  r*  r,  r-  r.  r   r1  r4  r	  r=   r=   r=   r>   r   w  s    +-r   c                   @      e Zd ZdS )r   NrQ   rR   rS   r=   r=   r=   r>   r          r   c                   @   r8  )r   Nr9  r=   r=   r=   r>   r     r:  r   c                  C   s*   t sd S tj } t| tjt da d S r`   )
_inRawModer9   rs   rt   r    r{   r|   _savedRawMode)r   r=   r=   r>   r    s
   
r  c                  C   sV  t rd S tj } zt| }|d d  }W n ty%   td Y d S w |d tj	B |d< |d tj
tjB tjB tjB tjB tjB tjB  @ |d< ttdrZ|d tj @ |d< |d tjtjB tjB tjB tjB tjB tjB  @ |d< ttdr|d tj @ |d< |d tj @ |d< d|d tj< d|d tj< |at| tj| da d S )Nznot a typewriter!r   IUCLCr   IEXTENr4      ) r;  r9   rs   rt   r    ru   rw   r   r   IGNPARISTRIPINLCRIGNCRICRNLIXONIXANYIXOFFr   r=  ISIGICANONECHOECHOEECHOKECHONLr>  OPOSTVMINVTIMEr<  r{   r|   )r   rv   newr=   r=   r>   r     sd   



	

	r   __main__):r  r   r   rx   r  r9   r    typingr   r   twisted.conch.clientr   r   twisted.conch.client.optionsr   twisted.conch.errorr   twisted.conch.sshr   r	   r
   r   r   twisted.internetr   r   r   r   r   r   twisted.python.compatr   r   r   rh   r   r   rv   r;  r<  rz   r   r   rr   r   r   rb   r   r   r   r   
SSHChannelr   r   r   r  r   rQ   r=   r=   r=   r>   <module>   sT   W<
$D 
	2
