o
    b@                     @   s  d 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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 ddlmZ dd	lmZmZmZ dd
lmZmZmZ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* ddl+m,Z, zddl-Z-W n e.y   dZ-Y nw ee$j/G dd dZ0G dd deZ1eeG dd dZ2eeG dd dZ3eeG dd dZ4G dd dZ5e*6e3e1ej e*6e2e1ej dS )z
A UNIX SSH server.
    N)implementer)ttymodes)	ConchUser)
ConchError)ISession	ISFTPFileISFTPServer)lsLine)filetransfer
forwardingsession)
FXF_APPEND	FXF_CREATFXF_EXCLFXF_READ	FXF_TRUNC	FXF_WRITE)portal)ProcessExitedAlready)Logger)
components)nativeStringc                   @   s   e Zd Zdd ZdS )UnixSSHRealmc                 G   s   t |}|d ||jfS Nr   )UnixConchUserlogout)selfusernamemind
interfacesuser r!   4/usr/lib/python3/dist-packages/twisted/conch/unix.pyrequestAvatar0   s   zUnixSSHRealm.requestAvatarN)__name__
__module____qualname__r#   r!   r!   r!   r"   r   .   s    r   c                   @   sT   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d ZdS )r   c                 C   s   t |  || _t| j| _| jd g}t D ]\}}}}||v r(|| q|| _	i | _
| jtjtjd | jdtji d S )N   )s   sessions   direct-tcpips   sftp)r   __init__r   pwdgetpwnampwdDatagrpgetgrallappendotherGroups	listenerschannelLookupupdater   
SSHSessionr   openConnectForwardingClientsubsystemLookupr
   FileTransferServer)r   r   l	groupnamepasswordgiduserlistr!   r!   r"   r(   6   s    

zUnixConchUser.__init__c                 C   s   | j dd S )N      r+   r   r!   r!   r"   getUserGroupIdI   s   zUnixConchUser.getUserGroupIdc                 C   s   | j S N)r/   r?   r!   r!   r"   getOtherGroupsL   s   zUnixConchUser.getOtherGroupsc                 C   
   | j d S )N   r>   r?   r!   r!   r"   
getHomeDirO      
zUnixConchUser.getHomeDirc                 C   rC   )N   r>   r?   r!   r!   r"   getShellR   rF   zUnixConchUser.getShellc                 C   s   t |\}}ddlm} z| j|j|t | j||ft j|d}W n
 t	y,   Y dS w || j
||f< |dkrF| d }dtd|fS dS )Nr   reactor)	interfacer<      z>L)r   unpackGlobal_tcpip_forwardtwisted.internetrJ   
_runAsUser	listenTCPSSHListenForwardingFactoryconn SSHListenServerForwardingChannelBaseExceptionr0   getHoststructpack)r   data
hostToBind
portToBindrJ   listenerr!   r!   r"   global_tcpip_forwardU   s*   

z"UnixConchUser.global_tcpip_forwardc                 C   sD   t |\}}| j||fd }|sdS | j||f= | |j dS )Nr   rL   )r   rM   r0   getrO   stopListening)r   rX   rY   rZ   r[   r!   r!   r"   global_cancel_tcpip_forwardn   s   z)UnixConchUser.global_cancel_tcpip_forwardc                 C   s:   | j  D ]}| |j q| jjd| jt| j d d S )Nz,avatar {username} logging out ({nlisteners}))r   
nlisteners)r0   valuesrO   r^   _loginfor   len)r   r[   r!   r!   r"   r   w   s   
zUnixConchUser.logoutc              	   O   sD  t  }t  }t  }|  \}}t d t d t |   t | t | zt	|}W n t
yB   |||fg}Y nw zD|D ]%}	|	d }
t|	dkrV|	d pWd}t|	dkrb|	d pci }|
|i |}qFW t d t d t | t | t | |S t d t d t | t | t | w )Nr   rL   r!   r<   )osgeteuidgetegid	getgroupsr@   setegidseteuid	setgroupsrB   iter	TypeErrorrd   )r   fargskweuidegidgroupsuidr:   ifuncrr!   r!   r"   rO      s@   












