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      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  # Note: The WM_COPYDATA value is pulled from win32con, as a workaround 
 48  # so we do not have to import this huge library just for this one variable. 
 49  win32con_WM_COPYDATA = 74 
 50   
 51   
52 -def _get_pageant_window_object():
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 # Return 0 if there is no Pageant window. 61 return ctypes.windll.user32.FindWindowA('Pageant', 'Pageant') 62 return None
63 64
65 -def can_talk_to_agent():
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
77 -def _query_pageant(msg):
78 hwnd = _get_pageant_window_object() 79 if not hwnd: 80 # Raise a failure to connect exception, pageant isn't running anymore! 81 return None 82 83 # Write our pageant request string into the file (pageant will read this to determine what to do) 84 filename = tempfile.mktemp('.pag') 85 map_filename = os.path.basename(filename) 86 87 f = open(filename, 'w+b') 88 f.write(msg ) 89 # Ensure the rest of the file is empty, otherwise pageant will read this 90 f.write('\0' * (_AGENT_MAX_MSGLEN - len(msg))) 91 # Create the shared file map that pageant will use to read from 92 pymap = mmap.mmap(f.fileno(), _AGENT_MAX_MSGLEN, tagname=map_filename, access=mmap.ACCESS_WRITE) 93 try: 94 # Create an array buffer containing the mapped filename 95 char_buffer = array.array("c", map_filename + '\0') 96 char_buffer_address, char_buffer_size = char_buffer.buffer_info() 97 # Create a string to use for the SendMessage function call 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 # Remove the file, it was temporary only 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
135 - def recv(self, n):
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
144 - def close(self):
145 pass
146