
    mgyB                        d Z ddlZddlZddlmZ ddlZddlZddlmZm	Z	m
Z
mZ ddlmZmZmZmZmZ ddlm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 erddlm Z  ddl!m"Z" ee	e#gdf      Z$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3de4dee4e4e5f   fdZ6dejn                  de4d e5dee4   fd!Z8 G d" d#e      Z9 G d$ d%e      Z: G d& d'      Z; G d( d)      Z<d*ee4   de4fd+Z=d*e4dee9   fd,Z>dejn                  d*ee4   de4d-e4dee#e#f   f
d.Z?d*ee4   de4d-e4d/e#d0e#ddfd1Z@dejn                  de4d*ee4   de;fd2ZAd3d4dejn                  d*ee4   d/e#d0e#dee<   fd5ZBy)6zX11 forwarding support    N)Path)TYPE_CHECKINGCallableDictIterable)
NamedTupleOptionalSequenceSetTuple   )OPEN_CONNECT_FAILED)SSHForwarderSSHForwarderCoro)SSHListenercreate_tcp_forward_listener)logger)ChannelOpenError)DataType)
SSHChannel)SSHServerConnection      i  s   MIT-MAGIC-COOKIE-1   z-c   g?ip  
   @   	localhostdisplayreturnc                 "   	 | j                  dd      \  }}|j                  d      r|j                  d      r|dd }|j                  d      }|dk\  rt	        ||dz   d       }|d| }nd}|||fS # t
        t        f$ r t        d	      dw xY w)
zParse an X11 display value:r   [].r   NzInvalid X11 display)rsplit
startswithendswithfindint
ValueErrorUnicodeEncodeError)r   hostdpynumidxscreens        ,lib/python3.12/site-packages/asyncssh/x11.py_parse_displayr3   J   s    :~~c1-f??3DMM#$6":Dkk#!8A(FDS\FF  *+ :./T9:s   A+A2 2Bloopr.   familyc                    K   	 | j                  |d|t        j                         d{   }|D cg c]
  }|d   d    c}S 7 # t        j                  $ r g cY S w xY wc c}w w)z-Look up IPv4 or IPv6 addresses of a host namer   )r5   typeN   )getaddrinfosocketSOCK_STREAMgaierror)r4   r.   r5   addrinfoais        r2   _lookup_hostr?   ^   sw     ))$&/5/A/A * C C
  ((xBqE!Hx((C?? 	 )sB   A'&A AA A'A"A'A AA'AA'c                   P    e Zd ZU dZeed<   eed<   eed<   eed<   eed<   defdZy	)
SSHXAuthorityEntryzAn entry in an Xauthority filer5   addrr/   protodatar    c           	         dt         dt        fddt        dt        ffd}dj                   | j                         || j                         || j
                         || j                         || j                        f      S )zConstruct an Xauthority entryvaluer    c                 &    | j                  dd      S )z.Construct a big-endian 16-bit unsigned integer   big)to_bytes)rF   s    r2   _uint16z-SSHXAuthorityEntry.__bytes__.<locals>._uint16w   s     >>!U++    rD   c                 ,     t        |             | z   S )z.Construct a binary string with a 16-bit lengthlen)rD   rK   s    r2   _stringz-SSHXAuthorityEntry.__bytes__.<locals>._string|   s     3t9%,,rL   rL   )r+   bytesjoinr5   rB   r/   rC   rD   )selfrP   rK   s     @r2   	__bytes__zSSHXAuthorityEntry.__bytes__t   sz    	,3 	,5 	,
	-% 	-E 	-
 xx-wtyy/A -wtzz/B +- . 	.rL   N)__name__
