o
    b5                     @   s"  d Z 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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 ddlmZ e ZG d	d
 d
ejZG dd dejZG dd dZdd Zdd Zg dZeejG dd dejZ G dd dej!Z"dd Z#dd Z$dd Z%dd Z&dS ) z
This module contains the implementation of SSHSession, which (by default)
allows access to a shell and a python interpreter over SSH.

Maintainer: Paul Swartz
    N)implementer)EnvironmentVariableNotPermittedISessionISessionSetEnv)channelcommon
connection)
interfacesprotocol)Logger)networkStringc                   @   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d Zdd Zdd Zdd ZdS )
SSHSessiona  
    A generalized implementation of an SSH session.

    See RFC 4254, section 6.

    The precise implementation of the various operations that the remote end
    can send is left up to the avatar, usually via an adapter to an
    interface such as L{ISession}.

    @ivar buf: a buffer for data received before making a connection to a
        client.
    @type buf: L{bytes}
    @ivar client: a protocol for communication with a shell, an application
        program, or a subsystem (see RFC 4254, section 6.5).
    @type client: L{SSHSessionProcessProtocol}
    @ivar session: an object providing concrete implementations of session
        operations.
    @type session: L{ISession}
    s   sessionc                 O   s0   t jj| g|R i | d| _d | _d | _d S N    )r   
SSHChannel__init__bufclientsession)selfargskw r   ;/usr/lib/python3/dist-packages/twisted/conch/ssh/session.pyr   8   s   
zSSHSession.__init__c                 C   sn   t |\}}tjd|d | j||}|r0t| }t|}|| |t	| || _
dS td dS )Nz"Asking for subsystem "{subsystem}")	subsystem   zFailed to get subsystemr   )r   getNSloginfoavatarlookupSubsystemSSHSessionProcessProtocolwrapProcessProtocolmakeConnectionwrapProtocolr   error)r   datar   ignoredr   ppprotor   r   r   request_subsystem>   s   

zSSHSession.request_subsystemc                 C   s^   t d | jst| j| _zt| }| j| W n ty)   t d Y dS w || _	dS )NzGetting shellzError getting shellr   r   )
r   r   r   r   r   r!   	openShell	Exceptionfailurer   )r   r&   r(   r   r   r   request_shellM   s   

zSSHSession.request_shellc                 C   sv   | j s	t| j| _ t|\}}tjd|d zt| }| j || W n t	y5   tj
d|d Y dS w || _dS )NzExecuting command "{f}")fzError executing command "{f}"r   r   )r   r   r   r   r   r   r   r!   execCommandr,   r-   r   )r   r&   r/   r(   r   r   r   request_exec[   s   zSSHSession.request_execc                 C   sf   | j s	t| j| _ t|\}}}tjd||d z| j ||| W dS  ty2   td Y dS w )Nz-Handling pty request: {term!r} {windowSize!r})term
windowSizezError handling pty requestr   r   )	r   r   r   parseRequest_pty_reqr   r   getPtyr,   r-   )r   r&   r2   r3   modesr   r   r   request_pty_reqj   s   
zSSHSession.request_pty_reqc                 C   s   | j s	t| j| _ t| j stjd| j| j d dS t|d\}}}z
| j 	|| W dS  t
y8   Y dS  tyH   tjd|d Y dS w )ag  
        Process a request to pass an environment variable.

        @param data: The environment variable name and value, each encoded
            as an SSH protocol string and concatenated.
        @type data: L{bytes}
        @return: A true value if the request to pass this environment
            variable was accepted, otherwise a false value.
        zCan't handle environment variables for SSH avatar {avatar}: {session} does not provide ISessionSetEnv interface. It should be decorated with @implementer(ISession, ISessionSetEnv) to support env variables.)r   r   r      z)Error setting environment variable {name})namer   )r   r   r   r   
providedByr   warnr   r   setEnvr   r,   r-   )r   r&   r9   valuer   r   r   request_env{   s&   
zSSHSession.request_envc                 C   sL   | j s	t| j| _ t|}z	| j | W dS  ty%   td Y dS w )NzError changing window sizer   r   )r   r   r   parseRequest_window_changewindowChangedr,   r   r-   )r   r&   winSizer   r   r   request_window_change   s   
z SSHSession.request_window_changec                 C   s*   | j s|  j|7  _d S | j j| d S N)r   r   	transportwriter   r&   r   r   r   dataReceived   s   zSSHSession.dataReceivedc                 C   sJ   |t jkr| jrt| jjdr| jj| d S d S d S tjd|d d S )NwriteErrzWeird extended data: {dataType})dataType)r   EXTENDED_DATA_STDERRr   hasattrrD   rH   r   r;   )r   rI   r&   r   r   r   extReceived   s
   
