U
    ˆj,%  ã                   @   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r¶e"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   ú;/tmp/pip-unpacked-wheel-j5h_c8_q/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   Ú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   r5   r6   Ú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   r5   r   r8   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   r5   r8   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*   r.   r-   r9   r=   r<   rA   rC   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   rK   ž   s    zSSHAgentServer.sendResponsec                 C   sz   |dkst ‚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)ÚAssertionErrorr   rM   r   r)   r   r&   Úvaluesr   r5   rK   r0   Újoin)r   r   r2   ÚrespÚkeyr6   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   rM   r   rK   r   rO   r>   r   Úsign)r   r   r5   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-dssr/   zunknown blob type: %séÿÿÿÿZprivate_blob©Útyper   N)
r   r   ZBadKeyErrorr   ÚKeyÚ
fromStringrM   r5   rK   r   )r   r   ZkeyTypeÚrestZnmpr6   Ú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.
        r5   rY   r   N)r   r   r[   r\   rM   r5   rK   r   )r   r   r5   Ú_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)rO   rM   r   rK   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)rK   ÚAGENT_RSA_IDENTITIES_ANSWERr   r&   rb   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©rK   r   rb   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   Nrf   rb   r   r   r   Ú agentc_REMOVE_ALL_RSA_IDENTITIESû   s    z/SSHAgentServer.agentc_REMOVE_ALL_RSA_IDENTITIESN)rD   rE   rF   rG   r   r$   rK   rT   rV   r_   ra   rc   re   rg   rh   r   r   r   r   rH   €   s   	rH   r   é   r/   rW   é   é	   é   é   é   é   é   é   é   é   ZAGENTC_)$rG   r   Ztwisted.conch.errorr   r   Ztwisted.conch.sshr   Ztwisted.conch.ssh.commonr   r   r   Ztwisted.internetr   r	   ÚProtocolr
   rH   ZAGENTC_REQUEST_RSA_IDENTITIESrd   r   r   ZAGENTC_REMOVE_RSA_IDENTITYZ AGENTC_REMOVE_ALL_RSA_IDENTITIESr+   r0   r;   r>   r7   r@   rB   rI   ÚlocalsÚcopyÚitemsÚnameÚvaluer   r   r   r   Ú<module>   s2   	k 