zUnixConchUser._runAsUserN)r$   r%   r&   r(   r@   rB   rE   rH   r\   r_   r   rO   r!   r!   r!   r"   r   5   s    	
r   c                   @   sn   e Zd Ze ZdddZd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 )SSHSessionForUnixConchUserNc                 C   s:   |du r
ddl m} || _|| _ddi| _d| _d| _dS )a  
        Construct an C{SSHSessionForUnixConchUser}.

        @param avatar: The L{UnixConchUser} for whom this is an SSH session.
        @param reactor: An L{IReactorProcess} used to handle shell and exec
            requests. Uses the default reactor if None.
        Nr   rI   PATHz/bin:/usr/bin:/usr/local/bin)rN   rJ   _reactoravatarenvironptyptyTuple)r   r{   rJ   r!   r!   r"   r(      s   

z#SSHSessionForUnixConchUser.__init__rL   c                 C   s  t sd S | jjjj j}tdt	|\}| j
d dd  }t }t|}t|| d }t  }|r9t jp;t j|_| jj|_||_|dd  |_||f|_|rg| jj|_t|d |_|dddf|_t t j}	|	| |	  t t j }
|
| |
  d S )NLr<   rD   g    .Ar   )!utmpr{   rR   	transportgetPeerhostrV   unpacksocket	inet_atonr~   timeint	UtmpEntryUSER_PROCESSDEAD_PROCESSut_typer}   pidut_pidut_lineut_idut_tvr   ut_usergethostbyaddrut_host
ut_addr_v6
UtmpRecord	UTMP_FILE	pututlineendutent	WTMP_FILE)r   loggedIn	ipAddresspackedIpttyNamett1t2entryabr!   r!   r"   addUTMPEntry   s0   




z'SSHSessionForUnixConchUser.addUTMPEntryc                 C   sF   || j d< || _|| _t \}}t|}|| j d< |||f| _d S )NTERMSSH_TTY)r|   winSizemodesr}   openptyre   ttynamer~   )r   term
windowSizer   masterslaver   r!   r!   r"   getPty   s   


z!SSHSessionForUnixConchUser.getPtyc           	   
   C   sB  | j s| jd td| j \}}| j }| j }| jj| j	d< || j	d< || j	d< t
j|}| jjjj }| jjjj }|j d|j d|j | j	d< |   | jj||d| g| j	|||| j d	| _|   t| j tjtjd
g| jR   | j r| !  |jj"| _#| j$|j_"| jjjj%d d S )Nz'tried to get shell without pty, failingzno ptyUSERHOMESHELL 
SSH_CLIENT-usePTY4HrL   )&r~   rb   errorr   r{   r@   rE   rH   r   r|   re   pathbasenamerR   r   r   rU   r   portgetPtyOwnershiprz   spawnProcessr}   r   fcntlioctlfilenotty
TIOCSWINSZrV   rW   r   r   setModeswriteoldWrite
_writeHacksetTcpNoDelay)	r   protort   r:   homeDirshell	shellExecpeerr   r!   r!   r"   	openShell   s>   



 

&

z$SSHSessionForUnixConchUser.openShellc           
   
   C   s   | j  \}}| j  }| j  pd}|| jd< |d|f}| j jjj }| j jjj }	|j	 d|j
 d|	j
 | jd< | jrD|   | jj|||| j|||| jpSdd| _| jre|   | jre|   | j jjjd d S )	Nz/bin/shr   z-cr   r   r   r   rL   )r{   r@   rE   rH   r|   rR   r   r   rU   r   r   r~   r   rz   r   r}   r   r   r   r   )
r   r   cmdrt   r:   r   r   commandr   r   r!   r!   r"   execCommand   s2   


 
z&SSHSessionForUnixConchUser.execCommandc              	   C   s   t | jd d }| j \}}t  t  }}t d t d zt 	| jd || W t | t | d S t | t | w )Nr<   rD   r   )
re   statr~   r{   r@   rf   rg   ri   rj   chown)r   ttyGidrt   r:   rq   rr   r!   r!   r"   r     s   



z*SSHSessionForUnixConchUser.getPtyOwnershipc           	      C   s  | j }t| }| jD ]n\}}|tjvrqtj| }t|dkrF|\}}tt|s,qt	t|}|r<|| |B ||< q|| | @ ||< q|dkrVt	td| |tj
< q|dkrft	td| |tj< qtt|slqt	t|}t|f|tj |< qt| tj| d S )Nr<   OSPEEDBISPEED)r}   r   	tcgetattrr   r   r   TTYMODESrd   hasattrgetattrr   r   bytesCC	tcsetattrTCSANOW)	r   r}   attrmode	modeValuettyModeflagttyAttrttyvalr!   r!   r"   r     s.   





