
    mg[                     N   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
mZmZmZmZ ddlmZmZ ddlmZ ddlmZmZ dd	lmZmZmZmZmZ dd
lmZmZm Z  ddlm!Z!m"Z" erddl#m$Z$  G d de      Z% G d de      Z&	 ejN                  dk(  rddl(m)Z) nddl*m)Z)  G d de      Z.ee-e.f   Z/dZ0dZ1dZ2dZ3dZ4dZ5dZ6dZ7d Z8d!Z9d"Z:d#Z;d$Z<d%Z=d&Z>d'Z?d(Z@dZAd)ZBd*ZCd)ZDd+ZE G d, d-e       ZF G d. d/      ZG G d0 d1      ZHed3de/dd/fd2       ZIy# e+$ rZ,de-dee%e&f   fdZ)Y dZ,[,dZ,[,ww xY w)4SSH agent client    N)TracebackType)TYPE_CHECKINGListOptionalSequenceTupleTypeUnion)ProtocolSelf   )SSHForwardListener)async_context_managermaybe_wait_closed)ByteStringUInt32PacketDecodeError	SSHPacket)KeyPairListArgSSHCertificate
SSHKeyPair)load_default_keypairsload_keypairs)TemporaryDirectoryc                        e Zd ZdZdedefdZy)AgentReaderz&Protocol for reading from an SSH agentnreturnc                    K   yw)z'Read exactly n bytes from the SSH agentN )selfr   s     .lib/python3.12/site-packages/asyncssh/agent.pyreadexactlyzAgentReader.readexactly,           N)__name__
__module____qualname____doc__intbytesr%   r"       r$   r   r   )   s    063 65 6r.   r   c                   0    e Zd ZdZdeddfdZddZddZy)	AgentWriterz$Protocol for writing to an SSH agentdatar    Nc                      y)zWrite bytes to the SSH agentNr"   r#   r1   s     r$   writezAgentWriter.write3       r.   c                      y)z!Close connection to the SSH agentNr"   r#   s    r$   closezAgentWriter.close6   r5   r.   c                    K   yw)z1Wait for the connection to the SSH agent to closeNr"   r7   s    r$   wait_closedzAgentWriter.wait_closed9   r&   r'   r    N)r(   r)   r*   r+   r-   r4   r8   r:   r"   r.   r$   r0   r0   0   s#    .+% +D +0@r.   r0   win32)
open_agent
agent_pathr    c                 ^   K   t        t        j                  dt        t              z        w)z6Dummy function if we're unable to import agent supportzAgent support unavailable: %s)OSErrorerrnoENOENTstr_exc)r>   s    r$   r=   r=   C   s#      ell$Cc$i$OPPs   +-c                   &    e Zd ZdZdeeef   fdZy)_SupportsOpenAgentConnectionz+A class that supports open_agent_connectionr    c                    K   yw)z8Open a forwarded ssh-agent connection back to the clientNr"   r7   s    r$   open_agent_connectionz2_SupportsOpenAgentConnection.open_agent_connectionM   r&   r'   N)r(   r)   r*   r+   r	   r   r0   rH   r"   r.   r$   rF   rF   J   s    5GU;3K-L Gr.   rF                                                               c                        e Zd ZdZdZdddededef fdZedefd	       Z	edefd
       Z
