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