
    hX                        S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
r
S SKJr  S SKJrJrJrJrJr  S SKJr  S SKJr  S SKJr  S SKJr  S SKJrJr  S S	KJr  S S
K J!r!  S SK"J#r#J$r$  S SK%J&r&  S SK'J(r(J)r)J*r*  S SK+J,r,  S SK-J.r.J/r/  S SK0J1r1J2r2  S SK3J4r4  \Rj                  " S5      r6S\4S jr7S\\8   4S jr9 " S S\)5      r:SSSS.\Rv                  Er; " S S\25      r< " S S\Rz                  5      r>S \8S\?\\8   \\8   4   4S! jr@S"\\8   S#\8S$\S%\8S\?\\8   \\8   4   4
S& jrAS"\\8   S'\\8   S\?\\8   \\8   4   4S( jrB " S) S*\,5      rC " S+ S,\15      rDS0S- jrES0S. jrF\GS/:X  a  \F" 5         gg)1    N)Path)DictIterableLiteralOptionalSequence)	polyfills)ferny)
bootloader)BridgeBeibootHelper)parse_os_releasesetup_logging)ChannelRoutingRule)PackagesChannel)
JsonObjectget_str)supported_oses)PackagesPackagesLoaderpatch_libexecdir)Peer)CockpitProblemCockpitProtocolError)RouterRoutingRule)StdioTransportzcockpit.beibootreturnc                     [         R                  R                  [        R                  5      S-  n U R                  5       n[        R                  R                  S5      nUc  [        R                  R                  S5      n[        R                  " USS9  [        US5      n[        R                  SU5         UR                  5       U:w  a  [        R                  S5        [        eUR!                  5       R"                  S	-  (       d  [        R                  S
5        [        e U$ ! [$        [        4 a;    [        R                  S5        UR'                  U5        UR)                  S5         U$ f = f)zCreate askpass executable

We need this for the flatpak: ssh and thus the askpass program run on the host (via flatpak-spawn),
not the flatpak. Thus we cannot use the shipped cockpit-askpass program.
zinteraction_client.pyXDG_CACHE_HOMEz~/.cacheT)exist_okzcockpit-client-askpasszChecking if %s exists...z.  ... it exists but is not the same version...@   z;  ... it has the correct contents, but is not executable...z  ... writing contents.i  )	importlib	resourcesfilesr
   __name__
read_bytesosenvirongetpath
expandusermakedirsr   loggerdebug
ValueErrorstatst_modeFileNotFoundErrorwrite_byteschmod)src_pathsrc_dataxdg_cache_home	dest_paths       1/usr/lib/python3/dist-packages/cockpit/beiboot.pyensure_ferny_askpassr:   1   s,    ""((8;RRH""$H ZZ^^$45N++J7KK.^%=>I
LL+Y7
!X-LLIJ~~''%/LLVW 0  z* ./h's   :A,D) )AE43E4c               #      #    [         R                  " 5        HW  n U R                   HD  nUR                  S;   d  M  [	        UR
                  [        5      (       d  M6  UR
                  v   MF     MY     g 7f)N)path-existspath-not-exists)r   load_manifests
conditionsname
isinstancevaluestr)manifest	conditions     r9   get_interesting_filesrF   S   sS     "113!,,I~~!CC
S\SbSbdgHhHhoo% - 4s   6A4A4A4c                   X    \ rS rSr% \\\4   \S'   S\S\S\4S jr	S\\\4   4S jr
Srg	)
ProxyPackagesLoaderZ   file_statusrE   rB   r   c                     [        U[        5      (       d   eX R                  ;   d   eUS:X  a  U R                  U   $ US:X  a  U R                  U   (       + $ [        e)Nr<   r=   )rA   rC   rJ   KeyError)selfrE   rB   s      r9   check_condition#ProxyPackagesLoader.check_condition]   sb    %%%%%(((((%##E**++''...N    c                     Xl         g NrJ   )rM   rJ   s     r9   __init__ProxyPackagesLoader.__init__h   s    &rP   rS   N)r%   
__module____qualname____firstlineno__r   rC   bool__annotations__objectrN   rT   __static_attributes__ rP   r9   rH   rH   Z   s>    c4i 	 	V 	 	'DdO 'rP   rH   z
    import os
    def report_exists(files):
        command('cockpit.report-exists', {name: os.path.exists(name) for name in files})
    z
    import os
    def check_os_release(_argv):
        try:
            with open('/etc/os-release') as f:
                command('cockpit.check-os-release', f.read())
        except OSError:
                command('cockpit.check-os-release', "")
    z
    import os
    def force_exec(argv):
        try:
            os.execvp(argv[0], argv)
        except OSError as e:
            command('cockpit.fail-no-cockpit', str(e))
    )report_existscheck_os_release
force_execc                   X   ^  \ rS rSr% S\S'   S\4U 4S jjrS\SS4S jrSS	 jr	S
r
U =r$ )DefaultRoutingRule   zPeer | Nonepeerrouterc                 $   > [         TU ]  U5        g rR   )superrT   )rM   re   	__class__s     r9   rT   DefaultRoutingRule.__init__   s     rP   optionsr   c                     U R                   $ rR   )rd   )rM   rj   s     r9   
apply_ruleDefaultRoutingRule.apply_rule   s    yyrP   c                 T    U R                   b  U R                   R                  5         g g rR   )rd   closerM   s    r9   shutdownDefaultRoutingRule.shutdown   s    99 IIOO !rP   r]   r   N)r%   rV   rW   rX   rZ   r   rT   r   rl   rq   r\   __classcell__rh   s   @r9   rb   rb      s2    
!v !*   rP   rb   c            
           \ rS rSr% Sr\\S'   S\S\\   4S jr	S\S\S\S	\\   4S
 jr