zSSHSession.extReceivedc                 C   s.   | j r
| j   d S | jr| j|  d S d S rC   )r   eofReceivedr   conn	sendCloser   r   r   r   rM      
   zSSHSession.eofReceivedc                 C   s.   | j r
| j   d S | jr| jj  d S d S rC   )r   closedr   rD   loseConnectionrP   r   r   r   rR      rQ   zSSHSession.closedc                 C   s"   | j r	| j j  tj|  d S rC   )r   rD   rS   r   r   rP   r   r   r   rS      s   zSSHSession.loseConnectionN)__name__
__module____qualname____doc__r9   r   r*   r.   r1   r7   r>   rB   rG   rL   rM   rR   rS   r   r   r   r   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 )_ProtocolWrapperzS
    This class wraps a L{Protocol} instance in a L{ProcessProtocol} instance.
    c                 C   
   || _ d S rC   r)   r   r)   r   r   r   r         
z_ProtocolWrapper.__init__c                 C      | j   d S rC   )r)   connectionMaderP   r   r   r   r^         z_ProtocolWrapper.connectionMadec                 C      | j | d S rC   r)   rG   rF   r   r   r   outReceived      z_ProtocolWrapper.outReceivedc                 C   r`   rC   )r)   connectionLostr   reasonr   r   r   processEnded   rc   z_ProtocolWrapper.processEndedN)rT   rU   rV   rW   r   r^   rb   rg   r   r   r   r   rX      s    rX   c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )_DummyTransportc                 C   rY   rC   rZ   r[   r   r   r   r      r\   z_DummyTransport.__init__c                 C   s   | j j| d S rC   )r)   rD   rE   rF   r   r   r   rG         z_DummyTransport.dataReceivedc                 C   r`   rC   ra   rF   r   r   r   rE      rc   z_DummyTransport.writec                 C   s   |  d| d S r   )rE   joinr   seqr   r   r   writeSequence      z_DummyTransport.writeSequencec                 C   s   | j tj d S rC   )r)   rd   r
   connectionDonerP   r   r   r   rS      ri   z_DummyTransport.loseConnectionN)rT   rU   rV   r   rG   rE   rm   rS   r   r   r   r   rh      s    rh   c                 C   s   t | tjr
t| S | S rC   )
isinstancer
   ProtocolrX   )instr   r   r   r"      s   r"   c                 C   s   t | S rC   )rh   rZ   r   r   r   r$      s   r$   )ABRTALRMFPEHUPILLINTKILLPIPEQUITSEGVTERMUSR1USR2c                   @   s   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dZdd ZdddZdd Zdd Zdd Zdd Zdd ZdS ) r!   zI am both an L{IProcessProtocol} and an L{ITransport}.

    I am a transport to the remote endpoint and a process protocol to the
    local subsystem.
    Nc                 C   s   || _ d| _d S )NF)r   lostOutOrErrFlag)r   r   r   r   r   r     s   
z"SSHSessionProcessProtocol.__init__c                 C   s(   | j jr| j| j j d | j _d S d S rC   )r   r   rD   rE   rP   r   r   r   r^     s   z(SSHSessionProcessProtocol.connectionMadec                 C   r`   rC   r   rE   rF   r   r   r   rb   !  rc   z%SSHSessionProcessProtocol.outReceivedc                 C   s   | j tj| d S rC   )r   writeExtendedr   rJ   )r   errr   r   r   errReceived$  rn   z%SSHSessionProcessProtocol.errReceivedc                 C   s$   | j r| jj| j dS d| _ dS )zW
        EOF should only be sent when both STDOUT and STDERR have been closed.
        TN)r   r   rN   sendEOFrP   r   r   r   outConnectionLost'  s   
z+SSHSessionProcessProtocol.outConnectionLostc                 C   s   |    dS )z*
        See outConnectionLost().
        N)r   rP   r   r   r   errConnectionLost0  s   z+SSHSessionProcessProtocol.errConnectionLostc                 C   r]   rC   r   rS   re   r   r   r   rd   6  r_   z(SSHSessionProcessProtocol.connectionLostc                 C   s   | j du rCi | _ tD ]}d| }tt|d}|dur|| j |< q
