o
    ¯b,%  ã                   @   sä   d Z ddlZddl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 G dd„ dejƒZG d	d
„ d
ejƒZdZdZdZdZdZdZdZdZdZdZdZdZdZi Zeƒ   ¡  !¡ D ]\Z"Z#e"dd… dkroe"dd… ee#< q[dS )zÞ
Implements the SSH v2 key agent protocol.  This protocol is documented in the
SSH source code, in the file
U{PROTOCOL.agent<http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent>}.

Maintainer: Paul Swartz
é    N)Ú
ConchErrorÚMissingKeyStoreError)Úkeys)ÚNSÚgetMPÚgetNS)ÚdeferÚprotocolc                   @   sb   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zddd„Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚSSHAgentClientz½
    The client side of the SSH agent protocol.  This is equivalent to
    ssh-add(1) and can be used with either ssh-agent(1) or the SSHAgentServer
    protocol, also in this package.
    c                 C   s   d| _ g | _d S ©Nó    )ÚbufÚ	deferreds©Úself© r   ú9/usr/lib/python3/dist-packages/twisted/conch/ssh/agent.pyÚ__init__   s   
zSSHAgentClient.__init__c                 C   sÎ   |  j |7  _ 	 t| j ƒdkrd S t d| j d d… ¡d }t| j ƒd| k r)d S | j dd| … | j d| d … }| _ t|dd… ƒ}| j d¡}|tkrW| t	dƒ¡ n|t
kra| d¡ n| |¡ q)Né   é   ú!Lr   zagent failurer   )r   ÚlenÚstructÚunpackÚordr   ÚpopÚAGENT_FAILUREÚerrbackr   ÚAGENT_SUCCESSÚcallback)r   ÚdataÚpackLenÚpacketÚreqTypeÚdr   r   r   ÚdataReceived    s    (
òzSSHAgentClient.dataReceivedc                 C   s>   t  dt|ƒd |¡| }| j |¡ t ¡ }| j |¡ |S ©Nz!LBr   )	r   Úpackr   Ú	transportÚwriter   ÚDeferredr   Úappend)r   r#   r    r'   r$   r   r   r   ÚsendRequest2   s
   zSSHAgentClient.sendRequestc                 C   s   |   td¡}| | j¡ |S )zÄ
        @return: A L{Deferred} which will fire with a list of all keys found in
            the SSH agent. The list of keys is comprised of (public key blob,
            comment) tuples.
        r   )r,   ÚAGENTC_REQUEST_IDENTITIESÚaddCallbackÚ_cbRequestIdentities)r   r$   r   r   r   ÚrequestIdentities9   s   z SSHAgentClient.requestIdentitiesc                 C   sŒ   t |dd… ƒtkrtdt |dd… ƒ ƒ‚t d|dd… ¡d }g }|dd… }t|ƒD ]}t|ƒ\}}t|ƒ\}}| ||f¡ q.|S )z}
        Unpack a collection of identities into a list of tuples comprised of
        public key blobs and comments.
        r   r   zunexpected response: %ir   é   N)r   ÚAGENT_IDENTITIES_ANSWERr   r   r   Úranger   r+   )r   r    ÚnumKeysÚresultÚiÚblobÚcommentr   r   r   r/   C   s   z#SSHAgentClient._cbRequestIdentitiesr   c                 C   s   |}|t |ƒ7 }|  t|¡S )zK
        Add a private key blob to the agent's collection of keys.
        )r   r,   ÚAGENTC_ADD_IDENTITY)r   r7   r8   Úreqr   r   r   ÚaddIdentityS   s   zSSHAgentClient.addIdentityc                 C   s0   t |ƒ}|t |ƒ7 }|d7 }|  t|¡ | j¡S )a†  
        Request that the agent sign the given C{data} with the private key
        which corresponds to the public key given by C{blob}.  The private
        key should have been added to the agent already.

        @type blob: L{bytes}
        @type data: L{bytes}
        @return: A L{Deferred} which fires with a signature for given data
            created with the given key.
        ó       )r   r,   ÚAGENTC_SIGN_REQUESTr.   Ú_cbSignData)r   r7   r    r:   r   r   r   ÚsignData[   s   zSSHAgentClient.signDatac                 C   sD   t |dd… ƒtkrtdt |dd… ƒ ƒ‚t|dd … ƒd }|S )Nr   r   zunexpected data: %i)r   ÚAGENT_SIGN_RESPONSEr   r   )r   r    Ú	signaturer   r   r   r>   k   s   zSSHAgentClient._cbSignDatac                 C   s   t |ƒ}|  t|¡S )zp
        Remove the private key corresponding to the public key in blob from the
        running agent.
        )r   r,   ÚAGENTC_REMOVE_IDENTITY)r   r7   r:   r   r   r   ÚremoveIdentityq   s   zSSHAgentClient.removeIdentityc                 C   s   |   td¡S )z9
        Remove all keys from the running agent.
        r   )r,   ÚAGENTC_REMOVE_ALL_IDENTITIESr   r   r   r   ÚremoveAllIdentitiesy   s   z"SSHAgentClient.removeAllIdentitiesN)r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r%   r,   r0   r/   r;   r?   r>   rC   rE   r   r   r   r   r
      s    

r
   c                   @   sh   e Zd 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S )ÚSSHAgentServerz½
    The server side of the SSH agent protocol.  This is equivalent to
    ssh-agent(1) and can be used with either ssh-add(1) or the SSHAgentClient
    protocol, also in this package.
    c                 C   s
   d| _ d S r   )r   r   r   r   r   r   ‡   s   