S\S\S\\   S\S	S4
S jrSrg)AuthorizeResponder   )zferny.askpasscockpit.report-existscockpit.fail-no-cockpitcockpit.check-os-releasere   basic_passwordc                 .    Xl         X l        US LU l        g rR   )re   r|   have_basic_password)rM   re   r|   s      r9   rT   AuthorizeResponder.__init__   s    ,#1#= rP   messagesprompthintr   c           	        #    [         R                  SX!U5        U R                  (       aL  SUR                  5       ;   a8  U R                  b+  [         R                  SU5        U R                  nS U l        U$ US:X  a  g [
        R                  " SU5      n[
        R                  " SU5      n0 nU(       ac  U(       a\  UR                  S5      nUS:X  a  [         R                  S	U5        g
U SUR                  S5       S3US'   UR                  S5      US'   [        R                  " 5        S[        R                  " 5        3n	SU	 3n
U
S-   [        R                  " UR                  5       5      R                  5       -   nU R                  R                   " U4S UUUSS.UD6I S h  vN nUR#                  U
5      (       d  [%        SU SU
 35      eUR'                  U
5      R)                  5       n[        R*                  " UR                  5       5      R                  5       n[         R                  S[-        U5      5        U$  N7f)Nz3AuthorizeResponder: prompt %r, messages %r, hint %rz	password:z=AuthorizeResponder: sending Basic auth password for prompt %rnonez$\n(\w+) key fingerprint is ([^.]+)\.zauthenticity of host '([^ ]+)    z	127.0.0.1z,auto-accepting fingerprint for 127.0.0.1: %syes z login-datazhost-key   default-zX-Conversation F)timeoutr   r   r   echozAuthorizeResponder: response z does not match challenge zReturning a %d chars response)r-   r.   r~   lowerr|   researchgroupr'   getpidtimebase64	b64encodeencodedecodere   request_authorization
startswithr   removeprefixstrip	b64decodelen)rM   r   r   r   replyfp_match
host_matchargshostnamechallenge_idchallenge_prefix	challengeresponseb64s                 r9   
do_askpassAuthorizeResponder.do_askpass   s    JF^bc##v||~(E "".\^de++&*#6>  99DfMYY@&I

!''*H;&KZX
 #+1X^^A->,?{KD&nnQ/DO))+a		}5,\N;$s*V-=-=fmmo-N-U-U-WW	::9 CCGDLBH@D@EC >BC C ""#344&/z9STdSefh h##$45;;=##CJJL188:4c(mDCs   F&I(I)BIcommandr   fdsstderrNc                   ^#    [         R                  SXU5        US:X  ad  Uu  n[        [        U5      S9U R                  l        U R                  R                  R                  S[        U R                  [        /5      5        US:X  a  [        SUS   S9eUS:X  Gao  [        US   5      m[         R                  S	T5        [         R                  S
[        5        [         HC  n[        U4S jUR                  5        5       5      (       d  M-  [         R                  SU5          g    [         R                  ST5         [        S5       n[        UR!                  5       5      nS S S 5        TR'                  S5      WR'                  S5      :X  a;  TR'                  S5      UR'                  S5      :X  a  [         R                  SU5        g TR'                  STR'                  SS5      5       STR'                  SS5       3n
[        SU
S9eg ! , (       d  f       N= f! ["         a   n	[         R%                  SU	5         S n	A	g S n	A	ff = f7f)NzGot ferny command %s %s %sry   )loaderr   rz   z
no-cockpit)messager{   z'cockpit.check-os-release: remote OS: %rz,cockpit.check-os-release: supported OSes: %rc              3   P   >#    U  H  u  pTR                  U5      U:H  v   M     g 7frR   )r)   ).0kv	remote_oss      r9   	<genexpr>7AuthorizeResponder.do_custom_command.<locals>.<genexpr>   s!     Hy}}Q'1,s   #&z8cockpit.check-os-release: remote matches supported OS %rz$cockpit.check-os-release: remote: %rz/etc/os-releasezIfailed to read local /etc/os-release, skipping OS compatibility check: %sID
VERSION_IDz7cockpit.check-os-release: remote OS matches local OS %rNAME?r    )unsupported)r-   r.   r   rH   re   packagesrouting_rulesinsertr   r   r   r   r   allitemsopenreadOSErrorwarningr)   )rM   r   r   r   r   rJ   osinfofthis_oser   r   s              @r9   do_custom_command$AuthorizeResponder.do_custom_command   s    17&I--LK#+3F{3S#TDKK KK%%,,Q0B4;;Q`Pa0bc// tAw??00(a1ILLBINLLGX(HHHHLL![]cd	 ) LL?K+,.qvvx8G - }}T"gkk$&77IMM,<W[b[f[fgs[t<tVX_`&]]69==s3KLMQy}}]ikmOnNopK ;GG3 1 -, jlmns[   D	I0IH  H&H  .B!I
HH  IH   
I
*I II

I)r|   r~   re   )r%   rV   rW   rX   commandsr   rZ   r   rC   rT   r   tuplelistintr   r\   r]   rP   r9   rw   rw      s    pHN>v >x} >
B Bc B BRU BH%Hs %H% %Hd3i %HY\ %Hae %HrP   rw   commentc                     SSSU  34S4$ )Npython3z-icz# r]   r]   )r   s    r9   python_interpreterr   
  s    u7)n-r11rP   cmddestssh_askpassssh_optsc                 @   UR                  S5      u  pEnUR                  5       (       aL  UR                  S5      (       d6  UR                  S5      (       a  UR                  S5      (       a  USS nSXd/nOU/nS/UQUQ[        R
                  " U 5      P7SU< 3S	S
44$ )N:[]r   z-psshzSSH_ASKPASS=z	DISPLAY=xzSSH_ASKPASS_REQUIRE=force)
rpartitionisdigitendswithr   shlexjoin)r   r   r   r   host_portdestinations           r9   via_sshr     s    OOC(MDT||~~dmmC00??3DMM#$6$6":DT(f 	&(-

3 {o& 	# rP   envc                 &    SS/S U 5       QU Q7S4$ )Nzflatpak-spawnz--hostc              3   ,   #    U  H
  nS U 3v   M     g7f)z--env=Nr]   )r   kvs     r9   r    flatpak_spawn.<locals>.<genexpr>'  s     	&#BF2$-#s   r]   r]   )r   r   s     r9   flatpak_spawnr   $  s2    	&#	& 
	 rP   c                      ^  \ rS rSr% S\S'   S\S\S\R                  4U 4S jjr	SS
 jr
SS jrSS jrS\\   S\\   SS	4S jrSS jrS\SS	4S jrSrU =r$ )SshPeeri-  zMLiteral["always"] | Literal["never"] | Literal["supported"] | Literal["auto"]modere   r   r   c                    > X l         UR                  U l        [        R                  " 5       U l        [        U R                  R                  5      S-  U l        S U l        [        TU ])  U5        g )Nzuser-known-hosts)r   remote_bridgetempfileTemporaryDirectorytmpdirr   r@   known_hosts_filer|   rg   rT   )rM   re   r   r   rh   s       r9   rT   SshPeer.__init__0  sY    &!//113 $T[[%5%5 69K K,0 rP   r   Nc                    #    [         R                  R                  S5      (       a  U R                  5       I S h  vN   g U R	                  5       I S h  vN   g  N N7f)Nz/.flatpak-info)r'   r*   existsconnect_from_flatpakconnect_from_bastion_hostrp   s    r9   do_connect_transportSshPeer.do_connect_transport8  sE     77>>*++++---00222 .2s!   8AAAAAAc                    #    [        S5      u  pU R                  S:w  a   [        XR                  [        5       5      u  p[	        X5      u  pU R                  X5      I S h  vN   g  N7f)Ncockpit-bridge	localhost)r   r   r   r:   r   boot)rM   r   r   s      r9   r   SshPeer.connect_from_flatpak?  sX     %&67 {*s$4$46J6LMHC *ii!!!s   AA)!A'"A)c                   #    S nSS/nU R                   R                  S5      I S h  vN n[        US5      nUR                  S5      (       ax  [        R
                  " USS  5      R                  5       nUR                  S5      u  pgnUR                  S5      u  pU l        U(       a  [        R                  S	U5        US
U/-  nU R                  c  USS/-  n[        S5      u  p[        S5      n[        U[        5      (       d   e[        U5      nUR!                  5       (       d  [        R#                  SU5        [$        R&                  " S5      nUb
  USSU 3/-  nUb0  U R(                  R+                  U5        USSU R(                  < 3/-  n[-        XR.                  U/UQ76 u  pU R1                  X5      I S h  vN   g  GN N7f)Nz-ozNumberOfPasswordPrompts=1*r   zBasic     r   z,got username %s and password from Basic authz-lzPasswordAuthentication=nor   z${libexecdir}/cockpit-askpassz+Could not find cockpit-askpass helper at %rCOCKPIT_SSH_KNOWN_HOSTS_FILEzGlobalKnownHostsFile=zUserKnownHostsfile=)re   request_authorization_objectr   r   r   r   r   	partitionr|   r-   r.   r   r   rA   rC   r   r   errorr'   getenvr   
write_textr   r   r   )rM   known_hostsr   authr   decodeduser_passwordr   userr   r   askpassr   env_known_hostss                 r9   r   !SshPeer.connect_from_bastion_hostL  s    12 [[==cBB4,x((&&x|4;;=G,3,=,=d,C)Mk+8+B+B3+G(DT(KTRt$&T677D &&67 ##BC'3''''7m!!##LLFP))$BC&T2?2CDEED"!!,,[9T01F1F0IJKKD3 0 0+EEii!!!C CB 	"s"   %GGFGGGGr   r   c                   #    [        U 5      n[        R                  " [        U R                  U R
                  5      U/5      n[        R                  SX5        U R                  XUSS9I S h  vN nU R                  S:X  a  SS/44/nOHU R                  S:X  a  SS/44/nO0U R                  S	:X  a  SS/44S
/ 44/nOU R                  S:X  d   e/ n[        R                  " / UQS[        [        5       5      /4PUR                  Q[        S9nUR!                  UR#                  5       5        UR%                  5       I S h  vN   g  N N7f)Nz Launching command: cmd=%s env=%sT)r   start_new_sessionautotry_execr   alwaysr`   	supportedr_   neverr^   )gadgets)r   r
   InteractionAgentrw   re   r|   r-   r.   spawnr   r   make_bootloaderr   rF   stepsBEIBOOT_GADGETSwriter   communicate)rM   r   r   beiboot_helperagent	transportexec_cockpit_bridge_stepsstage1s           r9   r   SshPeer.bootu  sl    ,T2&&(:4;;H[H[(\^l'mn7B**Set*TT	'*48H7I6K)L(M%8+*6:J9K8M)N(O%;.*48H7I6K)LOadfchNi(j%%%000(*% ++ -
&-
t$9$;<=>-
 !!-
 #	$
 	( !!!- U, 	"s%   A,E.E/CEE
E
Ec                     S U l         g rR   )r|   rp   s    r9   do_superuser_init_doneSshPeer.do_superuser_init_done  s
    "rP   r   c                 t   [         R                  SXR                  S L5        [        US5      R	                  S5      (       aP  [        US5      nU R                  b7  [         R                  S5        U R                  SX R                  S9  S U l        g [         R                  S5        U R                  SWS	S
9  g )Nz*SshPeer.do_authorize: %r; have password %sr   zplain1:cookiez-SshPeer.do_authorize: responded with password	authorize)r   r-  r   z0SshPeer.do_authorize: authentication-unavailablezauthentication-unavailable)r   r-  problem)r-   r.   r|   r   r   write_control)rM   r   r-  s      r9   do_authorizeSshPeer.do_authorize  s    A7L_L_gkLkl7K(33I>>Wh/F"".LM"";vPcPc"d&*#GH;vGcdrP   )r|   r   r   r   r   rs   )r%   rV   rW   rX   rZ   r   rC   argparse	NamespacerT   r   r   r   r   r   r*  r   r1  r\   rt   ru   s   @r9   r   r   -  s|    
YY!v !C !x?Q?Q !3"'"R"hsm "(3- "D ":#eJ e4 e erP   r   c                   z   ^  \ rS rSr% Sr\\   \S'   \\S'   S\	R                  4U 4S jjrS rS rSS	 jrS
rU =r$ )	SshBridgei  Nr   ssh_peerr   c                    > [        U 5      n[        TU ]	  U/5        [        XR                  U5      U l        U R
                  Ul        g rR   )rb   rg   rT   r   r   r7  rd   )rM   r   rulerh   s      r9   rT   SshBridge.__init__  s?     "$'$   &6&6=MM	rP   c                     g rR   r]   rp   s    r9   do_send_initSshBridge.do_send_init  s    rP   c                 f    [         R                  SU5        U R                  R                  U5        g )NzSshBridge.do_init: %r)r-   r.   r7  r0  )rM   r   s     r9   do_initSshBridge.do_init  s%     	,g6##G,rP   c                 N    U R                   R                  U R                  5        g rR   )r7  add_done_callbackro   rp   s    r9   setup_sessionSshBridge.setup_session  s    ''

3rP   )r7  rs   )r%   rV   rW   rX   r   r   r   rZ   r   r3  r4  rT   r<  r?  rC  r\   rt   ru   s   @r9   r6  r6    s>    #'Hhx '	"X// 	"-4 4rP   r6  c                   #    [         R                  S5        [        U 5      n[        [        R
                  " 5       U5         [        UR                  R                  5       I S h  vN 5      nUR                  R                  R                  5       (       a6  UR                  SSSSUR                  R                  R                  5       0S9  UR                  S0 5      n[        U[        5      (       d  UR                  SS	S
S9  g [        U[        5      (       d   eSUS'   UR                  (       a,  [        R!                  UR                  R                  5      US'   UR                  U5        UR                  R#                  5         [         R                  S5        UR?                  5          URA                  5       I S h  vN   g  GNd! [$        R&                   Gak  n[$        R(                  R+                  [-        U5      5      n[         R                  SXE5        [        U[$        R.                  5      (       a  SnO[        U[$        R0                  5      (       a  SnO^[        U[$        R2                  5      (       a  SnO<[        U[4        5      (       a  SnO$[        U[$        R6                  5      (       a  SnOSnUR                  R                  R                  5       (       a>  UR                  SU[-        U5      UR                  R                  R                  5       S9  OUR                  SU[-        U5      S9   S nAg S nAf[8         a:  n[         R                  SU5        UR                  UR:                  SS9   S nAg S nAf[        R<                   a    [         R                  S5         g f = f GN! [B         a     g f = f7f)NzHi. How are you today?r.  zx-login-datar   zknown-hosts)r   r   r-  
login_datacapabilitiesinitzprotocol-errorzcapabilities must be a dict)r   r/  r   Tzexplicit-superuserr   z.ferny.InteractionError: %s, interpreted as: %rzauthentication-failedzinvalid-hostkeyzunknown-hostkeyzunknown-hostzinternal-error)r   r/  r   r  zCockpitProblem: %s)r   z"Peer bridge got cancelled, exitingz/Startup done.  Looping until connection closes.)"r-   r.   r6  r   asyncioget_running_loopdictr7  startr   r   r0  	read_text
setdefaultrA   r   fromkeysthaw_endpointr
   InteractionError
ssh_errorsget_exception_for_ssh_stderrrC   SshAuthenticationErrorSshChangedHostKeyErrorSshHostKeyErrorr   SshErrorr   attrsCancelledErrorrC  r"  BrokenPipeError)r   bridger   rG  excr	  r/  s          r9   runr]    s    
LL)*t_F7++-v66V__22445??++2244  #~c!6??#C#C#M#M#OW !  ))."=,--  9ISp q,-----1)* ??"&--0H0H"IGJW%%%'@ LLBC
  """u 50 !!   ==c#hGEsReU99::-Gu;;<<'Gu4455'Gw''$Gu~~..-G&G??++2244  #e*-3__-M-M-W-W-Y ! [   #e* U )3/SYY7!! 9: 	# s   A O"G %G	&BG OBG 
%O0N> N;N> O	G N8!E!MON80N	O	,N85O7N88O;N> >
OO
OOc                  T   [         R                  " 5         [        R                  " SS9n U R	                  S/ SQSSS9  U R	                  SS	S
9  U R	                  SSS9  U R                  5       n[        UR                  S9  [        R                  " [        U5      UR                  S9  g )Nz@cockpit-bridge is run automatically inside of a Cockpit session.)descriptionz--remote-bridge)r  r  r  r  r  zHow to run cockpit-bridge from the remote host: auto: if installed (default), never: always copy the local one; supported: if not installed, copy local one for compatible OSes, fail otherwise; always: fail if not installed)choicesr   helpz--debug
store_true)actionr   z5Name of the remote host to connect to, or 'localhost')ra  )r.   )
r	   installr3  ArgumentParseradd_argument
parse_argsr   r.   rI  r]  )parserr   s     r9   mainri    s    $$1stF
)3[ek8  9
 	,7
,cdD

#KKD	,rP   __main__rs   )Hr3  rI  r   importlib.resourcesr"   loggingr'   r   r   r   r   pathlibr   typingr   r   r   r   r   cockpitr	   cockpit._vendorr
   cockpit._vendor.beir   cockpit.beipackr   cockpit.bridger   r   cockpit.channelr   cockpit.channelsr   cockpit.jsonutilr   r   cockpit.osinfor   cockpit.packagesr   r   r   cockpit.peerr   cockpit.protocolr   r   cockpit.routerr   r   cockpit.transportsr   	getLoggerr-   r:   rC   rF   rH   r   rb   AskpassHandlerrw   r   r   r   r   r   r6  r]  ri  r%   r]   rP   r9   <module>r     s  $      	 	     > >  ! * / : . , 0 ) G G  A . -			,	-d D&x} &'. '&
. /6 rH-- rHj2 2hsmXc].J(K 2# c   QVW_`cWdfnorfsWsQt ,x} 8C= U8C=RZ[^R_C_=` sed sel4 4:DN-$ zF rP   