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.keys = ()
59 if ('SSH_AUTH_SOCK' in os.environ) and (sys.platform != 'win32'):
60 conn = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
61 try:
62 conn.connect(os.environ['SSH_AUTH_SOCK'])
63 except:
64
65 return
66 self.conn = conn
67 elif sys.platform == 'win32':
68 import win_pageant
69 if win_pageant.can_talk_to_agent():
70 self.conn = win_pageant.PageantConnection()
71 else:
72 return
73 else:
74
75 return
76
77 ptype, result = self._send_message(chr(SSH2_AGENTC_REQUEST_IDENTITIES))
78 if ptype != SSH2_AGENT_IDENTITIES_ANSWER:
79 raise SSHException('could not get keys from ssh-agent')
80 keys = []
81 for i in range(result.get_int()):
82 keys.append(AgentKey(self, result.get_string()))
83 result.get_string()
84 self.keys = tuple(keys)
85
87 """
88 Close the SSH agent connection.
89 """
90 self.conn.close()
91 self.conn = None
92 self.keys = ()
93
95 """
96 Return the list of keys available through the SSH agent, if any. If
97 no SSH agent was running (or it couldn't be contacted), an empty list
98 will be returned.
99
100 @return: a list of keys available on the SSH agent
101 @rtype: tuple of L{AgentKey}
102 """
103 return self.keys
104
106 msg = str(msg)
107 self.conn.send(struct.pack('>I', len(msg)) + msg)
108 l = self._read_all(4)
109 msg = Message(self._read_all(struct.unpack('>I', l)[0]))
110 return ord(msg.get_byte()), msg
111
113 result = self.conn.recv(wanted)
114 while len(result) < wanted:
115 if len(result) == 0:
116 raise SSHException('lost ssh-agent')
117 extra = self.conn.recv(wanted - len(result))
118 if len(extra) == 0:
119 raise SSHException('lost ssh-agent')
120 result += extra
121 return result
122
123
125 """
126 Private key held in a local SSH agent. This type of key can be used for
127 authenticating to a remote server (signing). Most other key operations
128 work as expected.
129 """
130
135
138
141
152