z#SSHSessionForUnixConchUser.setModesc                 C   s   | j r
| j   d S d S rA   )r}   
closeStdinr?   r!   r!   r"   eofReceived8  s   z&SSHSessionForUnixConchUser.eofReceivedc              	   C   s   | j r tj| j d r t| j d d }t| j d d| | jrAz| jd W n tt	fy6   Y nw | j
  | d | jd d S )Nr<   rD   r   HUPzshell closed)r~   re   r   existsr   r   r}   signalProcessOSErrorr   loseConnectionr   rb   rc   )r   ttyGIDr!   r!   r"   closed<  s   

z!SSHSessionForUnixConchUser.closedc                 C   s0   || _ t| j tjtjdg| j R   d S )Nr   )	r   r   r   r}   r   r   r   rV   rW   )r   r   r!   r!   r"   windowChangedI  s   *z(SSHSessionForUnixConchUser.windowChangedc                 C   s\   | j dur't| j  d }|tj@ s'|tj@ r'| jjj	ddt
|   | | dS )zF
        Hack to send ignore messages when we aren't echoing.
        Nr'       )r}   r   r   r   ECHOICANONr{   rR   r   
sendIgnorerd   r   )r   rX   r   r!   r!   r"   r   M  s
   
z%SSHSessionForUnixConchUser._writeHackrA   )rL   )r$   r%   r&   r   rb   r(   r   r   r   r   r   r   r   r   r   r   r!   r!   r!   r"   rx      s    

	!rx   c                   @   s   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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 )$SFTPServerForUnixConchUserc                 C   s
   || _ d S rA   )r{   )r   r{   r!   r!   r"   r(   Z  rF   z#SFTPServerForUnixConchUser.__init__c                 C   sr   d|v rd|v rt ||d |d  d|v rt ||d  d|v r5d|v r7t ||d |d f dS dS dS )zl
        NOTE: this function assumes it runs as the logged-in user:
        i.e. under _runAsUser()
        rt   r:   permissionsatimemtimeN)re   r   chmodutimer   r   attrsr!   r!   r"   	_setAttrs]  s   z$SFTPServerForUnixConchUser._setAttrsc                 C   s&   |j |j|j|jt|jt|jdS )N)sizert   r:   r   r   r   )st_sizest_uidst_gidst_moder   st_atimest_mtimer   sr!   r!   r"   	_getAttrsi  s   z$SFTPServerForUnixConchUser._getAttrsc                 C   s"   | j  }tjt|jt|S rA   )r{   rE   re   r   joinr   )r   r   homer!   r!   r"   _absPaths  s   
z#SFTPServerForUnixConchUser._absPathc                 C   s   i S rA   r!   )r   otherVersionextDatar!   r!   r"   
gotVersionw     z%SFTPServerForUnixConchUser.gotVersionc                 C   s   t | | |||S rA   )UnixSFTPFiler  )r   filenameflagsr   r!   r!   r"   openFilez     z#SFTPServerForUnixConchUser.openFilec                 C      |  |}| jtj|S rA   )r  r{   rO   re   remove)r   r  r!   r!   r"   
removeFile}     
z%SFTPServerForUnixConchUser.removeFilec                 C   s&   |  |}|  |}| jtj||S rA   )r  r{   rO   re   rename)r   oldpathnewpathr!   r!   r"   
renameFile     

z%SFTPServerForUnixConchUser.renameFilec                 C   s,   |  |}| jtj|ff| j||ffgS rA   )r  r{   rO   re   mkdirr   r   r!   r!   r"   makeDirectory  s   
z(SFTPServerForUnixConchUser.makeDirectoryc                 C   s   |  |}| jtj| d S rA   )r  r{   rO   re   rmdirr   r   r!   r!   r"   removeDirectory  s   
z*SFTPServerForUnixConchUser.removeDirectoryc                 C   s   t | | |S rA   )UnixSFTPDirectoryr  r#  r!   r!   r"   openDirectory  s   z(SFTPServerForUnixConchUser.openDirectoryc                 C   s:   |  |}|r| jtj|}n| jtj|}| |S rA   )r  r{   rO   re   r   lstatr
  )r   r   followLinksr	  r!   r!   r"   getAttrs  s
   

