1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """
21 Functions for communicating with Pageant, the basic windows ssh agent program.
22 """
23
24 import os
25 import struct
26 import tempfile
27 import mmap
28 import array
29
30
31
32 _has_win32all = False
33 _has_ctypes = False
34 try:
35
36 import win32gui
37 _has_win32all = True
38 except ImportError:
39 try:
40 import ctypes
41 _has_ctypes = True
42 except ImportError:
43 pass
44
45
46 _AGENT_COPYDATA_ID = 0x804e50ba
47 _AGENT_MAX_MSGLEN = 8192
48
49
50 win32con_WM_COPYDATA = 74
51
52
54 if _has_win32all:
55 try:
56 hwnd = win32gui.FindWindow('Pageant', 'Pageant')
57 return hwnd
58 except win32gui.error:
59 pass
60 elif _has_ctypes:
61
62 return ctypes.windll.user32.FindWindowA('Pageant', 'Pageant')
63 return None
64
65
67 """
68 Check to see if there is a "Pageant" agent we can talk to.
69
70 This checks both if we have the required libraries (win32all or ctypes)
71 and if there is a Pageant currently running.
72 """
73 if (_has_win32all or _has_ctypes) and _get_pageant_window_object():
74 return True
75 return False
76
77
79 hwnd = _get_pageant_window_object()
80 if not hwnd:
81
82 return None
83
84
85 filename = tempfile.mktemp('.pag')
86 map_filename = os.path.basename(filename)
87
88 f = open(filename, 'w+b')
89 f.write(msg )
90
91 f.write('\0' * (_AGENT_MAX_MSGLEN - len(msg)))
92
93 pymap = mmap.mmap(f.fileno(), _AGENT_MAX_MSGLEN, tagname=map_filename, access=mmap.ACCESS_WRITE)
94 try:
95
96 char_buffer = array.array("c", map_filename + '\0')
97 char_buffer_address, char_buffer_size = char_buffer.buffer_info()
98
99 cds = struct.pack("LLP", _AGENT_COPYDATA_ID, char_buffer_size, char_buffer_address)
100
101 if _has_win32all:
102
103
104 response = win32gui.SendMessage(hwnd, win32con_WM_COPYDATA, len(cds), cds)
105 elif _has_ctypes:
106 _buf = array.array('B', cds)
107 _addr, _size = _buf.buffer_info()
108 response = ctypes.windll.user32.SendMessageA(hwnd, win32con_WM_COPYDATA, _size, _addr)
109 else:
110 response = 0
111
112 if response > 0:
113 datalen = pymap.read(4)
114 retlen = struct.unpack('>I', datalen)[0]
115 return datalen + pymap.read(retlen)
116 return None
117 finally:
118 pymap.close()
119 f.close()
120
121 os.unlink(filename)
122
123
124 -class PageantConnection (object):
125 """
126 Mock "connection" to an agent which roughly approximates the behavior of
127 a unix local-domain socket (as used by Agent). Requests are sent to the
128 pageant daemon via special Windows magick, and responses are buffered back
129 for subsequent reads.
130 """
131
132 - def __init__(self):
133 self._response = None
134
135 - def send(self, data):
136 self._response = _query_pageant(data)
137
139 if self._response is None:
140 return ''
141 ret = self._response[:n]
142 self._response = self._response[n:]
143 if self._response == '':
144 self._response = None
145 return ret
146
149