ยปCore Development>Code coverage>Lib/test/symlink_support.py

Python code coverage for Lib/test/symlink_support.py

#countcontent
1n/a"""
2n/aA module built to test if the current process has the privilege to
3n/acreate symlinks on Windows.
4n/a"""
5n/a
6n/a# allow script to run natively under python 2.6+
7n/afrom __future__ import print_function
8n/a
9n/aimport ctypes
10n/afrom ctypes import wintypes
11n/a
12n/aGetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
13n/aGetCurrentProcess.restype = wintypes.HANDLE
14n/aOpenProcessToken = ctypes.windll.advapi32.OpenProcessToken
15n/aOpenProcessToken.argtypes = (wintypes.HANDLE, wintypes.DWORD,
16n/a ctypes.POINTER(wintypes.HANDLE))
17n/aOpenProcessToken.restype = wintypes.BOOL
18n/a
19n/aclass LUID(ctypes.Structure):
20n/a _fields_ = [
21n/a ('low_part', wintypes.DWORD),
22n/a ('high_part', wintypes.LONG),
23n/a ]
24n/a
25n/a def __eq__(self, other):
26n/a return (
27n/a self.high_part == other.high_part and
28n/a self.low_part == other.low_part
29n/a )
30n/a
31n/a def __ne__(self, other):
32n/a return not (self==other)
33n/a
34n/aLookupPrivilegeValue = ctypes.windll.advapi32.LookupPrivilegeValueW
35n/aLookupPrivilegeValue.argtypes = (
36n/a wintypes.LPWSTR, # system name
37n/a wintypes.LPWSTR, # name
38n/a ctypes.POINTER(LUID),
39n/a )
40n/aLookupPrivilegeValue.restype = wintypes.BOOL
41n/a
42n/aclass TOKEN_INFORMATION_CLASS:
43n/a TokenUser = 1
44n/a TokenGroups = 2
45n/a TokenPrivileges = 3
46n/a # ... see http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx
47n/a
48n/aSE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001)
49n/aSE_PRIVILEGE_ENABLED = (0x00000002)
50n/aSE_PRIVILEGE_REMOVED = (0x00000004)
51n/aSE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000)
52n/a
53n/aclass LUID_AND_ATTRIBUTES(ctypes.Structure):
54n/a _fields_ = [
55n/a ('LUID', LUID),
56n/a ('attributes', wintypes.DWORD),
57n/a ]
58n/a
59n/a def is_enabled(self):
60n/a return bool(self.attributes & SE_PRIVILEGE_ENABLED)
61n/a
62n/a def enable(self):
63n/a self.attributes |= SE_PRIVILEGE_ENABLED
64n/a
65n/a def get_name(self):
66n/a size = wintypes.DWORD(10240)
67n/a buf = ctypes.create_unicode_buffer(size.value)
68n/a res = LookupPrivilegeName(None, self.LUID, buf, size)
69n/a if res == 0:
70n/a raise RuntimeError
71n/a return buf[:size.value]
72n/a
73n/a def __str__(self):
74n/a name = self.name
75n/a fmt = ['{name}', '{name} (enabled)'][self.is_enabled()]
76n/a return fmt.format(**vars())
77n/a
78n/aLookupPrivilegeName = ctypes.windll.advapi32.LookupPrivilegeNameW
79n/aLookupPrivilegeName.argtypes = (
80n/a wintypes.LPWSTR, # lpSystemName
81n/a ctypes.POINTER(LUID), # lpLuid
82n/a wintypes.LPWSTR, # lpName
83n/a ctypes.POINTER(wintypes.DWORD), #cchName
84n/a )
85n/aLookupPrivilegeName.restype = wintypes.BOOL
86n/a
87n/aclass TOKEN_PRIVILEGES(ctypes.Structure):
88n/a _fields_ = [
89n/a ('count', wintypes.DWORD),
90n/a ('privileges', LUID_AND_ATTRIBUTES*0),
91n/a ]
92n/a
93n/a def get_array(self):
94n/a array_type = LUID_AND_ATTRIBUTES*self.count
95n/a privileges = ctypes.cast(self.privileges,
96n/a ctypes.POINTER(array_type)).contents
97n/a return privileges
98n/a
99n/a def __iter__(self):
100n/a return iter(self.get_array())
101n/a
102n/aPTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES)
103n/a
104n/aGetTokenInformation = ctypes.windll.advapi32.GetTokenInformation
105n/aGetTokenInformation.argtypes = [
106n/a wintypes.HANDLE, # TokenHandle
107n/a ctypes.c_uint, # TOKEN_INFORMATION_CLASS value
108n/a ctypes.c_void_p, # TokenInformation
109n/a wintypes.DWORD, # TokenInformationLength
110n/a ctypes.POINTER(wintypes.DWORD), # ReturnLength
111n/a ]
112n/aGetTokenInformation.restype = wintypes.BOOL
113n/a
114n/a# http://msdn.microsoft.com/en-us/library/aa375202%28VS.85%29.aspx
115n/aAdjustTokenPrivileges = ctypes.windll.advapi32.AdjustTokenPrivileges
116n/aAdjustTokenPrivileges.restype = wintypes.BOOL
117n/aAdjustTokenPrivileges.argtypes = [
118n/a wintypes.HANDLE, # TokenHandle
119n/a wintypes.BOOL, # DisableAllPrivileges
120n/a PTOKEN_PRIVILEGES, # NewState (optional)
121n/a wintypes.DWORD, # BufferLength of PreviousState
122n/a PTOKEN_PRIVILEGES, # PreviousState (out, optional)
123n/a ctypes.POINTER(wintypes.DWORD), # ReturnLength
124n/a ]
125n/a
126n/adef get_process_token():
127n/a "Get the current process token"
128n/a token = wintypes.HANDLE()
129n/a TOKEN_ALL_ACCESS = 0xf01ff
130n/a res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token)
131n/a if not res > 0:
132n/a raise RuntimeError("Couldn't get process token")
133n/a return token
134n/a
135n/adef get_symlink_luid():
136n/a "Get the LUID for the SeCreateSymbolicLinkPrivilege"
137n/a symlink_luid = LUID()
138n/a res = LookupPrivilegeValue(None, "SeCreateSymbolicLinkPrivilege",
139n/a symlink_luid)
140n/a if not res > 0:
141n/a raise RuntimeError("Couldn't lookup privilege value")
142n/a return symlink_luid
143n/a
144n/adef get_privilege_information():
145n/a "Get all privileges associated with the current process."
146n/a # first call with zero length to determine what size buffer we need
147n/a
148n/a return_length = wintypes.DWORD()
149n/a params = [
150n/a get_process_token(),
151n/a TOKEN_INFORMATION_CLASS.TokenPrivileges,
152n/a None,
153n/a 0,
154n/a return_length,
155n/a ]
156n/a
157n/a res = GetTokenInformation(*params)
158n/a
159n/a # assume we now have the necessary length in return_length
160n/a
161n/a buffer = ctypes.create_string_buffer(return_length.value)
162n/a params[2] = buffer
163n/a params[3] = return_length.value
164n/a
165n/a res = GetTokenInformation(*params)
166n/a assert res > 0, "Error in second GetTokenInformation (%d)" % res
167n/a
168n/a privileges = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents
169n/a return privileges
170n/a
171n/adef report_privilege_information():
172n/a "Report all privilege information assigned to the current process."
173n/a privileges = get_privilege_information()
174n/a print("found {0} privileges".format(privileges.count))
175n/a tuple(map(print, privileges))
176n/a
177n/adef enable_symlink_privilege():
178n/a """
179n/a Try to assign the symlink privilege to the current process token.
180n/a Return True if the assignment is successful.
181n/a """
182n/a # create a space in memory for a TOKEN_PRIVILEGES structure
183n/a # with one element
184n/a size = ctypes.sizeof(TOKEN_PRIVILEGES)
185n/a size += ctypes.sizeof(LUID_AND_ATTRIBUTES)
186n/a buffer = ctypes.create_string_buffer(size)
187n/a tp = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents
188n/a tp.count = 1
189n/a tp.get_array()[0].enable()
190n/a tp.get_array()[0].LUID = get_symlink_luid()
191n/a token = get_process_token()
192n/a res = AdjustTokenPrivileges(token, False, tp, 0, None, None)
193n/a if res == 0:
194n/a raise RuntimeError("Error in AdjustTokenPrivileges")
195n/a
196n/a ERROR_NOT_ALL_ASSIGNED = 1300
197n/a return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED
198n/a
199n/adef main():
200n/a assigned = enable_symlink_privilege()
201n/a msg = ['failure', 'success'][assigned]
202n/a
203n/a print("Symlink privilege assignment completed with {0}".format(msg))
204n/a
205n/aif __name__ == '__main__':
206n/a main()