__module____qualname____doc__r+   __annotations__rQ   rT    rL   r2   rA   rA   k   s*    (K
KML
K.5 .rL   rA   c                        e Zd ZdZdddef fdZdedefdZdedefd	Z	e
d
edefd       Ze
dedefd       ZdeddfdZdeddfdZdeddfdZddededdf fdZ xZS )SSHX11ClientForwarderz!X11 forwarding connection handlerlistenerSSHX11ClientListenerpeerc                     t         |   |       || _        d| _        d| _        | j
                  | _        d| _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        y )NrL      r   )super__init__	_listener_inpbuf_bytes_needed_recv_prefix_recv_handler_endian_prefix_auth_proto_len_auth_data_len_auth_proto_auth_proto_pad
_auth_data_auth_data_pad)rS   r]   r_   	__class__s      r2   rc   zSSHX11ClientForwarder.__init__   sq    !+/+<+< "!rL   rF   r    c                 l    | j                   dk(  rt        |dz	  |dz  f      S t        |dz  |dz	  f      S )z Encode a 16-bit unsigned integer   B      )ri   rQ   rS   rF   s     r2   _encode_uint16z$SSHX11ClientForwarder._encode_uint16   s@     <<4%1*eck233%#+uz233rL   c                 X    | j                   dk(  r|d   dz  |d   z   S |d   dz  |d   z   S )z Decode a 16-bit unsigned integerrs   r   rt   r   )ri   rv   s     r2   _decode_uint16z$SSHX11ClientForwarder._decode_uint16   s>     <<4!HMU1X--!HMU1X--rL   lengthc                     | dz   dz  dz  S )z8Return length rounded up to the next multiple of 4 bytes   r8   rZ   )rz   s    r2   _padded_lenz!SSHX11ClientForwarder._padded_len   s     !!Q&&rL   rD   c                 @    t        |       dz  }| |r
d|z
  dz  z   S dz   S )z%Pad a string to a multiple of 4 bytesr8       rL   rN   )rD   rz   s     r2   _padzSSHX11ClientForwarder._pad   s/     TQF
f,@@C@@rL   Nc                     |dd | _         || _        | j                  |dd       | _        | j                  |dd       | _        | j
                  | _        | j                  | j                        | _        y)zParse X11 client prefixNr   r   rt   r   )	ri   rj   ry   rk   rl   _recv_auth_protorh   r}   rf   rS   rD   s     r2   rg   z"SSHX11ClientForwarder._recv_prefix   sq     BQx#224!9="11$q*=!22!--d.B.BCrL   c                     |d| j                    | _        || j                   d | _        | j                  | _        | j                  | j                        | _        y)zExtract X11 auth protocolN)rk   rm   rn   _recv_auth_datarh   r}   rl   rf   r   s     r2   r   z&SSHX11ClientForwarder._recv_auth_proto   sW       5!5!56#D$8$8$9:!11!--d.A.ABrL   c                    |d| j                    | _        || j                   d | _        	 | j                  j	                  | j                        | _        | j
                  | j                  z   | j                  z   | j                  z   | j                  z   | _        d| _        d| _        y# t        $ r d}dj                  t        dt        |      f      | j                  d      | j                  d      | j                  t        |      dz   dz        | j                  |      f      }	 | j                  |       | j!                          n# t"        $ r Y nw xY wd| _        Y w xY w)zExtract X11 auth dataNs   Invalid authentication key
rL   r      r|   r8   )rl   ro   rp   rd   validate_authrj   rm   rn   re   KeyErrorrR   rQ   rO   rw   r   write	write_eofOSErrorrh   rf   )rS   rD   reasonresponses       r2   r   z%SSHX11ClientForwarder._recv_auth_data   sS    3 3 34"4#6#6#78	1"nn::4??KDO$ !LL4+;+;; 00137??C //0DL "-  	4Fxx3v;'7!8!%!4!4R!8!%!4!4Q!7!%!4!4c&kAo!5K!L!%6!2	!4 5H

