paramiko.win_pageant

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 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