Package paramiko :: Module win_pageant
[frames] | no frames]

Source Code for Module paramiko.win_pageant

  1  # Copyright (C) 2005 John Arbash-Meinel <john@arbash-meinel.com> 
  2  # Modified up by: Todd Whiteman <ToddW@ActiveState.com> 
  3  # 
  4  # This file is part of paramiko. 
  5  # 
  6  # Paramiko is free software; you can redistribute it and/or modify it under the 
  7  # terms of the GNU Lesser General Public License as published by the Free 
  8  # Software Foundation; either version 2.1 of the License, or (at your option) 
  9  # any later version. 
 10  # 
 11  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
 12  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 13  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 14  # details. 
 15  # 
 16  # You should have received a copy of the GNU Lesser General Public License 
 17  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 18  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 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  # if you're on windows, you should have one of these, i guess? 
 31  # ctypes is part of standard library since Python 2.5 
 32  _has_win32all = False 
 33  _has_ctypes = False 
 34  try: 
 35      # win32gui is preferred over win32ui to avoid MFC dependencies 
 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  # Note: The WM_COPYDATA value is pulled from win32con, as a workaround 
 49  # so we do not have to import this huge library just for this one variable. 
 50  win32con_WM_COPYDATA = 74 
 51   
 52   
53 -def _get_pageant_window_object():
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 # Return 0 if there is no Pageant window. 62 return ctypes.windll.user32.FindWindowA('Pageant', 'Pageant') 63 return None
64 65
66 -def can_talk_to_agent():
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
78 -def _query_pageant(msg):
79 hwnd = _get_pageant_window_object() 80 if not hwnd: 81 # Raise a failure to connect exception, pageant isn't running anymore! 82 return None 83 84 # Write our pageant request string into the file (pageant will read this to determine what to do) 85 filename = tempfile.mktemp('.pag') 86 map_filename = os.path.basename(filename) 87 88 f = open(filename, 'w+b') 89 f.write(msg ) 90 # Ensure the rest of the file is empty, otherwise pageant will read this 91 f.write('\0' * (_AGENT_MAX_MSGLEN - len(msg))) 92 # Create the shared file map that pageant will use to read from 93 pymap = mmap.mmap(f.fileno(), _AGENT_MAX_MSGLEN, tagname=map_filename, access=mmap.ACCESS_WRITE) 94 try: 95 # Create an array buffer containing the mapped filename 96 char_buffer = array.array("c", map_filename + '\0') 97 char_buffer_address, char_buffer_size = char_buffer.buffer_info() 98 # Create a string to use for the SendMessage function call 99 cds = struct.pack("LLP", _AGENT_COPYDATA_ID, char_buffer_size, char_buffer_address) 100 101 if _has_win32all: 102 # win32gui.SendMessage should also allow the same pattern as 103 # ctypes, but let's keep it like this for now... 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 # Remove the file, it was temporary only 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
138 - def recv(self, n):
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
147 - def close(self):
148 pass
149