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