zSSHAgentServer.__init__c                 C   sì   |  j |7  _ 	 t| j ƒdkrd S t d| j d d… ¡d }t| j ƒd| k r)d S | j dd| … | j d| d … }| _ t|dd… ƒ}t |d ¡}|sT|  td¡ n!t	| d| ƒ}t	| j
dd ƒd u rm|  td¡ tƒ ‚||dd … ƒ q)Nr   r   r   r   r   z	agentc_%sr   )r   r   r   r   r   ÚmessagesÚgetÚsendResponser   ÚgetattrÚfactoryr   )r   r    r!   r"   r#   ÚreqNameÚfr   r   r   r%   Š   s$   (ðzSSHAgentServer.dataReceivedc                 C   s*   t  dt|ƒd |¡| }| j |¡ d S r&   )r   r'   r   r(   r)   )r   r#   r    r'   r   r   r   rM   ž   s   zSSHAgentServer.sendResponsec                 C   sz   |dksJ ‚t | jjƒ}g }| t d|¡¡ | jj ¡ D ]\}}| t| ¡ ƒ¡ | t|ƒ¡ q|  	t
d |¡¡ dS )zQ
        Return all of the identities that have been added to the server
        r   r   N)r   rO   r   r+   r   r'   Úvaluesr   r7   rM   r2   Újoin)r   r    r4   ÚrespÚkeyr8   r   r   r   Úagentc_REQUEST_IDENTITIES¢   s   z(SSHAgentServer.agentc_REQUEST_IDENTITIESc                 C   sb   t |ƒ\}}|| jjvr|  td¡S t |ƒ\}}|dksJ ‚|  tt| jj| d  |¡ƒ¡ dS )zó
        Data is a structure with a reference to an already added key object and
        some data that the clients wants signed with that key.  If the key
        object wasn't loaded, return AGENT_FAILURE, else return the signature.
        r   r<   r   N)r   rO   r   rM   r   r@   r   Úsign)r   r    r7   r?   r   r   r   Úagentc_SIGN_REQUEST°   s   ÿz"SSHAgentServer.agentc_SIGN_REQUESTc                 C   s„   t |ƒ\}}|dkrd}n|dkrd}nt d| ¡‚t||ƒd }t |ƒ\}}tjj|dd}||f| jj| ¡ < |  t	d	¡ d
S )zÃ
        Adds a private key to the agent's collection of identities.  On
        subsequent interactions, the private key can be accessed using only the
        corresponding public key.
        s   ssh-rsaé   s   ssh-dssr1   zunknown blob type: %séÿÿÿÿÚprivate_blob©Útyper   N)
r   r   ÚBadKeyErrorr   ÚKeyÚ
fromStringrO   r7   rM   r   )r   r    ÚkeyTypeÚrestÚnmpr8   Úkr   r   r   Úagentc_ADD_IDENTITY¿   s   ÿz"SSHAgentServer.agentc_ADD_IDENTITYc                 C   s:   t |ƒ\}}tjj|dd}| jj| ¡ = |  td¡ dS )zR
        Remove a specific key from the agent's collection of identities.
        r7   r\   r   N)r   r   r_   r`   rO   r7   rM   r   )r   r    r7   Ú_rd   r   r   r   Úagentc_REMOVE_IDENTITYØ   s   z%SSHAgentServer.agentc_REMOVE_IDENTITYc                 C   s$   |dksJ ‚i | j _|  td¡ dS )zL
        Remove all keys from the agent's collection of identities.
        r   N)rO   r   rM   r   ©r   r    r   r   r   Úagentc_REMOVE_ALL_IDENTITIESá   s   z+SSHAgentServer.agentc_REMOVE_ALL_IDENTITIESc                 C   s   |   tt dd¡¡ dS )z‡
        v1 message for listing RSA1 keys; superseded by
        agentc_REQUEST_IDENTITIES, which handles different key types.
        r   r   N)rM   ÚAGENT_RSA_IDENTITIES_ANSWERr   r'   rh   r   r   r   Úagentc_REQUEST_RSA_IDENTITIESí   s   z,SSHAgentServer.agentc_REQUEST_RSA_IDENTITIESc                 C   ó   |   td¡ dS )z…
        v1 message for removing RSA1 keys; superseded by
        agentc_REMOVE_IDENTITY, which handles different key types.
        r   N©rM   r   rh   r   r   r   Úagentc_REMOVE_RSA_IDENTITYô   ó   z)SSHAgentServer.agentc_REMOVE_RSA_IDENTITYc                 C   rl   )z
        v1 message for removing all RSA1 keys; superseded by
        agentc_REMOVE_ALL_IDENTITIES, which handles different key types.
        r   Nrm   rh   r   r   r   Ú agentc_REMOVE_ALL_RSA_IDENTITIESû   ro   z/SSHAgentServer.agentc_REMOVE_ALL_RSA_IDENTITIESN)rF   rG   rH   rI   r   r%   rM   rV   rX   re   rg   ri   rk   rn   rp   r   r   r   r   rJ   €   s    	rJ   r   é   r1   rY   é   é	   é   é   é   é   é   é   é   é   ÚAGENTC_)$rI   r   Útwisted.conch.errorr   r   Útwisted.conch.sshr   Útwisted.conch.ssh.commonr   r   r   Útwisted.internetr   r	   ÚProtocolr
   rJ   ÚAGENTC_REQUEST_RSA_IDENTITIESrj   r   r   ÚAGENTC_REMOVE_RSA_IDENTITYÚ AGENTC_REMOVE_ALL_RSA_IDENTITIESr-   r2   r=   r@   r9   rB   rD   rK   ÚlocalsÚcopyÚitemsÚnameÚvaluer   r   r   r   Ú<module>   s8   	k €þ