~davide-cst00/uftp/0.2

« back to all changes in this revision

Viewing changes to paramiko/_winapi.py

  • Committer: Davide Costa
  • Date: 2018-09-14 12:21:37 UTC
  • Revision ID: davide.cst00@gmail.com-20180914122137-j0ycqb4tk9z2r1k5
Xenial release 0.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Windows API functions implemented as ctypes functions and classes as found
 
3
in jaraco.windows (3.4.1).
 
4
 
 
5
If you encounter issues with this module, please consider reporting the issues
 
6
in jaraco.windows and asking the author to port the fixes back here.
 
7
"""
 
8
 
 
9
import sys
 
10
import ctypes.wintypes
 
11
 
 
12
from paramiko.py3compat import u, builtins
 
13
 
 
14
 
 
15
######################
 
16
# jaraco.windows.error
 
17
 
 
18
def format_system_message(errno):
 
19
    """
 
20
    Call FormatMessage with a system error number to retrieve
 
21
    the descriptive error message.
 
22
    """
 
23
    # first some flags used by FormatMessageW
 
24
    ALLOCATE_BUFFER = 0x100
 
25
    FROM_SYSTEM = 0x1000
 
26
 
 
27
    # Let FormatMessageW allocate the buffer (we'll free it below)
 
28
    # Also, let it know we want a system error message.
 
29
    flags = ALLOCATE_BUFFER | FROM_SYSTEM
 
30
    source = None
 
31
    message_id = errno
 
32
    language_id = 0
 
33
    result_buffer = ctypes.wintypes.LPWSTR()
 
34
    buffer_size = 0
 
35
    arguments = None
 
36
    bytes = ctypes.windll.kernel32.FormatMessageW(
 
37
        flags,
 
38
        source,
 
39
        message_id,
 
40
        language_id,
 
41
        ctypes.byref(result_buffer),
 
42
        buffer_size,
 
43
        arguments,
 
44
    )
 
45
    # note the following will cause an infinite loop if GetLastError
 
46
    #  repeatedly returns an error that cannot be formatted, although
 
47
    #  this should not happen.
 
48
    handle_nonzero_success(bytes)
 
49
    message = result_buffer.value
 
50
    ctypes.windll.kernel32.LocalFree(result_buffer)
 
51
    return message
 
52
 
 
53
 
 
54
class WindowsError(builtins.WindowsError):
 
55
    """more info about errors at
 
56
    http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx"""
 
57
 
 
58
    def __init__(self, value=None):
 
59
        if value is None:
 
60
            value = ctypes.windll.kernel32.GetLastError()
 
61
        strerror = format_system_message(value)
 
62
        if sys.version_info > (3, 3):
 
63
            args = 0, strerror, None, value
 
64
        else:
 
65
            args = value, strerror
 
66
        super(WindowsError, self).__init__(*args)
 
67
 
 
68
    @property
 
69
    def message(self):
 
70
        return self.strerror
 
71
 
 
72
    @property
 
73
    def code(self):
 
74
        return self.winerror
 
75
 
 
76
    def __str__(self):
 
77
        return self.message
 
78
 
 
79
    def __repr__(self):
 
80
        return '{self.__class__.__name__}({self.winerror})'.format(**vars())
 
81
 
 
82
 
 
83
def handle_nonzero_success(result):
 
84
    if result == 0:
 
85
        raise WindowsError()
 
86
 
 
87
 
 
88
###########################
 
89
# jaraco.windows.api.memory
 
90
 
 
91
GMEM_MOVEABLE = 0x2
 
92
 
 
93
GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc
 
94
GlobalAlloc.argtypes = ctypes.wintypes.UINT, ctypes.c_size_t
 
95
GlobalAlloc.restype = ctypes.wintypes.HANDLE
 
96
 
 
97
GlobalLock = ctypes.windll.kernel32.GlobalLock
 
98
GlobalLock.argtypes = ctypes.wintypes.HGLOBAL,
 
99
GlobalLock.restype = ctypes.wintypes.LPVOID
 
100
 
 
101
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
 
102
GlobalUnlock.argtypes = ctypes.wintypes.HGLOBAL,
 
103
GlobalUnlock.restype = ctypes.wintypes.BOOL
 
104
 
 
105
GlobalSize = ctypes.windll.kernel32.GlobalSize
 
106
GlobalSize.argtypes = ctypes.wintypes.HGLOBAL,
 
107
GlobalSize.restype = ctypes.c_size_t
 
108
 
 
109
CreateFileMapping = ctypes.windll.kernel32.CreateFileMappingW
 
110
CreateFileMapping.argtypes = [
 
111
    ctypes.wintypes.HANDLE,
 
112
    ctypes.c_void_p,
 
113
    ctypes.wintypes.DWORD,
 
114
    ctypes.wintypes.DWORD,
 
115
    ctypes.wintypes.DWORD,
 
116
    ctypes.wintypes.LPWSTR,
 
117
]
 
118
CreateFileMapping.restype = ctypes.wintypes.HANDLE
 
119
 
 
120
MapViewOfFile = ctypes.windll.kernel32.MapViewOfFile
 
121
MapViewOfFile.restype = ctypes.wintypes.HANDLE
 
122
 
 
123
UnmapViewOfFile = ctypes.windll.kernel32.UnmapViewOfFile
 
124
UnmapViewOfFile.argtypes = ctypes.wintypes.HANDLE,
 
125
 
 
126
RtlMoveMemory = ctypes.windll.kernel32.RtlMoveMemory
 
127
RtlMoveMemory.argtypes = (
 
128
    ctypes.c_void_p,
 
129
    ctypes.c_void_p,
 
130
    ctypes.c_size_t,
 
131
)
 
132
 
 
133
ctypes.windll.kernel32.LocalFree.argtypes = ctypes.wintypes.HLOCAL,
 
134
 
 
135
#####################
 
136
# jaraco.windows.mmap
 
137
 
 
138
 
 
139
class MemoryMap(object):
 
140
    """
 
