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