tj D ]\}}|drB|dsB|| j vrB|d tj | j |< q%| j | S )z:
        Get a signal name given a signal number.
        NSIGSIG_@)	_signalValuesToNamesSUPPORTED_SIGNALSgetattrsignal__dict__items
startswithsysplatform)r   signumsignamesigvaluekvr   r   r   _getSignalName9  s   



z(SSHSessionProcessProtocol._getSignalNamec              
   C   s   |durs|j }|jdurW| |j}ttdddur*t|jr*tjd|d d}n	tjd|d d}| j	j
| j	dtt|d	d |rHd
nd td td  n|jdurstjd|jd | j	j
| j	dtd|j | j	  dS )z
        When we are told the process ended, try to notify the other side about
        how the process ended using the exit-signal or exit-status requests.
        Also, close the channel.
        N	WCOREDUMPz#exitSignal: {signame} (core dumped))r   TzexitSignal: {}Fs   exit-signal          r   zexitCode: {exitCode!r})exitCodes   exit-status>L)r=   r   r   r   osr   statusr   r   r   rN   sendRequestr   NSr   r   structpackrS   )r   rf   r   r   
coreDumpedr   r   r   rg   M  s8   


z&SSHSessionProcessProtocol.processEndedc                 C      | j jj S )z>
        Return the host from my session's transport.
        )r   rN   rD   getHostrP   r   r   r   r   n     z!SSHSessionProcessProtocol.getHostc                 C   r   )z>
        Return the peer from my session's transport.
        )r   rN   rD   getPeerrP   r   r   r   r   t  r   z!SSHSessionProcessProtocol.getPeerc                 C   r`   rC   r   rF   r   r   r   rE   z  rc   zSSHSessionProcessProtocol.writec                 C   s   | j d| d S r   )r   rE   rj   rk   r   r   r   rm   }  s   z'SSHSessionProcessProtocol.writeSequencec                 C   r]   rC   r   rP   r   r   r   rS     r_   z(SSHSessionProcessProtocol.loseConnectionrC   )rT   rU   rV   rW   r   r   r^   rb   r   r   r   rd   r   rg   r   r   rE   rm   rS   r   r   r   r   r!     s"    	

!r!   c                   @   s   e Zd Zdd ZdS )SSHSessionClientc                 C   s   | j r| j | d S d S rC   )rD   rE   rF   r   r   r   rG     s   zSSHSessionClient.dataReceivedN)rT   rU   rV   rG   r   r   r   r   r     s    r   c           	         sx   t | \}}td|dd \}}}}t |dd \ }||||f} fddtdt d dD  || fS )	zParse the data from a pty-req request into usable data.

    @returns: a tuple of (terminal type, (rows, cols, xpixel, ypixel), modes)
    >4LN   c              
      s@   g | ]}t  ||d   td |d  |d  d fqS )r   r      r   )ordr   unpack).0ir6   r   r   
<listcomp>  s    2z(parseRequest_pty_req.<locals>.<listcomp>r   r   r   )r   r   r   r   rangelen)	r&   r2   restcolsrowsxpixelypixelr'   rA   r   r   r   r4     s   

r4   c           
      C   s>   |\}}}}t | }td||||}t |}	|| |	 S )z
    Pack a pty-req request so that it is suitable for sending.

    NOTE: modes must be packed before being sent here.

    @type geometry: L{tuple}
    @param geometry: A tuple of (rows, columns, xpixel, ypixel)
    r   )r   r   r   r   )
r2   geometryr6   r   r   r   r   
termPackedwinSizePackedmodesPackedr   r   r   packRequest_pty_req  s
   	

r   c                 C   s    t d| \}}}}||||fS )zzParse the data from a window-change request into usuable data.

    @returns: a tuple of (rows, cols, xpixel, ypixel)
    r   )r   r   )r&   r   r   r   r   r   r   r   r?     s   r?   c                 C   s   | \}}}}t d||||S )z
    Pack a window-change request so that it is suitable for sending.

    @type geometry: L{tuple}
    @param geometry: A tuple of (rows, columns, xpixel, ypixel)
    r   )r   r   )r   r   r   r   r   r   r   r   packRequest_window_change  s   r   )'rW   r   r   r   r   zope.interfacer   twisted.conch.interfacesr   r   r   twisted.conch.sshr   r   r   twisted.internetr	   r
   twisted.loggerr   twisted.python.compatr   r   r   r   ProcessProtocolrX   rh   r"   r$   r   
ITransportr!   rq   r   r4   r   r?   r   r   r   r   r   <module>   s4    +w	