deddf fdZdeddf fdZdedefdZddZ xZS )SSHAgentKeyPairz,Surrogate for a key managed by the SSH agentagentSSHAgentClient	algorithmpublic_datacommentc                    |j                  d      }|r |j                  d      r	|d d dz   }n|d d }n|}|dk(  rt        j                  dk7  rd}n|f}|r|f}n|}t        	|   ||||||       || _        || _        d| _        y )	Ns   -cert-v01@openssh.com   sk-is   @openssh.com   ssh-rsar<   )   rsa-sha2-256   rsa-sha2-512rf   r   )	endswith
startswithsysplatformsuper__init___agent_is_cert_flags)
r#   r_   ra   rb   rc   is_certsig_algorithmsig_algorithmshost_key_algorithms	__class__s
            r$   rn   zSSHAgentKeyPair.__init__x   s    $$%=>##F+ )$3/ A )$3%M J&3<<7+B>  ,-N4=<"0M>,k7	D r.   r    c                     | j                   S )z/ Return if this key pair has an associated cert)rp   r7   s    r$   has_certzSSHAgentKeyPair.has_cert   s     }}r.   c                      y)z; Return if this key pair has an associated X.509 cert chainFr"   r7   s    r$   has_x509_chainzSSHAgentKeyPair.has_x509_chain   s     r.   certNc                 2    t         |   |       d| _        y)z$Set certificate to use with this keyTN)rm   set_certificaterp   )r#   r{   rv   s     r$   r}   zSSHAgentKeyPair.set_certificate   s     	%r.   rs   c                     t         |   |       |dv r| xj                  t        z  c_        y|dk(  r| xj                  t        z  c_        yy)z4Set the signature algorithm to use when signing data)rg   s   x509v3-rsa2048-sha256rh   N)rm   set_sig_algorithmrq   SSH_AGENT_RSA_SHA2_256SSH_AGENT_RSA_SHA2_512)r#   rs   rv   s     r$   r   z!SSHAgentKeyPair.set_sig_algorithm   sF     	!-0GGKK11Ko-KK11K .r.   r1   c                    K   | j                   j                  | j                  || j                         d{   S 7 w)z9Asynchronously sign a block of data with this private keyN)ro   signkey_public_datarq   r3   s     r$   
