_winapi.py 11 KB

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