z#SFTPServerForUnixConchUser.getAttrsc                 C   s    |  |}| j| j|| d S rA   )r  r{   rO   r   r   r!   r!   r"   setAttrs  s   
z#SFTPServerForUnixConchUser.setAttrsc                 C   r  rA   )r  r{   rO   re   readlinkr#  r!   r!   r"   readLink  r  z#SFTPServerForUnixConchUser.readLinkc                 C   s&   |  |}|  |}| jtj||S rA   )r  r{   rO   re   symlink)r   linkPath
targetPathr!   r!   r"   makeLink  r  z#SFTPServerForUnixConchUser.makeLinkc                 C   s   t j| |S rA   )re   r   realpathr  r#  r!   r!   r"   realPath  s   z#SFTPServerForUnixConchUser.realPathc                 C      t rA   NotImplementedError)r   extNamer  r!   r!   r"   extendedRequest  r  z*SFTPServerForUnixConchUser.extendedRequestN)r$   r%   r&   r(   r   r
  r  r  r  r  r  r!  r$  r&  r)  r*  r,  r0  r2  r7  r!   r!   r!   r"   r   X  s$    
r   c                   @   s<   e Z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  || _ d}|t@ tkr|t@ dkrtj}|t@ tkr#|t@ dkr#tj}|t@ tkr2|t@ tkr2tj}|t@ tkr=|tjO }|t	@ t	krH|tj
O }|t@ tkrS|tjO }|t@ tkr^|tjO }d|v rj|d }|d= nd}|jtj|||}|r|j|j|| || _d S )Nr   r   i  )serverr   r   re   O_RDONLYO_WRONLYO_RDWRr   O_APPENDr   O_CREATr   O_TRUNCr   O_EXCLr{   rO   openr   fd)r   r8  r  r  r   	openFlagsr   rA  r!   r!   r"   r(     s0   




zUnixSFTPFile.__init__c                 C   s   | j jtj| jS rA   )r8  r{   rO   re   closerA  r?   r!   r!   r"   rC    r  zUnixSFTPFile.closec                 C   ,   | j jtj| j|dfftj| j|ffgS r   )r8  r{   rO   re   lseekrA  read)r   offsetlengthr!   r!   r"   	readChunk      zUnixSFTPFile.readChunkc                 C   rD  r   )r8  r{   rO   re   rE  rA  r   )r   rG  rX   r!   r!   r"   
writeChunk  rJ  zUnixSFTPFile.writeChunkc                 C   s    | j jtj| j}| j |S rA   )r8  r{   rO   re   fstatrA  r
  r  r!   r!   r"   r)    s   zUnixSFTPFile.getAttrsc                 C   r3  rA   r4  )r   r   r!   r!   r"   r*    r  zUnixSFTPFile.setAttrsN)	r$   r%   r&   r(   rC  rI  rK  r)  r*  r!   r!   r!   r"   r    s    r  c                   @   s0   e Zd Zdd Zdd Zdd ZeZdd Zd	S )
r%  c                 C   s"   || _ |jtj|| _|| _d S rA   )r8  r{   rO   re   listdirfilesdir)r   r8  	directoryr!   r!   r"   r(     s   
zUnixSFTPDirectory.__init__c                 C   s   | S rA   r!   r?   r!   r!   r"   __iter__  r  zUnixSFTPDirectory.__iter__c                 C   sb   z| j d}W n	 ty   tw | jjtjtj	
| j|}t||}| j|}|||fS r   )rN  pop
IndexErrorStopIterationr8  r{   rO   re   r'  r   r  rO  r	   r
  )r   rn   r	  longnamer   r!   r!   r"   __next__  s   

zUnixSFTPDirectory.__next__c                 C   s
   g | _ d S rA   )rN  r?   r!   r!   r"   rC    rF   zUnixSFTPDirectory.closeN)r$   r%   r&   r(   rQ  rV  nextrC  r!   r!   r!   r"   r%    s    r%  )7__doc__r   r,   re   r}   r)   r   rV   r   r   zope.interfacer   twisted.conchr   twisted.conch.avatarr   twisted.conch.errorr   twisted.conch.interfacesr   r   r   twisted.conch.lsr	   twisted.conch.sshr
   r   r   twisted.conch.ssh.filetransferr   r   r   r   r   r   twisted.credr   twisted.internet.errorr   twisted.loggerr   twisted.pythonr   twisted.python.compatr   r   ImportErrorIRealmr   r   rx   r   r  r%  registerAdapterr!   r!   r!   r"   <module>   sV    i :V1