1# -*- test-case-name: twisted.conch.test.test_default -*-
2# Copyright (c) Twisted Matrix Laboratories.
3# See LICENSE for details.
4
5"""
6Accesses the key agent for user authentication.
7
8Maintainer: Paul Swartz
9"""
10
11import os
12
13from twisted.conch.ssh import agent, channel, keys
14from twisted.internet import protocol, reactor
15from twisted.python import log
16
17
18
19class SSHAgentClient(agent.SSHAgentClient):
20
21    def __init__(self):
22        agent.SSHAgentClient.__init__(self)
23        self.blobs = []
24
25
26    def getPublicKeys(self):
27        return self.requestIdentities().addCallback(self._cbPublicKeys)
28
29
30    def _cbPublicKeys(self, blobcomm):
31        log.msg('got %i public keys' % len(blobcomm))
32        self.blobs = [x[0] for x in blobcomm]
33
34
35    def getPublicKey(self):
36        """
37        Return a L{Key} from the first blob in C{self.blobs}, if any, or
38        return C{None}.
39        """
40        if self.blobs:
41            return keys.Key.fromString(self.blobs.pop(0))
42        return None
43
44
45
46class SSHAgentForwardingChannel(channel.SSHChannel):
47
48    def channelOpen(self, specificData):
49        cc = protocol.ClientCreator(reactor, SSHAgentForwardingLocal)
50        d = cc.connectUNIX(os.environ['SSH_AUTH_SOCK'])
51        d.addCallback(self._cbGotLocal)
52        d.addErrback(lambda x:self.loseConnection())
53        self.buf = ''
54
55
56    def _cbGotLocal(self, local):
57        self.local = local
58        self.dataReceived = self.local.transport.write
59        self.local.dataReceived = self.write
60
61
62    def dataReceived(self, data):
63        self.buf += data
64
65
66    def closed(self):
67        if self.local:
68            self.local.loseConnection()
69            self.local = None
70
71
72class SSHAgentForwardingLocal(protocol.Protocol):
73    pass
74