8$   DL	s6   *B( (B E$)!E
E$	EE$E
E$#E$datatypec                    | j                   r| xj                  |z  c_        | j                   ryt        | j                        | j                  k\  rI| j                  d| j                   }| j                  | j                  d | _        | j                  |       ny| j                   ry| j                  }d| _        |rt        |   ||       yy)z(Handle incoming data from the X11 clientNrL   )rh   re   rO   rf   rb   data_received)rS   rD   r   rq   s      r2   r   z#SSHX11ClientForwarder.data_received   s     LLD L$$t||$(:(::<<(;););<D#'<<0B0B0C#DDL&&t, $$ <<DDLG!$1 rL   N)rU   rV   rW   rX   r   rc   r+   rQ   rw   ry   staticmethodr}   r   rg   r   r   r   r   __classcell__)rq   s   @r2   r\   r\      s    +"!7 "| "(4C 4E 4.E .c . 'C 'C ' '
 A5 AU A A
D 
D4 
DCU Ct CE d @2% 28 2t 2 2rL   r\   c                       e Zd ZdZdej
                  dedededef
dZded	d
de	de
eeef   fdZd	d
de	fdZdefdZdedefdZy)r^   z8Client listener used to accept forwarded X11 connectionsr4   r.   r/   
auth_proto	auth_datac                 P   || _         || _        || _        || _        |j	                  d      r |j
                  | _        |dz   |z   f| _        nK|dv r|j
                  | _        d|z   f| _        n*|j                  | _        |t        t        |      z   f| _        i | _        i | _        y )N/r"   ) unixz/tmp/.X11-unix/X)_host_dpynumrm   _local_authr(   create_unix_connection_connect_coro_connect_argscreate_connectionX11_BASE_PORTr+   _remote_auth_channel)rS   r4   r.   r/   r   r   s         r2   rc   zSSHX11ClientListener.__init__  s    
%$??3373N3ND483J4G3ID\!!%!<!<D"4v"=!?D!%!7!7D"&F(C!DD79@BrL   r   chanr   single_connectionr    c                     t        |      \  }}}| j                  |k7  s| j                  |k7  rt        d      t	        j
                  t        | j                              }|| j                  |<   ||f| j                  |<   | j                  ||fS )z!Attach a channel to this listenerz)Already forwarding to another X11 display)r3   r   r   r,   osurandomrO   r   r   r   rm   )rS   r   r   r   r.   r/   r1   remote_auths           r2   attachzSSHX11ClientListener.attach  s      .g6ff::!7HIIjjT%5%5!67"-$%)+<%<k"f44rL   c                     	 | j                   j                  |      }| j                  |= t	        | j                          S # t        $ r Y !w xY w)#Detach a channel from this listener)r   popr   r   bool)rS   r   r   s      r2   detachzSSHX11ClientListener.detach+  sS    	++//5Kk* ))***  		s   (A   	AAc                    K   	  | j                   t        g| j                    d{   \  }}t        | |      S 7 # t        $ r}t	        t
        t        |            dd}~ww xY ww)z4Forward an incoming connection to the local X serverN)r   r   r   r   r   r   strr\   )rS   _r_   excs       r2   forward_connectionz'SSHX11ClientListener.forward_connection6  st     
	L.D..| D040B0BD DGAt
 %T400D 	L"#6CAtK	Ls1   A)$> <> A)> 	A&A!!A&&A)r   c                 v    | j                   |   \  }}|r| j                   |= | j                  |= | j                  S )z7Validate client auth and enforce single connection flag)r   r   r   )rS   r   r   r   s       r2   r   z"SSHX11ClientListener.validate_authC  sA     #'--"<k*!!$'rL   N)rU   rV   rW   rX   asyncioAbstractEventLoopr   rQ   rc   r   r   r+   r   r   r\   r   r   rZ   rL   r2   r^   r^     s    BCW66 Cc C3 C"C/4C(5c 5 5"&5+0s1B+C5 	+< 	+D 	+1*? 1	  	 5 	 rL   r^   c                   D    e Zd ZdZdedefdZdddedefd	Zddde	fd
