Merge branch '1.10' into 1.11

Conflicts:
	NEWS
This commit is contained in:
Jeff Forcier 2014-01-21 13:58:44 -08:00
commit 2cf23bf784
3 changed files with 42 additions and 13 deletions

14
NEWS
View File

@ -12,6 +12,20 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/.
Releases Releases
======== ========
v1.11.4 (21st Jan 2014)
-----------------------
* #193 (and its attentant PRs #230 & #253): Fix SSH agent problems present on
Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle
Lundberg for the patches.
v1.10.6 (21st Jan 2014)
-----------------------
* #193 (and its attentant PRs #230 & #253): Fix SSH agent problems present on
Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle
Lundberg for the patches.
v1.11.3 (8th Jan 2014) v1.11.3 (8th Jan 2014)
---------------------- ----------------------

View File

@ -10,6 +10,11 @@ import ctypes
import ctypes.wintypes import ctypes.wintypes
import __builtin__ import __builtin__
try:
USHORT = ctypes.wintypes.USHORT
except AttributeError:
USHORT = ctypes.c_ushort
###################### ######################
# jaraco.windows.error # jaraco.windows.error
@ -81,9 +86,6 @@ def handle_nonzero_success(result):
raise WindowsError() raise WindowsError()
#####################
# jaraco.windows.mmap
CreateFileMapping = ctypes.windll.kernel32.CreateFileMappingW CreateFileMapping = ctypes.windll.kernel32.CreateFileMappingW
CreateFileMapping.argtypes = [ CreateFileMapping.argtypes = [
ctypes.wintypes.HANDLE, ctypes.wintypes.HANDLE,
@ -130,15 +132,18 @@ class MemoryMap(object):
self.pos = pos self.pos = pos
def write(self, msg): def write(self, msg):
ctypes.windll.msvcrt.memcpy(self.view + self.pos, msg, len(msg)) n = len(msg)
self.pos += len(msg) if self.pos + n >= self.length: # A little safety.
raise ValueError("Refusing to write %d bytes" % n)
ctypes.windll.kernel32.RtlMoveMemory(self.view + self.pos, msg, n)
self.pos += n
def read(self, n): def read(self, n):
""" """
Read n bytes from mapped view. Read n bytes from mapped view.
""" """
out = ctypes.create_string_buffer(n) out = ctypes.create_string_buffer(n)
ctypes.windll.msvcrt.memcpy(out, self.view + self.pos, n) ctypes.windll.kernel32.RtlMoveMemory(out, self.view + self.pos, n)
self.pos += n self.pos += n
return out.raw return out.raw
@ -173,7 +178,7 @@ class SECURITY_DESCRIPTOR(ctypes.Structure):
PACL Dacl; PACL Dacl;
} SECURITY_DESCRIPTOR; } SECURITY_DESCRIPTOR;
""" """
SECURITY_DESCRIPTOR_CONTROL = ctypes.wintypes.USHORT SECURITY_DESCRIPTOR_CONTROL = USHORT
REVISION = 1 REVISION = 1
_fields_ = [ _fields_ = [

View File

@ -23,14 +23,19 @@ Functions for communicating with Pageant, the basic windows ssh agent program.
from __future__ import with_statement from __future__ import with_statement
import struct
import threading
import array import array
import platform
import ctypes.wintypes import ctypes.wintypes
import platform
import struct
try:
import _thread as thread # Python 3.x
except ImportError:
import thread # Python 2.5-2.7
from . import _winapi from . import _winapi
_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 # Note: The WM_COPYDATA value is pulled from win32con, as a workaround
@ -51,7 +56,10 @@ def can_talk_to_agent():
""" """
return bool(_get_pageant_window_object()) return bool(_get_pageant_window_object())
ULONG_PTR = ctypes.c_uint64 if platform.architecture()[0] == '64bit' else ctypes.c_uint32 ULONG_PTR = ctypes.c_uint64 if platform.architecture()[0] == '64bit' else ctypes.c_uint32
class COPYDATASTRUCT(ctypes.Structure): class COPYDATASTRUCT(ctypes.Structure):
""" """
ctypes implementation of ctypes implementation of
@ -61,7 +69,8 @@ class COPYDATASTRUCT(ctypes.Structure):
('num_data', ULONG_PTR), ('num_data', ULONG_PTR),
('data_size', ctypes.wintypes.DWORD), ('data_size', ctypes.wintypes.DWORD),
('data_loc', ctypes.c_void_p), ('data_loc', ctypes.c_void_p),
] ]
def _query_pageant(msg): def _query_pageant(msg):
""" """
@ -74,7 +83,7 @@ def _query_pageant(msg):
return None return None
# create a name for the mmap # create a name for the mmap
map_name = 'PageantRequest%08x' % threading.current_thread().ident map_name = 'PageantRequest%08x' % thread.get_ident()
pymap = _winapi.MemoryMap(map_name, _AGENT_MAX_MSGLEN, pymap = _winapi.MemoryMap(map_name, _AGENT_MAX_MSGLEN,
_winapi.get_security_attributes_for_user(), _winapi.get_security_attributes_for_user(),
@ -98,7 +107,8 @@ def _query_pageant(msg):
return datalen + pymap.read(retlen) return datalen + pymap.read(retlen)
return None return None
class PageantConnection (object):
class PageantConnection(object):
""" """
Mock "connection" to an agent which roughly approximates the behavior of Mock "connection" to an agent which roughly approximates the behavior of
a unix local-domain socket (as used by Agent). Requests are sent to the a unix local-domain socket (as used by Agent). Requests are sent to the