141
    A memory map object which can have security attributes overridden.
 
142
    """
 
143
    def __init__(self, name, length, security_attributes=None):
 
144
        self.name = name
 
145
        self.length = length
 
146
        self.security_attributes = security_attributes
 
147
        self.pos = 0
 
148
 
 
149
    def __enter__(self):
 
150
        p_SA = (
 
151
            ctypes.byref(self.security_attributes)
 
152
            if self.security_attributes else None
 
153
        )
 
154
        INVALID_HANDLE_VALUE = -1
 
155
        PAGE_READWRITE = 0x4
 
156
        FILE_MAP_WRITE = 0x2
 
157
        filemap = ctypes.windll.kernel32.CreateFileMappingW(
 
158
            INVALID_HANDLE_VALUE, p_SA, PAGE_READWRITE, 0, self.length,
 
159
            u(self.name))
 
160
        handle_nonzero_success(filemap)
 
161
        if filemap == INVALID_HANDLE_VALUE:
 
162
            raise Exception("Failed to create file mapping")
 
163
        self.filemap = filemap
 
164
        self.view = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0)
 
165
        return self
 
166
 
 
167
    def seek(self, pos):
 
168
        self.pos = pos
 
169
 
 
170
    def write(self, msg):
 
171
        assert isinstance(msg, bytes)
 
172
        n = len(msg)
 
173
        if self.pos + n >= self.length:  # A little safety.
 
174
            raise ValueError("Refusing to write %d bytes" % n)
 
175
        dest = self.view + self.pos
 
176
        length = ctypes.c_size_t(n)
 
177
        ctypes.windll.kernel32.RtlMoveMemory(dest, msg, length)
 
178
        self.pos += n
 
179
 
 
180
    def read(self, n):
 
181
        """
 
182
        Read n bytes from mapped view.
 