Z
y)SSHX11ServerListenerz/Server listener used to forward X11 connectionstcp_listenerr   c                 >    || _         || _        t               | _        y r   )_tcp_listener_displayset	_channels)rS   r   r   s      r2   rc   zSSHX11ServerListener.__init__R  s    )&)erL   r   r   r1   r    c                 Z    | j                   j                  |       | j                  d|S )z8Attach a channel to this listener and return its displayr&   )r   addr   )rS   r   r1   s      r2   r   zSSHX11ServerListener.attachW  s%     	4 --00rL   c                     	 | j                   j                  |       | j                   s| j                  j	                          yy# t        $ r Y 3w xY w)r   TF)r   remover   r   close)rS   r   s     r2   r   zSSHX11ServerListener.detach^  sN    	NN!!$' ~~$$&  		s   A 	AAN)rU   rV   rW   rX   r   r   rc   r+   r   r   r   rZ   rL   r2   r   r   O  sE    9,[ ,3 ,
1< 1 1 1< D rL   r   	auth_pathc                     | st         j                  j                  d      } | s#t        t	        dd      j                               } | S )z'Compute the path to the Xauthority file
XAUTHORITY~z.Xauthority)r   environgetr   r   
expanduser)r   s    r2   get_xauth_pathr   m  s<     JJNN<0	S-0;;=>	rL   c           	   #   |  K   dt         dt        ffddt         ffddt        ffd}	 t        | d      5 	 	         }	 t	        | |        |        |        |              /# t        $ r Y nw xY w# t        $ r t        d      dw xY w	 ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY ww)	z&Walk the entries in an Xauthority filenr    c                 R    j                  |       }t        |      | k7  rt        |S )zRead exactly n bytes)readrO   EOFError)r   rD   	auth_files     r2   _read_byteszwalk_xauth.<locals>._read_bytes|  s(     ~~a t9>NrL   c                  <    t         j                    d      d      S )zRead a 16-bit unsigned integerrH   rI   )r+   
from_bytes)r   s   r2   _read_uint16z walk_xauth.<locals>._read_uint16  s     ~~k!ne44rL   c                                      S )zRead a stringrZ   )r   r   s   r2   _read_stringz walk_xauth.<locals>._read_string  s     <>**rL   rbzIncomplete Xauthority entryN)r+   rQ   openr   rA   r,   r   )r   r   r5   r   r   r   s      @@@r2   
walk_xauthr   y  s     s u 5# 5
+% +
)T"i)^FN,V\^-9^\^-9^= =       N$%BCMN  #""  s   ,B<B- B!A/	%A>.B!/	A;8B!:A;;B!>BB!B-  B<!B*&B- )B<*B- -	B96B<8B99B<r/   c                   K   t        |      }|j                  d      s|dv rt        j                         }|j	                  d      }g }g }t        |      D ][  }|j                  r|j                  |k7  r |j                  t        k(  rX|s#t        | |t        j                         d{   }t        j                  t        j                  |j                        }||v }n|j                  t        k(  rX|s#t        | |t        j                         d{   }t        j                  t        j                  |j                        }||v }nJ|j                  t        k(  r|j                  |j	                  d      k(  }n|j                  t         k(  rd}nd}|sD|j"                  |j$                  fc S  t'        j(                  d       t*        t-        j.                  t0              fS 7 @7 ׭w)	z1Look up Xauthority data for the specified displayr   r   r   r   asciiNidnaTFz3No xauth entry found for display: using random auth)r   r(   r:   gethostnameencoder   r/   r5   XAUTH_FAMILY_IPV4r?   AF_INET	inet_ntoprB   XAUTH_FAMILY_IPV6AF_INET6XAUTH_FAMILY_HOSTNAMEXAUTH_FAMILY_WILDrC   rD   r   debug1XAUTH_PROTO_COOKIEr   r   XAUTH_COOKIE_LEN)	r4   r   r.   r/   
ipv4_addrs
ipv6_addrsentryrB   matchs	            r2   lookup_xauthr     s    
 y)Ist'@@!!#]]7#F "J "JI&<<ELLF2<<,,#/dFNN#KK
##FNNEJJ?DJ&E\\..#/dFOO#LL
##FOOUZZ@DJ&E\\22JJ$++f"55E\\..EE;;

