1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 SSH Agent interface for Unix clients.
21 """
22
23 import os
24 import socket
25 import struct
26 import sys
27
28 from paramiko.ssh_exception import SSHException
29 from paramiko.message import Message
30 from paramiko.pkey import PKey
31
32
33 SSH2_AGENTC_REQUEST_IDENTITIES, SSH2_AGENT_IDENTITIES_ANSWER, \
34 SSH2_AGENTC_SIGN_REQUEST, SSH2_AGENT_SIGN_RESPONSE = range(11, 15)
35
36
38 """
39 Client interface for using private keys from an SSH agent running on the
40 local machine. If an SSH agent is running, this class can be used to
41 connect to it and retreive L{PKey} objects which can be used when
42 attempting to authenticate to remote SSH servers.
43
44 Because the SSH agent protocol uses environment variables and unix-domain
45 sockets, this probably doesn't work on Windows. It does work on most
46 posix platforms though (Linux and MacOS X, for example).
47 """
48
50 """
51 Open a session with the local machine's SSH agent, if one is running.
52 If no agent is running, initialization will succeed, but L{get_keys}
53 will return an empty tuple.
54
55 @raise SSHException: if an SSH agent is found, but speaks an
56 incompatible protocol
57 """
58 self.conn = None
59 self.keys = ()
60 if ('SSH_AUTH_SOCK' in os.environ) and (sys.platform != 'win32'):
61 conn = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
62 try:
63 conn.connect(os.environ['SSH_AUTH_SOCK'])
64 except:
65
66 return
67 self.conn = conn
68 elif sys.platform == 'win32':
69 import win_pageant
70 if win_pageant.can_talk_to_agent():
71 self.conn = win_pageant.PageantConnection()
72 else:
73 return
74 else:
75
76 return
77
78 ptype, result = self._send_message(chr(SSH2_AGENTC_REQUEST_IDENTITIES))
79 if ptype != SSH2_AGENT_IDENTITIES_ANSWER:
80 raise SSHException('could not get keys from ssh-agent')
81 keys = []
82 for i in range(result.get_int()):
83 keys.append(AgentKey(self, result.get_string()))
84 result.get_string()
85 self.keys = tuple(keys)
86
88 """
89 Close the SSH agent connection.
90 """
91 if self.conn is not None:
92 self.conn.close()
93 self.conn = None
94 self.keys = ()
95
97 """
98 Return the list of keys available through the SSH agent, if any. If
99 no SSH agent was running (or it couldn't be contacted), an empty list
100 will be returned.
101
102 @return: a list of keys available on the SSH agent
103 @rtype: tuple of L{AgentKey}
104 """
105 return self.keys
106
108 msg = str(msg)
109 self.conn.send(struct.pack('>I', len(msg)) + msg)
110 l = self._read_all(4)
111 msg = Message(self._read_all(struct.unpack('>I', l)[0]))
112 return ord(msg.get_byte()), msg
113
115 result = self.conn.recv(wanted)
116 while len(result) < wanted:
117 if len(result) == 0:
118 raise SSHException('lost ssh-agent')
119 extra = self.conn.recv(wanted - len(result))
120 if len(extra) == 0:
121 raise SSHException('lost ssh-agent')
122 result += extra
123 return result
124
125
127 """
128 Private key held in a local SSH agent. This type of key can be used for
129 authenticating to a remote server (signing). Most other key operations
130 work as expected.
131 """
132
137
140
143
154