sign_asynczSSHAgentKeyPair.sign_async   s1      [[%%d&:&:D$++NNNNs   5><>c                 X   K   | j                   j                  | g       d{    y7 w)z#Remove this key pair from the agentN)ro   remove_keysr7   s    r$   removezSSHAgentKeyPair.remove   s"      kk%%tf---s    *(*r;   )r(   r)   r*   r+   	_key_typer-   rn   propertyboolrx   rz   r   r}   r   r   r   __classcell__)rv   s   @r$   r^   r^   s   s    6I. 5 #.3@ $  
   
N t 2u 2 2OU Ou O
.r.   r^   c                      e Zd ZdZdefdZdefdZdee	e
      dee
   dee   defd	Zd'dZedee   dedefd       Zd'dZdededeeef   fdZd(deee      dee   fdZ	 d)dedededefdZ	 	 	 	 d*dedee   dee   dedd
f
dZ	 	 	 d+dedee   dee   dedd
f
dZdee   dd
fdZ	 d(dedee   dd
fd Z d'd!Z!dedd
fd"Z"dedd
fd#Z#dee   fd$Z$d'd%Z%d'd&Z&y
),r`   r   r>   c                 `    || _         d | _        d | _        t        j                         | _        y N)_agent_path_reader_writerasyncioLock_lock)r#   r>   s     r$   rn   zSSHAgentClient.__init__   s%    %.2.2\\^
r.   r    c                    K   | S w)z;Allow SSHAgentClient to be used as an async context managerr"   r7   s    r$   
__aenter__zSSHAgentClient.__aenter__   s      s   exc_type	exc_value	tracebackc                 @   K   | j                          d{    y7 w)z?Wait for connection close when used as an async context managerNF)_cleanup)r#   r   r   r   s       r$   	__aexit__zSSHAgentClient.__aexit__   s     
 mmo 	s   Nc                 `   K   | j                          | j                          d{    y7 w)zClean up this SSH agent clientN)r8   r:   r7   s    r$   r   zSSHAgentClient._cleanup   s#      	

   s   $.,.lifetimeconfirmc                 r    d}| r|t        t              t        |       z   z  }|r|t        t              z  }|S )zEncode key constraintsr.   )r   SSH_AGENT_CONSTRAIN_LIFETIMEr   SSH_AGENT_CONSTRAIN_CONFIRM)r   r   results      r$   encode_constraintsz!SSHAgentClient.encode_constraints   s>     d786(;KKKFd677Fr.   c                    K   t        | j                  t              r+t        | j                         d{   \  | _        | _        y| j                  j                          d{   \  | _        | _        y7 B7 w)zConnect to the SSH agentN)
isinstancer   rC   r=   r   r   rH   r7   s    r$   connectzSSHAgentClient.connect   sd      d&&,/9$:J:J/K)K&DL$, &&<<>> 'DL$, *L ?s!   3A<A8/A<%A:&A<:A<msgtypeargsc                    K   | j                   4 d{    	 | j                  s| j                          d{    | j                  }| j                  }|J |J t	        |      dj                  |      z   }|j                  t        t        |            |z          t        j                  |j                  d       d{   d      }t        |j                  |       d{         }|j                         }||fcddd      d{    S 7 7 7 U7 47 # t        t        t         f$ r3}	| j#                          d{  7   t%        t'        |	            dd}	~	ww xY w# 1 d{  7  sw Y   yxY ww)zSend an SSH agent requestNr.   r\   big)r   r   r   r   r   joinr4   r   lenr,   
from_bytesr%   r   get_byter@   EOFErrorr   r   
ValueErrorrC   )
r#   r   r   readerwriterpayloadresplenrespresptypeexcs
             r$   _make_requestzSSHAgentClient._make_request   s1     :::5||,,.(())))))w-#((4.8VCL1G;<..0B0B10E*EN (:(:7(C"CE==?~' :: ) +F"C! ( X'89 5mmo%% S*45) ::s   E>DE>E)DDB
DD
"D&D
'DE>DE>DDDE>E&3E!E	E!!E&&E))E;/E20E;7E>
identitiesc           	        K   | j                  t               d{   \  }}|t        k(  rg }|j                         }t	        |      D ]a  }|j                         }|j                         }|r||vr*t        |      }	|	j                         }
|j                  t        | |
||             c |j                          |S t        d|z        7 w)a  Request the available client keys

           This method is a coroutine which returns a list of client keys
           available in the ssh-agent.

           :param identities: (optional)
               A list of allowed byte string identities to return. If empty,
               all identities on the SSH agent will be returned.

           :returns: A list of :class:`SSHKeyPair` objects

        NUnknown SSH agent response: %d)r   SSH_AGENTC_REQUEST_IDENTITIESSSH_AGENT_IDENTITIES_ANSWER
get_uint32range
get_stringr   appendr^   	check_endr   )r#   r   r   r   r   num_keys_key_blobrc   packetra   s              r$   get_keyszSSHAgentClient.get_keys  s       $$%BCC 	$ 22')F(H8_??,//+(*"<"8,"--/	odI.6A B % NNM=HII- Ds   CCB2Cr   r1   flagsc                 $  K   | j                  t        t        |      t        |      t        |             d{   \  }}|t        k(  r"|j                         }|j                          |S |t        k(  rt        d      t        d|z        7 Tw)z+Sign a block of data with the requested keyNz!Unable to sign with requested keyr   )	r   SSH_AGENTC_SIGN_REQUESTr   r   SSH_AGENT_SIGN_RESPONSEr   r   SSH_AGENT_FAILUREr   )r#   r   r1   r   r   r   sigs          r$   r   zSSHAgentClient.sign7  s       $112I282B28,u O O$ ..//#CNNJ**@AA=HIIOs   7BBABkeylist
passphrasec           	        K   |rt        ||      }d}nt        |      }d}| j                  ||      }t        j                  j                  d      xs d}t        t              t        d      z   t        |      z   }	|D ]  }
|}|
j                  j                  d      r||	z  }|rt        nt        }|
j                         }| j                  ||
j                         t        |xs d      |       d{   \  }}|t         k(  r|j#                          |t$        k(  r|rt'        d	      t'        d
|z         y7 Hw)a4  Add keys to the agent

           This method adds a list of local private keys and optional
           matching certificates to the agent.

           :param keylist: (optional)
               The list of keys to add. If not specified, an attempt will
               be made to load keys from the files
               :file:`.ssh/id_ed25519_sk`, :file:`.ssh/id_ecdsa_sk`,
               :file:`.ssh/id_ed448`, :file:`.ssh/id_ed25519`,
               :file:`.ssh/id_ecdsa`, :file:`.ssh/id_rsa` and
               :file:`.ssh/id_dsa` in the user's home directory with
               optional matching certificates loaded from the files
               :file:`.ssh/id_ed25519_sk-cert.pub`,
               :file:`.ssh/id_ecdsa_sk-cert.pub`,
               :file:`.ssh/id_ed448-cert.pub`,
               :file:`.ssh/id_ed25519-cert.pub`,
               :file:`.ssh/id_ecdsa-cert.pub`, :file:`.ssh/id_rsa-cert.pub`,
               and :file:`.ssh/id_dsa-cert.pub`. Failures when adding keys
               are ignored in this case, as the agent may not recognize
               some of these key types.
           :param passphrase: (optional)
               The passphrase to use to decrypt the keys.
           :param lifetime: (optional)
               The time in seconds after which the keys should be
               automatically deleted, or `None` to store these keys
               indefinitely (the default).
           :param confirm: (optional)
               Whether or not to require confirmation for each private
               key operation which uses these keys, defaulting to `False`.
           :type keylist: *see* :ref:`SpecifyingPrivateKeys`
           :type passphrase: `str`
           :type lifetime: `int` or `None`
           :type confirm: `bool`

           :raises: :exc:`ValueError` if the keys cannot be added

        FTSSH_SK_PROVIDERinternalzsk-provider@openssh.comre   r.   NzUnable to add keyr   )r   r   r   osenvirongetr   SSH_AGENT_CONSTRAIN_EXTENSIONr   ra   rj   SSH_AGENTC_ADD_ID_CONSTRAINEDSSH_AGENTC_ADD_IDENTITYget_comment_bytesr   get_agent_private_keySSH_AGENT_SUCCESSr   r   r   )r#   r   r   r   r   keypairsignore_failuresbase_constraintsprovidersk_constraintskeypairconstraintsr   rc   r   r   s                   r$   add_keyszSSHAgentClient.add_keysH  sJ    V $Wj9H#O,Z8H"O228WE::>>"34B
;< 9:;)*  G*K  ++F3~-7B31  //1G (()0)F)F)H)/3)?N N Hd
 ,, ..&$%899 !AH!LMM-  Ns   C2D?4D=5,D?"D?r   pinc                 0  K   | j                  ||      }|rt        nt        }| j                  |t	        |      t	        |xs d      |       d{   \  }}|t
        k(  r|j                          y|t        k(  rt        d      t        d|z        7 Cw)aM  Store keys associated with a smart card in the agent

           :param provider:
               The name of the smart card provider
           :param pin: (optional)
               The PIN to use to unlock the smart card
           :param lifetime: (optional)
               The time in seconds after which the keys should be
               automatically deleted, or `None` to store these keys
               indefinitely (the default).
           :param confirm: (optional)
               Whether or not to require confirmation for each private
               key operation which uses these keys, defaulting to `False`.
           :type provider: `str`
           :type pin: `str` or `None`
           :type lifetime: `int` or `None`
           :type confirm: `bool`

           :raises: :exc:`ValueError` if the keys cannot be added

         NzUnable to add keysr   )	r   (SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINEDSSH_AGENTC_ADD_SMARTCARD_KEYr   r   r   r   r   r   )	r#   r   r   r   r   r   r   r   r   s	            r$   add_smartcard_keysz!SSHAgentClient.add_smartcard_keys  s     4 --h@$ ;*F 	  $11'6(;K282C2= ? ?$ ((NN**122=HII?s   ABBABc                    K   |D ]q  }| j                  t        t        |j                               d{   \  }}|t        k(  r|j                          Q|t        k(  rt        d      t        d|z         y7 Ew)zRemove a key stored in the agent

           :param keylist:
               The list of keys to remove.
           :type keylist: `list` of :class:`SSHKeyPair`

           :raises: :exc:`ValueError` if any keys are not found

        NzKey not foundr   )r   SSH_AGENTC_REMOVE_IDENTITYr   rb   r   r   r   r   )r#   r   r   r   r   s        r$   r   zSSHAgentClient.remove_keys  s      G(()C)/0C0C)DF F Hd ,, .. 11 !AH!LMM Fs   2A<A:AA<c                    K   | j                  t        t        |      t        |xs d             d{   \  }}|t        k(  r|j	                          y|t
        k(  rt        d      t        d|z        7 Cw)aw  Remove keys associated with a smart card stored in the agent

           :param provider:
               The name of the smart card provider
           :param pin: (optional)
               The PIN to use to unlock the smart card
           :type provider: `str`
           :type pin: `str` or `None`

           :raises: :exc:`ValueError` if the keys are not found

        r   NzKeys not foundr   )r   SSH_AGENTC_REMOVE_SMARTCARD_KEYr   r   r   r   r   )r#   r   r   r   r   s        r$   remove_smartcard_keysz$SSHAgentClient.remove_smartcard_keys  s}       $$%D%+H%5vciR7HJ J 	$ ((NN**-..=HIIJs   1A9A7AA9c                    K   | j                  t               d{   \  }}|t        k(  r|j                          y|t        k(  rt        d      t        d|z        7 Cw)zqRemove all keys stored in the agent

           :raises: :exc:`ValueError` if the keys can't be removed

        NzUnable to remove all keysr   )r    SSH_AGENTC_REMOVE_ALL_IDENTITIESr   r   r   r   )r#   r   r   s      r$   
remove_allzSSHAgentClient.remove_all  sd      $$%EFF 	$ ((NN**899=HII Gs   A!AAA!c                    K   | j                  t        t        |             d{   \  }}|t        k(  r|j	                          y|t
        k(  rt        d      t        d|z        7 Cw)a  Lock the agent using the specified passphrase

           .. note:: The lock and unlock actions don't appear to be
                     supported on the Windows 10 OpenSSH agent.

           :param passphrase:
               The passphrase required to later unlock the agent
           :type passphrase: `str`

           :raises: :exc:`ValueError` if the agent can't be locked

        NzUnable to lock SSH agentr   )r   SSH_AGENTC_LOCKr   r   r   r   r   r#   r   r   r   s       r$   lockzSSHAgentClient.lock  sn       $11/282D F F$ ((NN**788=HIIF   #A+A)AA+c                    K   | j                  t        t        |             d{   \  }}|t        k(  r|j	                          y|t
        k(  rt        d      t        d|z        7 Cw)a  Unlock the agent using the specified passphrase

           .. note:: The lock and unlock actions don't appear to be
                     supported on the Windows 10 OpenSSH agent.

           :param passphrase:
               The passphrase to use to unlock the agent
           :type passphrase: `str`

           :raises: :exc:`ValueError` if the agent can't be unlocked

        NzUnable to unlock SSH agentr   )r   SSH_AGENTC_UNLOCKr   r   r   r   r   r   s       r$   unlockzSSHAgentClient.unlock  so       $112C282D F F$ ((NN**9::=HIIFr   c                 P  K   | j                  t        t        d             d{   \  }}|t        k(  r<g }|r6|j	                         }	 |j                  d      }|j                  |       |r6|S |t        k(  rg S t        d|z        7 e# t        $ r t        d      dw xY ww)zReturn a list of extensions supported by the agent

           :returns: A list of strings of supported extension names

        queryNzutf-8zInvalid extension type namer   )
r   SSH_AGENTC_EXTENSIONr   r   r   decodeUnicodeDecodeErrorr   r   r   )r#   r   r   r   exttypeexttype_strs         r$   query_extensionszSSHAgentClient.query_extensions5  s       $112F28/ C C$ ((F//+N").."9K k*  M**I=HII)C * N$%BCMNs-   #B&B$B&B B&0B&B##B&c                 R    | j                   r| j                   j                          yy)zClose the SSH agent connection

           This method closes the connection to the ssh-agent. Any
           attempts to use this :class:`SSHAgentClient` or the key
           pairs it previously returned will result in an error.

        N)r   r8   r7   s    r$   r8   zSSHAgentClient.closeR  s      <<LL  r.   c                    K   | j                   r,t        | j                          d{    d| _        d| _         yy7 w)zWait for this agent connection to close

           This method is a coroutine which can be called to block until
           the connection to the agent has finished closing.

        N)r   r   r   r7   s    r$   r:   zSSHAgentClient.wait_closed^  s7      <<#DLL111DLDL	 1s   %><>r;   r   )r   )r"   NNF)NNF)'r(   r)   r*   r+   
_AgentPathrn   r   r   r   r
   BaseExceptionr   r   r   r   staticmethodr,   r-   r   r   r	   r   r   r   r   r   r   r   rC   r   r   r   r   r   r   r   r  r8   r:   r"   r.   r$   r`   r`      s3   $: $$ 
m1D(E #+M#:#+M#:?C! Xc] T e  ?53 5u 5#y.!58&J(5/)B &JZ &JR !"J5 J JJ&+J" 8:3715',PNn PN#+C=PN!)#PN !%PN 26PNf 7;;?16'J 'J&.sm'J+3C='J +/'J <@'JRN*)= N$ N0 :>JC J)1#JBFJ4J"JS JT J0Js Jt J0J J:
! r.   r`   c                   8    e Zd ZdZdddedefdZdefdZdd
Zy	)SSHAgentListenerz*Listener used to forward agent connectionstempdirzTemporaryDirectory[str]pathunix_listenerc                 .    || _         || _        || _        y r   )_tempdir_path_unix_listener)r#   r  r  r  s       r$   rn   zSSHAgentListener.__init__p  s    
+r.   r    c                     | j                   S )z!Return the path being listened on)r  r7   s    r$   get_pathzSSHAgentListener.get_pathv  s     zzr.   Nc                 l    | j                   j                          | j                  j                          y)zClose the agent listenerN)r  r8   r  cleanupr7   s    r$   r8   zSSHAgentListener.close{  s&     	!!#r.   r;   )	r(   r)   r*   r+   rC   r   rn   r  r8   r"   r.   r$   r
  r
  m  s2    4, 9 , , 2,# 
 r.   r
  c                    K   | s t         j                  j                  dd      } t        |       }|j	                          d{    |S 7 w)a  Make a connection to the SSH agent

       This function attempts to connect to an ssh-agent process
       listening on a UNIX domain socket at `agent_path`. If not
       provided, it will attempt to get the path from the `SSH_AUTH_SOCK`
       environment variable.

       If the connection is successful, an :class:`SSHAgentClient` object
       is returned that has methods on it you can use to query the
       ssh-agent. If no path is specified and the environment variable
       is not set or the connection to the agent fails, an error is
       raised.

       :param agent_path: (optional)
           The path to use to contact the ssh-agent process, or the
           :class:`SSHServerConnection` to forward the agent request
           over.
       :type agent_path: `str` or :class:`SSHServerConnection`

       :returns: An :class:`SSHAgentClient`

       :raises: :exc:`OSError` or :exc:`ChannelOpenError` if the
                connection to the agent can't be opened

    SSH_AUTH_SOCKr   N)r   r   r   r`   r   )r>   r_   s     r$   connect_agentr    sB     8 ZZ^^OR8
:&E
--/L s   AAA
A)r   )Jr+   r   rA   r   rk   typesr   typingr   r   r   r   r	   r
   r   typing_extensionsr   r   listenerr   miscr   r   r   r   r   r   r   r   
public_keyr   r   r   r   r   tempfiler   r   r0   rl   agent_win32r=   
agent_unixImportErrorrD   rC   rF   r  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   SSH_AGENT_EXTENSION_FAILUREr   r   r   r   r   r^   r`   r
  r  r"   r.   r$   <module>r$     s  *    	 
  N N N , ( : F F B B <+6( 6
@( 
@
Q
||w+*G8 G 3445
 ,. +- +- +- +-  +- +- +-+- +- +- (+-  ,- +, +- +- +-  ,- +, +.  ,- +, J.j J.Zj  j Z   * !J !8H ! !C  QQS Q+{*+Q QQs    D D$DD$