183
        """
 
184
        out = ctypes.create_string_buffer(n)
 
185
        source = self.view + self.pos
 
186
        length = ctypes.c_size_t(n)
 
187
        ctypes.windll.kernel32.RtlMoveMemory(out, source, length)
 
188
        self.pos += n
 
189
        return out.raw
 
190
 
 
191
    def __exit__(self, exc_type, exc_val, tb):
 
192
        ctypes.windll.kernel32.UnmapViewOfFile(self.view)
 
193
        ctypes.windll.kernel32.CloseHandle(self.filemap)
 
194
 
 
195
 
 
196
#############################
 
197
# jaraco.windows.api.security
 
198
 
 
199
# from WinNT.h
 
200
READ_CONTROL = 0x00020000
 
201
STANDARD_RIGHTS_REQUIRED = 0x000F0000
 
202
STANDARD_RIGHTS_READ = READ_CONTROL
 
203
STANDARD_RIGHTS_WRITE = READ_CONTROL
 
204
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
 
205
STANDARD_RIGHTS_ALL = 0x001F0000
 
206
 
 
207
# from NTSecAPI.h
 
208
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001
 
209
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002
 
210
POLICY_GET_PRIVATE_INFORMATION = 0x00000004
 
211
POLICY_TRUST_ADMIN = 0x00000008
 
212
POLICY_CREATE_ACCOUNT = 0x00000010
 
213
POLICY_CREATE_SECRET = 0x00000020
 
214
POLICY_CREATE_PRIVILEGE = 0x00000040
 
215
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080
 
216
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100
 
217
POLICY_AUDIT_LOG_ADMIN = 0x00000200
 
218
POLICY_SERVER_ADMIN = 0x00000400
 
219
POLICY_LOOKUP_NAMES = 0x00000800
 
220
POLICY_NOTIFICATION = 0x00001000
 
221
 
 
222
POLICY_ALL_ACCESS = (
 
223
    STANDARD_RIGHTS_REQUIRED |
 
224
    POLICY_VIEW_LOCAL_INFORMATION |
 
225
    POLICY_VIEW_AUDIT_INFORMATION |
 
226
    POLICY_GET_PRIVATE_INFORMATION |
 
227
    POLICY_TRUST_ADMIN |
 
228
    POLICY_CREATE_ACCOUNT |
 
229
    POLICY_CREATE_SECRET |
 
230
    POLICY_CREATE_PRIVILEGE |
 
231
    POLICY_SET_DEFAULT_QUOTA_LIMITS |
 
232
    POLICY_SET_AUDIT_REQUIREMENTS |
 
233
    POLICY_AUDIT_LOG_ADMIN |
 
234
    POLICY_SERVER_ADMIN |
 
235
    POLICY_LOOKUP_NAMES)
 
236
 
 
237
 
 
238
POLICY_READ = (
 
239
    STANDARD_RIGHTS_READ |
 
240
    POLICY_VIEW_AUDIT_INFORMATION |
 
241
    POLICY_GET_PRIVATE_INFORMATION)
 
242
 
 
243
POLICY_WRITE = (
 
244
    STANDARD_RIGHTS_WRITE |
 
245
    POLICY_TRUST_ADMIN |
 
246
    POLICY_CREATE_ACCOUNT |
 
247
    POLICY_CREATE_SECRET |
 
248
    POLICY_CREATE_PRIVILEGE |
 
249
    POLICY_SET_DEFAULT_QUOTA_LIMITS |
 
250
    POLICY_SET_AUDIT_REQUIREMENTS |
 
251
    POLICY_AUDIT_LOG_ADMIN |
 
252
    POLICY_SERVER_ADMIN)
 
253
 
 
254
POLICY_EXECUTE = (
 
255
    STANDARD_RIGHTS_EXECUTE |
 
256
    POLICY_VIEW_LOCAL_INFORMATION |
 
257
    POLICY_LOOKUP_NAMES)
 
258
 
 
259
 
 
260
class TokenAccess:
 
261
    TOKEN_QUERY = 0x8
 
262
 
 
263
 
 
264
class TokenInformationClass:
 
265
    TokenUser = 1
 
266
 
 
267
 
 
268
class TOKEN_USER(ctypes.Structure):
 
269
    num = 1
 
270
    _fields_ = [
 
271
        ('SID', ctypes.c_void_p),
 
272
        ('ATTRIBUTES', ctypes.wintypes.DWORD),
 
273
    ]
 
274
 
 
275
 
 
276
class SECURITY_DESCRIPTOR(ctypes.Structure):
 
277
    """
 
278
    typedef struct _SECURITY_DESCRIPTOR
 
279
        {
 
280
        UCHAR Revision;
 
281
        UCHAR Sbz1;
 
282
        SECURITY_DESCRIPTOR_CONTROL Control;
 
283
        PSID Owner;
 
284
        PSID Group;
 
285
        PACL Sacl;
 
286
        PACL Dacl;
 
287
        }   SECURITY_DESCRIPTOR;
 
288
    """
 
289
    SECURITY_DESCRIPTOR_CONTROL = ctypes.wintypes.USHORT
 
290
    REVISION = 1
 
291
 
 
292
    _fields_ = [
 
293
        ('Revision', ctypes.c_ubyte),
 
294
        ('Sbz1', ctypes.c_ubyte),
 
295
        ('Control', SECURITY_DESCRIPTOR_CONTROL),
 
296
        ('Owner', ctypes.c_void_p),
 
297
        ('Group', ctypes.c_void_p),
 
298
        ('Sacl', ctypes.c_void_p),
 
299
        ('Dacl', ctypes.c_void_p),
 
300
    ]
 
301
 
 
302
 
 
303
class SECURITY_ATTRIBUTES(ctypes.Structure):
 
304
    """
 
