U
    
W[%                     @   s   d Z ddlmZmZ ddlZddl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 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re'dd e#e(< qd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
    )absolute_importdivisionN)NSgetNSgetMP)
ConchErrorMissingKeyStoreError)keys)deferprotocol)
itervaluesc                   @   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 rPd S | j dd|  | j d| d   }| _ t|dd }| jd}|tkr|t	d q|t
kr|d q|| qd S )N   !Lr      zagent failurer   )r   lenstructunpackordr   popAGENT_FAILUREZ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
   ZDeferredr   append)r   r%   r"   r)   r&   r   r   r   sendRequest7   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   requestIdentities?   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   r0   J   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   r8   r9   reqr   r   r   addIdentity[   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   r8   r"   r;   r   r   r   signDatad   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"   Z	signaturer   r   r   r?   u   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   r8   r;   r   r   r   removeIdentity|   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   removeAllIdentities   s    z"SSHAgentClient.removeAllIdentitiesN)r   )__name__
__module____qualname____doc__r   r'   r-   r1   r0   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 rPd S | j dd|  | j d| d   }| _ t|dd }t|d }|s| td qt	| d| }t	| j
dd d kr| td t ||dd   qd S )Nr   r   r   r   r   z	agentc_%sr	   )r   r   r   r   r   messagesgetsendResponser   getattrfactoryr   )r   r"   r#   r$   r%   Z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t t| jj}g }|td| t| 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)AssertionErrorr   rO   r	   r,   r   r)   r   r   r8   rM   r3   join)r   r"   r5   Zrespkeyr9   r   r   r   agentc_REQUEST_IDENTITIES   s    z(SSHAgentServer.agentc_REQUEST_IDENTITIESc                 C   sb   t |\}}|| jjkr$| tdS t |\}}|dks<t| 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   rQ   rA   r   Zsign)r   r"   r8   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-dssr2   zunknown blob type: %sZprivate_blobtyper   N)
r   r	   ZBadKeyErrorr   Key
fromStringrO   r8   rM   r    )r   r"   ZkeyTyperestZnmpr9   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.
        r8   rX   r   N)r   r	   rZ   r[   rO   r8   rM   r    )r   r"   r8   _r]   r   r   r   agentc_REMOVE_IDENTITY   s    z%SSHAgentServer.agentc_REMOVE_IDENTITYc                 C   s$   |dkst i | j_| td dS )zL
        Remove all keys from the agent's collection of identities.
        r   N)rQ   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)   ra   r   r   r   agentc_REQUEST_RSA_IDENTITIES   s    z,SSHAgentServer.agentc_REQUEST_RSA_IDENTITIESc                 C   s   |  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    ra   r   r   r   agentc_REMOVE_RSA_IDENTITY  s    z)SSHAgentServer.agentc_REMOVE_RSA_IDENTITYc                 C   s   |  td dS )z
        v1 message for removing all RSA1 keys; superseded by
        agentc_REMOVE_ALL_IDENTITIES, which handles different key types.
        r   Nre   ra   r   r   r    agentc_REMOVE_ALL_RSA_IDENTITIES  s    z/SSHAgentServer.agentc_REMOVE_ALL_RSA_IDENTITIESN)rF   rG   rH   rI   r   r'   rM   rT   rU   r^   r`   rb   rd   rf   rg   r   r   r   r   rJ      s   
rJ   r      r2   rV      	                           ZAGENTC_))rI   Z
__future__r   r   r   Ztwisted.conch.ssh.commonr   r   r   Ztwisted.conch.errorr   r   Ztwisted.conch.sshr	   Ztwisted.internetr
   r   Ztwisted.python.compatr   ZProtocolr   rJ   ZAGENTC_REQUEST_RSA_IDENTITIESrc   r   r    ZAGENTC_REMOVE_RSA_IDENTITYZ AGENTC_REMOVE_ALL_RSA_IDENTITIESr.   r3   r>   rA   r:   rB   rD   rK   localscopyitemsnamevaluer   r   r   r   <module>   s6   u 	