o b5@s"dZddlZddlZddlZddlZddlmZddlmZm Z m Z ddl m Z m Z mZddlmZmZddlmZddlmZeZGd d d e jZGd d d ejZGd ddZddZddZgdZeejGdddejZ Gdddej!Z"ddZ#ddZ$ddZ%ddZ&dS) 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)EnvironmentVariableNotPermittedISessionISessionSetEnv)channelcommon connection) interfacesprotocol)Logger) networkStringc@steZdZdZdZddZddZddZd d Zd d Z d dZ ddZ ddZ ddZ ddZddZddZdS) 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} ssessioncOs0tjj|g|Ri|d|_d|_d|_dSN)r SSHChannel__init__bufclientsession)selfargskwr;/usr/lib/python3/dist-packages/twisted/conch/ssh/session.pyr8s zSSHSession.__init__cCsnt|\}}tjd|d|j||}|r0t|}t|}|||t |||_ dSt ddS)Nz"Asking for subsystem "{subsystem}") subsystemzFailed to get subsystemr) rgetNSloginfoavatarlookupSubsystemSSHSessionProcessProtocolwrapProcessProtocolmakeConnection wrapProtocolrerror)rdatarignoredrppprotorrrrequest_subsystem>s  zSSHSession.request_subsystemcCs^td|jst|j|_z t|}|j|Wnty)tdYdSw||_ dS)Nz Getting shellzError getting shellrr) rrrrrr! openShell Exceptionfailurer)rr&r(rrr request_shellMs    zSSHSession.request_shellcCsv|js t|j|_t|\}}tjd|dz t|}|j||Wnt y5tj d|dYdSw||_ dS)NzExecuting command "{f}")fzError executing command "{f}"rr) rrrrrrrr! execCommandr,r-r)rr&r/r(rrr request_exec[s  zSSHSession.request_execcCsf|js t|j|_t|\}}}tjd||dz |j|||WdSty2tdYdSw)Nz-Handling pty request: {term!r} {windowSize!r})term windowSizezError handling pty requestrr) rrrparseRequest_pty_reqrrgetPtyr,r-)rr&r2r3modesrrrrequest_pty_reqjs  zSSHSession.request_pty_reqcCs|js t|j|_t|jstjd|j|jddSt|d\}}}z |j ||WdSt y8YdSt yHtj d|dYdSw)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.)rrrz)Error setting environment variable {name})namer) rrrr providedByrwarnrrsetEnvrr,r-)rr&r9valuerrr request_env{s&    zSSHSession.request_envcCsL|js t|j|_t|}z |j|WdSty%tdYdSw)NzError changing window sizerr)rrrparseRequest_window_change windowChangedr,rr-)rr&winSizerrrrequest_window_changes  z SSHSession.request_window_changecCs*|js |j|7_dS|jj|dSN)rr transportwriterr&rrr dataReceivedszSSHSession.dataReceivedcCsJ|tjkr|jrt|jjdr|jj|dSdSdStjd|ddS)NwriteErrzWeird extended data: {dataType})dataType)rEXTENDED_DATA_STDERRrhasattrrDrHrr;)rrIr&rrr extReceiveds zSSHSession.extReceivedcCs.|jr |jdS|jr|j|dSdSrC)r eofReceivedrconn sendCloserrrrrM zSSHSession.eofReceivedcCs.|jr |jdS|jr|jjdSdSrC)rclosedrrDloseConnectionrPrrrrRrQzSSHSession.closedcCs"|jr |jjtj|dSrC)rrDrSrrrPrrrrSs zSSHSession.loseConnectionN)__name__ __module__ __qualname____doc__r9rr*r.r1r7r>rBrGrLrMrRrSrrrrr !s!  r c@s0eZdZdZddZddZddZdd Zd S) _ProtocolWrapperzS This class wraps a L{Protocol} instance in a L{ProcessProtocol} instance. cC ||_dSrCr)rr)rrrr z_ProtocolWrapper.__init__cC|jdSrC)r)connectionMaderPrrrr^z_ProtocolWrapper.connectionMadecC|j|dSrCr)rGrFrrr outReceivedz_ProtocolWrapper.outReceivedcCr`rC)r)connectionLostrreasonrrr processEndedrcz_ProtocolWrapper.processEndedN)rTrUrVrWrr^rbrgrrrrrXs  rXc@s4eZdZddZddZddZddZd d Zd S) _DummyTransportcCrYrCrZr[rrrrr\z_DummyTransport.__init__cCs|jj|dSrC)r)rDrErFrrrrGz_DummyTransport.dataReceivedcCr`rCrarFrrrrErcz_DummyTransport.writecCs|d|dSr)rEjoinrseqrrr writeSequencez_DummyTransport.writeSequencecCs|jtjdSrC)r)rdr connectionDonerPrrrrSriz_DummyTransport.loseConnectionN)rTrUrVrrGrErmrSrrrrrhs  rhcCst|tjr t|S|SrC) isinstancer ProtocolrX)instrrrr"s r"cCst|SrC)rhrZrrrr$sr$) ABRTALRMFPEHUPILLINTKILLPIPEQUITSEGVTERMUSR1USR2c@seZdZdZdZddZddZddZd d Zd d Z d dZ dddZ ddZ dddZ ddZddZddZddZddZdS) 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. NcCs||_d|_dS)NF)rlostOutOrErrFlag)rrrrrrs z"SSHSessionProcessProtocol.__init__cCs(|jjr|j|jjd|j_dSdSrC)rrrDrErPrrrr^s z(SSHSessionProcessProtocol.connectionMadecCr`rCrrErFrrrrb!rcz%SSHSessionProcessProtocol.outReceivedcCs|jtj|dSrC)r writeExtendedrrJ)rerrrrr errReceived$rnz%SSHSessionProcessProtocol.errReceivedcCs$|jr |jj|jdSd|_dS)zW EOF should only be sent when both STDOUT and STDERR have been closed. TN)rrrNsendEOFrPrrroutConnectionLost's z+SSHSessionProcessProtocol.outConnectionLostcCs |dS)z* See outConnectionLost(). N)rrPrrrerrConnectionLost0s z+SSHSessionProcessProtocol.errConnectionLostcCr]rCrrSrerrrrd6r_z(SSHSessionProcessProtocol.connectionLostcCs|jdurCi|_tD]}d|}tt|d}|dur||j|<q tjD]\}}|drB|dsB||jvrB|dtj|j|<q%|j|S)z: Get a signal name given a signal number. NSIGSIG_@) _signalValuesToNamesSUPPORTED_SIGNALSgetattrsignal__dict__items startswithsysplatform)rsignumsignamesigvaluekvrrr_getSignalName9s     z(SSHSessionProcessProtocol._getSignalNamec Cs|durs|j}|jdurW||j}ttdddur*t|jr*tjd|dd}n tjd|dd}|j j |j dt t|d d|rHd nd t d t d n|jdurstjd |jd|j j |j dtd|j|j dS)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))rTzexitSignal: {}Fs exit-signalrzexitCode: {exitCode!r})exitCodes exit-status>L)r=rrrosrstatusrrrrN sendRequestrNSr rstructpackrS)rrfrr coreDumpedrrrrgMs8    z&SSHSessionProcessProtocol.processEndedcC|jjjS)z> Return the host from my session's transport. )rrNrDgetHostrPrrrrnz!SSHSessionProcessProtocol.getHostcCr)z> Return the peer from my session's transport. )rrNrDgetPeerrPrrrrtrz!SSHSessionProcessProtocol.getPeercCr`rCrrFrrrrEzrczSSHSessionProcessProtocol.writecCs|jd|dSr)rrErjrkrrrrm}sz'SSHSessionProcessProtocol.writeSequencecCr]rCrrPrrrrSr_z(SSHSessionProcessProtocol.loseConnectionrC)rTrUrVrWrrr^rbrrrrdrrgrrrErmrSrrrrr! s"  ! r!c@seZdZddZdS)SSHSessionClientcCs|jr |j|dSdSrC)rDrErFrrrrGszSSHSessionClient.dataReceivedN)rTrUrVrGrrrrrs rc sxt|\}}td|dd\}}}}t|dd\}||||f}fddtdtddD||fS) zParse the data from a pty-req request into usable data. @returns: a tuple of (terminal type, (rows, cols, xpixel, ypixel), modes) >4LNc s@g|]}t||dtd|d|ddfqS)rrr)ordrunpack).0ir6rr s2z(parseRequest_pty_req..rrr)rrrrrangelen) r&r2restcolsrowsxpixelypixelr'rArrrr4s   r4c Cs>|\}}}}t|}td||||}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)rrrr) r2geometryr6rrrr termPacked winSizePacked modesPackedrrrpackRequest_pty_reqs   rcCs td|\}}}}||||fS)zzParse the data from a window-change request into usuable data. @returns: a tuple of (rows, cols, xpixel, ypixel) r)rr)r&rrrrrrrr?s r?cCs|\}}}}td||||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)rr)rrrrrrrrpackRequest_window_changes r)'rWrrrrzope.interfacertwisted.conch.interfacesrrrtwisted.conch.sshrrrtwisted.internetr r twisted.loggerr twisted.python.compatr rrr ProcessProtocolrXrhr"r$r ITransportr!rqrr4rr?rrrrrs4   +w