changes to win_pageant from todd whiteman which avoid using ctypes and apparently makes the pageant agent work
This commit is contained in:
parent
8087fa5a29
commit
017d315bce
|
@ -64,6 +64,8 @@ class Agent:
|
||||||
import win_pageant
|
import win_pageant
|
||||||
if win_pageant.can_talk_to_agent():
|
if win_pageant.can_talk_to_agent():
|
||||||
self.conn = win_pageant.PageantConnection()
|
self.conn = win_pageant.PageantConnection()
|
||||||
|
else:
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
# no agent support
|
# no agent support
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Copyright (C) 2005 John Arbash-Meinel <john@arbash-meinel.com>
|
# Copyright (C) 2005 John Arbash-Meinel <john@arbash-meinel.com>
|
||||||
|
# Modified up by: Todd Whiteman <ToddW@ActiveState.com>
|
||||||
#
|
#
|
||||||
# This file is part of paramiko.
|
# This file is part of paramiko.
|
||||||
#
|
#
|
||||||
|
@ -22,41 +23,31 @@ Functions for communicating with Pageant, the basic windows ssh agent program.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
|
import tempfile
|
||||||
|
import mmap
|
||||||
|
import array
|
||||||
|
|
||||||
# if you're on windows, you should have these, i guess?
|
# if you're on windows, you should have these, i guess?
|
||||||
try:
|
try:
|
||||||
import win32ui
|
import win32ui
|
||||||
import win32api
|
|
||||||
import win32con
|
|
||||||
import mmapfile
|
|
||||||
_has_win32all = True
|
_has_win32all = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_has_win32all = False
|
_has_win32all = False
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
import ctypes
|
|
||||||
_has_ctypes = True
|
|
||||||
except ImportError:
|
|
||||||
_has_ctypes = False
|
|
||||||
else:
|
|
||||||
class _COPYDATASTRUCT(ctypes.Structure):
|
|
||||||
"""This is a mapping to the Win32 COPYDATASTRUCT.
|
|
||||||
|
|
||||||
typedef struct tagCOPYDATASTRUCT {
|
|
||||||
ULONG_PTR dwData;
|
|
||||||
DWORD cbData;
|
|
||||||
PVOID lpData;
|
|
||||||
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
|
|
||||||
"""
|
|
||||||
_fields_ = [ ('dwData', ctypes.c_ulong) #I think this is right
|
|
||||||
, ('cbData', ctypes.c_ulong)
|
|
||||||
, ('lpData', ctypes.c_void_p)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
_AGENT_COPYDATA_ID = 0x804e50ba
|
_AGENT_COPYDATA_ID = 0x804e50ba
|
||||||
_AGENT_MAX_MSGLEN = 8192
|
_AGENT_MAX_MSGLEN = 8192
|
||||||
|
# Note: The WM_COPYDATA value is pulled from win32con, as a workaround
|
||||||
|
# so we do not have to import this huge library just for this one variable.
|
||||||
|
win32con_WM_COPYDATA = 74
|
||||||
|
|
||||||
|
|
||||||
|
def _get_pageant_window_object():
|
||||||
|
try:
|
||||||
|
hwnd = win32ui.FindWindow('Pageant', 'Pageant')
|
||||||
|
return hwnd
|
||||||
|
except win32ui.error:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def can_talk_to_agent():
|
def can_talk_to_agent():
|
||||||
|
@ -66,39 +57,45 @@ def can_talk_to_agent():
|
||||||
This checks both if we have the required libraries (win32all)
|
This checks both if we have the required libraries (win32all)
|
||||||
and if there is a Pageant currently running.
|
and if there is a Pageant currently running.
|
||||||
"""
|
"""
|
||||||
if not _has_win32all or not _has_ctypes:
|
if not _has_win32all or not _get_pageant_window_object():
|
||||||
return False
|
|
||||||
hwnd = win32ui.FindWindow('Pageant', 'Pageant')
|
|
||||||
if not hwnd:
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _query_pageant(msg):
|
def _query_pageant(msg):
|
||||||
hwnd = win32ui.FindWindow('Pageant', 'Pageant')
|
hwnd = _get_pageant_window_object()
|
||||||
if not hwnd:
|
if not hwnd:
|
||||||
# Raise a failure to connect exception
|
# Raise a failure to connect exception, pageant isn't running anymore!
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# I have a feeling that GetCurrentThreadId is just a
|
# Write our pageant request string into the file (pageant will read this to determine what to do)
|
||||||
# way to ensure that we have a unique map name
|
filename = tempfile.mktemp('.pag')
|
||||||
mapname = 'PageantRequest%08x' % (win32api.GetCurrentThreadId())
|
map_filename = os.path.basename(filename)
|
||||||
# Created a named memory map
|
|
||||||
map = mmapfile.mmapfile('', mapname, _AGENT_MAX_MSGLEN)
|
f = open(filename, 'w+b')
|
||||||
|
f.write(msg )
|
||||||
|
# Ensure the rest of the file is empty, otherwise pageant will read this
|
||||||
|
f.write('\0' * (_AGENT_MAX_MSGLEN - len(msg)))
|
||||||
|
# Create the shared file map that pageant will use to read from
|
||||||
|
pymap = mmap.mmap(f.fileno(), _AGENT_MAX_MSGLEN, tagname=map_filename, access=mmap.ACCESS_WRITE)
|
||||||
try:
|
try:
|
||||||
map.write(msg)
|
# Create an array buffer containing the mapped filename
|
||||||
|
char_buffer = array.array("c", map_filename + '\0')
|
||||||
|
char_buffer_address, char_buffer_size = char_buffer.buffer_info()
|
||||||
|
# Create a string to use for the SendMessage function call
|
||||||
|
cds = struct.pack("LLP", _AGENT_COPYDATA_ID, char_buffer_size, char_buffer_address)
|
||||||
|
|
||||||
cds = _COPYDATASTRUCT(_AGENT_COPYDATA_ID, 1 + len(mapname), ctypes.c_char_p(mapname))
|
response = hwnd.SendMessage(win32con_WM_COPYDATA, cds)
|
||||||
|
|
||||||
response = hwnd.SendMessage(win32con.WM_COPYDATA, None, ctypes.byref(cds))
|
|
||||||
if response > 0:
|
if response > 0:
|
||||||
retlen = 4 + struct.unpack('i', map.read(4))
|
datalen = pymap.read(4)
|
||||||
return map.read(retlen)
|
retlen = struct.unpack('>I', datalen)[0]
|
||||||
|
return datalen + pymap.read(retlen)
|
||||||
return None
|
return None
|
||||||
finally:
|
finally:
|
||||||
# This may be done automatically.
|
pymap.close()
|
||||||
map.close()
|
f.close()
|
||||||
|
# Remove the file, it was temporary only
|
||||||
|
os.unlink(filename)
|
||||||
|
|
||||||
|
|
||||||
class PageantConnection (object):
|
class PageantConnection (object):
|
||||||
|
|
Loading…
Reference in New Issue