**1 '4 MMGHrzz*:;;;+ L Ms-   B(G/*G*+A*G/G-BG/AG/-G/r   r   c                   K   |j                  d      s|dv rt        j                         }|j                  d      }t	        |      j                  d      }t        |       } | t        z   }d}	 t        j                         t        j                  |      j                  z
  t        kD  rt        j                  |       t        t              D ]  }	 t!        |d      } n |st+        d      t-        t.        ||||      }|j1                  t3        |             t5        |       D ]h  }	|	j6                  |j6                  k7  s3|	j8                  |j8                  k7  s|	j:                  |j:                  k7  sO|j1                  t3        |	             j |j=                          t        j>                  ||        y# t        $ r Y w xY w# t"        $ r& t%        j&                  t(               d{  7   Y (w xY ww)z0Update Xauthority data for the specified displayr   r   r   r   Nxbz!Unable to acquire Xauthority lock) r(   r:   r   r   r   r   XAUTH_LOCK_SUFFIXtimer   statst_ctimeXAUTH_LOCK_DEADunlinkFileNotFoundErrorrangeXAUTH_LOCK_TRIESr   FileExistsErrorr   sleepXAUTH_LOCK_DELAYr,   rA   r   r   rQ   r   r5   rB   r/   r   replace)
r   r.   r/   r   r   new_auth_pathnew_filer   	new_entryr   s
             r2   update_xauthr    s     st'@@!!#;;vD[(Fy)I 11MH99;/888?JIIm$ #$	M40H  % <=="#8$#):yBI NN5#$I&LLI,,,

inn0L	 0 00NN5<( '
 NNJJ}i(5    	2-- 0111	2sc   A+G9.AF7 >G9GBG94AG97	G G9GG9%G6,G/-G62G95G66G9c                 |   K   t        |      \  }}}t        | |||       d{   \  }}t        | ||||      S 7 w)z>Create a listener to accept X11 connections forwarded over SSHN)r3   r   r^   )r4   r   r   r.   r/   r   r   r   s           r2   create_x11_client_listenerr    sI      %W-OD&!".tYf"MMJ	dFJ	JJ Ns   !<:<connr   c           	      x  K   t        t        t              D ]l  }	 t        | || j                  t
        t        |z          d{   }dt
        |fz  }	 t        |t
        t        |      ||       d{    t        ||      c S  y7 D# t        $ r Y }w xY w7 %# t        $ r |j                          Y  yw xY ww)z5Create a listener to forward X11 connections over SSHNz%s:%d)r   X11_DISPLAY_STARTX11_MAX_DISPLAYSr   create_x11_connectionX11_LISTEN_HOSTr   r   r  r   r,   r   r   )r  r4   r   r   r   r/   r   r   s           r2   create_x11_server_listenerr  
  s      )+;<	!<dD66!7"9 9L _f55	y/3v;)96 6 6 $L'::# =& #9  		6 	  	sp   B:'B	BB	B:B2B3B7B:B			BB:BB:BB73B:6B77B:)CrX   r   r   pathlibr   r:   r   typingr   r   r   r   r   r	   r
   r   r   	constantsr   forwardr   r   r]   r   r   loggingr   miscr   sessionr   channelr   
connectionr   rQ   _RecvHandlerr   XAUTH_FAMILY_DECNETr   r   r   r   r   r   r   r   r   r   r
  r  r  r   r+   r3   r   r?   rA   r\   r^   r   r   r   r   r  r  r  rZ   rL   r2   <module>r     sa  *   	    : : = = * 3 >  "  #/ %$/0       .          $ C  E#sC-$8  (
)W66 
)c 
)"
)'/}
). .6{2L {2|H  H V <	hsm 	 	&# &(+="> &R*<W66 *<"*3-*<7:*<"*<',UE\':*<Z+)(3- +)s +)C +)#(+)5:+)?C+)\
K7+D+D 
K.1
K08
K 	
K+@ +2+D+D08 27 DI 	%&	rL   