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 distributed 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  from __future__ import with_statement 
 25   
 26  import array 
 27  import ctypes.wintypes 
 28  import platform 
 29  import struct 
 30   
 31  try: 
 32      import _thread as thread # Python 3.x 
 33  except ImportError: 
 34      import thread # Python 2.5-2.7 
 35   
 36  from . import _winapi 
 37   
 38   
 39  _AGENT_COPYDATA_ID = 0x804e50ba 
 40  _AGENT_MAX_MSGLEN = 8192 
 41  # Note: The WM_COPYDATA value is pulled from win32con, as a workaround 
 42  # so we do not have to import this huge library just for this one variable. 
 43  win32con_WM_COPYDATA = 74 
 44   
 45   
46 -def _get_pageant_window_object():
47 return ctypes.windll.user32.FindWindowA('Pageant', 'Pageant')
48 49
50 -def can_talk_to_agent():
51 """ 52 Check to see if there is a "Pageant" agent we can talk to. 53 54 This checks both if we have the required libraries (win32all or ctypes) 55 and if there is a Pageant currently running. 56 """ 57 return bool(_get_pageant_window_object())
58 59 60 ULONG_PTR = ctypes.c_uint64 if platform.architecture()[0] == '64bit' else ctypes.c_uint32 61 62
63 -class COPYDATASTRUCT(ctypes.Structure):
64 """ 65 ctypes implementation of 66 http://msdn.microsoft.com/en-us/library/windows/desktop/ms649010%28v=vs.85%29.aspx 67 """ 68 _fields_ = [ 69 ('num_data', ULONG_PTR), 70 ('data_size', ctypes.wintypes.DWORD), 71 ('data_loc', ctypes.c_void_p), 72 ]
73 74
75 -def _query_pageant(msg):
76 """ 77 Communication with the Pageant process is done through a shared 78 memory-mapped file. 79 """ 80 hwnd = _get_pageant_window_object() 81 if not hwnd: 82 # Raise a failure to connect exception, pageant isn't running anymore! 83 return None 84 85 # create a name for the mmap 86 map_name = 'PageantRequest%08x' % thread.get_ident() 87 88 pymap = _winapi.MemoryMap(map_name, _AGENT_MAX_MSGLEN, 89 _winapi.get_security_attributes_for_user(), 90 ) 91 with pymap: 92 pymap.write(msg) 93 # Create an array buffer containing the mapped filename 94 char_buffer = array.array("c", map_name + '\0') 95 char_buffer_address, char_buffer_size = char_buffer.buffer_info() 96 # Create a string to use for the SendMessage function call 97 cds = COPYDATASTRUCT(_AGENT_COPYDATA_ID, char_buffer_size, 98 char_buffer_address) 99 100 response = ctypes.windll.user32.SendMessageA(hwnd, 101 win32con_WM_COPYDATA, ctypes.sizeof(cds), ctypes.byref(cds)) 102 103 if response > 0: 104 pymap.seek(0) 105 datalen = pymap.read(4) 106 retlen = struct.unpack('>I', datalen)[0] 107 return datalen + pymap.read(retlen) 108 return None
109 110
111 -class PageantConnection(object):
112 """ 113 Mock "connection" to an agent which roughly approximates the behavior of 114 a unix local-domain socket (as used by Agent). Requests are sent to the 115 pageant daemon via special Windows magick, and responses are buffered back 116 for subsequent reads. 117 """ 118
119 - def __init__(self):
120 self._response = None
121
122 - def send(self, data):
123 self._response = _query_pageant(data)
124
125 - def recv(self, n):
126 if self._response is None: 127 return '' 128 ret = self._response[:n] 129 self._response = self._response[n:] 130 if self._response == '': 131 self._response = None 132 return ret
133
134 - def close(self):
135 pass
136