305
    typedef struct _SECURITY_ATTRIBUTES {
 
306
        DWORD  nLength;
 
307
        LPVOID lpSecurityDescriptor;
 
308
        BOOL   bInheritHandle;
 
309
    } SECURITY_ATTRIBUTES;
 
310
    """
 
311
    _fields_ = [
 
312
        ('nLength', ctypes.wintypes.DWORD),
 
313
        ('lpSecurityDescriptor', ctypes.c_void_p),
 
314
        ('bInheritHandle', ctypes.wintypes.BOOL),
 
315
    ]
 
316
 
 
317
    def __init__(self, *args, **kwargs):
 
318
        super(SECURITY_ATTRIBUTES, self).__init__(*args, **kwargs)
 
319
        self.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)
 
320
 
 
321
    @property
 
322
    def descriptor(self):
 
323
        return self._descriptor
 
324
 
 
325
    @descriptor.setter
 
326
    def descriptor(self, value):
 
327
        self._descriptor = value
 
328
        self.lpSecurityDescriptor = ctypes.addressof(value)
 
329
 
 
330
 
 
331
ctypes.windll.advapi32.SetSecurityDescriptorOwner.argtypes = (
 
332
    ctypes.POINTER(SECURITY_DESCRIPTOR),
 
333
    ctypes.c_void_p,
 
334
    ctypes.wintypes.BOOL,
 
335
)
 
336
 
 
337
#########################
 
338
# jaraco.windows.security
 
339
 
 
340
 
 
341
def GetTokenInformation(token, information_class):
 
342
    """
 
343
    Given a token, get the token information for it.
 
344
    """
 
345
    data_size = ctypes.wintypes.DWORD()
 
346
    ctypes.windll.advapi32.GetTokenInformation(token, information_class.num,
 
347
        0, 0, ctypes.byref(data_size))
 
348
    data = ctypes.create_string_buffer(data_size.value)
 
349
    handle_nonzero_success(ctypes.windll.advapi32.GetTokenInformation(token,
 
350
        information_class.num,
 
351
        ctypes.byref(data), ctypes.sizeof(data),
 
352
        ctypes.byref(data_size)))
 
353
    return ctypes.cast(data, ctypes.POINTER(TOKEN_USER)).contents
 
354
 
 
355
 
 
356
def OpenProcessToken(proc_handle, access):
 
357
    result = ctypes.wintypes.HANDLE()
 
358
    proc_handle = ctypes.wintypes.HANDLE(proc_handle)
 
359
    handle_nonzero_success(ctypes.windll.advapi32.OpenProcessToken(
 
360
        proc_handle, access, ctypes.byref(result)))
 
361
    return result
 
362
 
 
363
 
 
364
def get_current_user():
 
365
    """
 
366
    Return a TOKEN_USER for the owner of this process.
 
367
    """
 
368
    process = OpenProcessToken(
 
369
        ctypes.windll.kernel32.GetCurrentProcess(),
 
370
        TokenAccess.TOKEN_QUERY,
 
371
    )
 
372
    return GetTokenInformation(process, TOKEN_USER)
 
373
 
 
374
 
 
375
def get_security_attributes_for_user(user=None):
 
376
    """
 
377
    Return a SECURITY_ATTRIBUTES structure with the SID set to the
 
378
    specified user (uses current user if none is specified).
 
379
    """
 
380
    if user is None:
 
381
        user = get_current_user()
 
382
 
 
383
    assert isinstance(user, TOKEN_USER), "user must be TOKEN_USER instance"
 
384
 
 
385
    SD = SECURITY_DESCRIPTOR()
 
386
    SA = SECURITY_ATTRIBUTES()
 
387
    # by attaching the actual security descriptor, it will be garbage-
 
388
    # collected with the security attributes
 
389
    SA.descriptor = SD
 
390
    SA.bInheritHandle = 1
 
391
 
 
392
    ctypes.windll.advapi32.InitializeSecurityDescriptor(ctypes.byref(SD),
 
393
        SECURITY_DESCRIPTOR.REVISION)
 
394
    ctypes.windll.advapi32.SetSecurityDescriptorOwner(ctypes.byref(SD),
 
395
        user.SID, 0)
 
396
    return SA