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