1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Library -- Win32 helper functions
3*c2e0c6b5SAndroid Build Coastguard Worker *
4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 2023 Pali Rohár <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker *
6*c2e0c6b5SAndroid Build Coastguard Worker * Can be freely distributed and used under the terms of the GNU GPL v2+
7*c2e0c6b5SAndroid Build Coastguard Worker *
8*c2e0c6b5SAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker */
10*c2e0c6b5SAndroid Build Coastguard Worker
11*c2e0c6b5SAndroid Build Coastguard Worker #include <windows.h>
12*c2e0c6b5SAndroid Build Coastguard Worker
13*c2e0c6b5SAndroid Build Coastguard Worker #include <stdio.h> /* for sprintf() */
14*c2e0c6b5SAndroid Build Coastguard Worker
15*c2e0c6b5SAndroid Build Coastguard Worker #include "win32-helpers.h"
16*c2e0c6b5SAndroid Build Coastguard Worker
17*c2e0c6b5SAndroid Build Coastguard Worker /* Unfortunately i586-mingw32msvc toolchain does not provide this constant. */
18*c2e0c6b5SAndroid Build Coastguard Worker #ifndef PROCESS_QUERY_LIMITED_INFORMATION
19*c2e0c6b5SAndroid Build Coastguard Worker #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
20*c2e0c6b5SAndroid Build Coastguard Worker #endif
21*c2e0c6b5SAndroid Build Coastguard Worker
22*c2e0c6b5SAndroid Build Coastguard Worker /* Unfortunately some toolchains do not provide this constant. */
23*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SE_IMPERSONATE_NAME
24*c2e0c6b5SAndroid Build Coastguard Worker #define SE_IMPERSONATE_NAME TEXT("SeImpersonatePrivilege")
25*c2e0c6b5SAndroid Build Coastguard Worker #endif
26*c2e0c6b5SAndroid Build Coastguard Worker
27*c2e0c6b5SAndroid Build Coastguard Worker /* Unfortunately some toolchains do not provide these constants. */
28*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SE_DACL_AUTO_INHERIT_REQ
29*c2e0c6b5SAndroid Build Coastguard Worker #define SE_DACL_AUTO_INHERIT_REQ 0x0100
30*c2e0c6b5SAndroid Build Coastguard Worker #endif
31*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SE_SACL_AUTO_INHERIT_REQ
32*c2e0c6b5SAndroid Build Coastguard Worker #define SE_SACL_AUTO_INHERIT_REQ 0x0200
33*c2e0c6b5SAndroid Build Coastguard Worker #endif
34*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SE_DACL_AUTO_INHERITED
35*c2e0c6b5SAndroid Build Coastguard Worker #define SE_DACL_AUTO_INHERITED 0x0400
36*c2e0c6b5SAndroid Build Coastguard Worker #endif
37*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SE_SACL_AUTO_INHERITED
38*c2e0c6b5SAndroid Build Coastguard Worker #define SE_SACL_AUTO_INHERITED 0x0800
39*c2e0c6b5SAndroid Build Coastguard Worker #endif
40*c2e0c6b5SAndroid Build Coastguard Worker
41*c2e0c6b5SAndroid Build Coastguard Worker /*
42*c2e0c6b5SAndroid Build Coastguard Worker * These psapi functions are available in kernel32.dll library with K32 prefix
43*c2e0c6b5SAndroid Build Coastguard Worker * on Windows 7 and higher systems. On older Windows systems these functions are
44*c2e0c6b5SAndroid Build Coastguard Worker * available in psapi.dll libary without K32 prefix. So resolve pointers to
45*c2e0c6b5SAndroid Build Coastguard Worker * these functions dynamically at runtime from the available system library.
46*c2e0c6b5SAndroid Build Coastguard Worker * Function GetProcessImageFileNameW() is not available on Windows 2000 and
47*c2e0c6b5SAndroid Build Coastguard Worker * older systems.
48*c2e0c6b5SAndroid Build Coastguard Worker */
49*c2e0c6b5SAndroid Build Coastguard Worker typedef BOOL (WINAPI *EnumProcessesProt)(DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded);
50*c2e0c6b5SAndroid Build Coastguard Worker typedef DWORD (WINAPI *GetProcessImageFileNameWProt)(HANDLE hProcess, LPWSTR lpImageFileName, DWORD nSize);
51*c2e0c6b5SAndroid Build Coastguard Worker typedef DWORD (WINAPI *GetModuleFileNameExWProt)(HANDLE hProcess, HMODULE hModule, LPWSTR lpImageFileName, DWORD nSize);
52*c2e0c6b5SAndroid Build Coastguard Worker
53*c2e0c6b5SAndroid Build Coastguard Worker /*
54*c2e0c6b5SAndroid Build Coastguard Worker * These aclapi function is available in advapi.dll library on Windows 2000
55*c2e0c6b5SAndroid Build Coastguard Worker * and higher systems.
56*c2e0c6b5SAndroid Build Coastguard Worker */
57*c2e0c6b5SAndroid Build Coastguard Worker typedef BOOL (WINAPI *SetSecurityDescriptorControlProt)(PSECURITY_DESCRIPTOR pSecurityDescriptor, SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);
58*c2e0c6b5SAndroid Build Coastguard Worker
59*c2e0c6b5SAndroid Build Coastguard Worker /*
60*c2e0c6b5SAndroid Build Coastguard Worker * This errhandlingapi function is available in kernel32.dll library on
61*c2e0c6b5SAndroid Build Coastguard Worker * Windows 7 and higher systems.
62*c2e0c6b5SAndroid Build Coastguard Worker */
63*c2e0c6b5SAndroid Build Coastguard Worker typedef BOOL (WINAPI *SetThreadErrorModeProt)(DWORD dwNewMode, LPDWORD lpOldMode);
64*c2e0c6b5SAndroid Build Coastguard Worker
65*c2e0c6b5SAndroid Build Coastguard Worker
66*c2e0c6b5SAndroid Build Coastguard Worker static DWORD
format_message_from_system(DWORD win32_error_id,DWORD lang_id,LPSTR buffer,DWORD size)67*c2e0c6b5SAndroid Build Coastguard Worker format_message_from_system(DWORD win32_error_id, DWORD lang_id, LPSTR buffer, DWORD size)
68*c2e0c6b5SAndroid Build Coastguard Worker {
69*c2e0c6b5SAndroid Build Coastguard Worker return FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, win32_error_id, lang_id, buffer, size, NULL);
70*c2e0c6b5SAndroid Build Coastguard Worker }
71*c2e0c6b5SAndroid Build Coastguard Worker
72*c2e0c6b5SAndroid Build Coastguard Worker const char *
win32_strerror(DWORD win32_error_id)73*c2e0c6b5SAndroid Build Coastguard Worker win32_strerror(DWORD win32_error_id)
74*c2e0c6b5SAndroid Build Coastguard Worker {
75*c2e0c6b5SAndroid Build Coastguard Worker /*
76*c2e0c6b5SAndroid Build Coastguard Worker * Use static buffer which is large enough.
77*c2e0c6b5SAndroid Build Coastguard Worker * Hopefully no Win32 API error message string is longer than 4 kB.
78*c2e0c6b5SAndroid Build Coastguard Worker */
79*c2e0c6b5SAndroid Build Coastguard Worker static char buffer[4096];
80*c2e0c6b5SAndroid Build Coastguard Worker DWORD len;
81*c2e0c6b5SAndroid Build Coastguard Worker
82*c2e0c6b5SAndroid Build Coastguard Worker /*
83*c2e0c6b5SAndroid Build Coastguard Worker * If it is possible show error messages in US English language.
84*c2e0c6b5SAndroid Build Coastguard Worker * International Windows editions do not have to provide error
85*c2e0c6b5SAndroid Build Coastguard Worker * messages in English language, so fallback to the language
86*c2e0c6b5SAndroid Build Coastguard Worker * which system provides (neutral).
87*c2e0c6b5SAndroid Build Coastguard Worker */
88*c2e0c6b5SAndroid Build Coastguard Worker len = format_message_from_system(win32_error_id, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), buffer, sizeof(buffer));
89*c2e0c6b5SAndroid Build Coastguard Worker if (!len)
90*c2e0c6b5SAndroid Build Coastguard Worker len = format_message_from_system(win32_error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer));
91*c2e0c6b5SAndroid Build Coastguard Worker
92*c2e0c6b5SAndroid Build Coastguard Worker /* FormatMessage() automatically appends ".\r\n" to the error message. */
93*c2e0c6b5SAndroid Build Coastguard Worker if (len && buffer[len-1] == '\n')
94*c2e0c6b5SAndroid Build Coastguard Worker buffer[--len] = '\0';
95*c2e0c6b5SAndroid Build Coastguard Worker if (len && buffer[len-1] == '\r')
96*c2e0c6b5SAndroid Build Coastguard Worker buffer[--len] = '\0';
97*c2e0c6b5SAndroid Build Coastguard Worker if (len && buffer[len-1] == '.')
98*c2e0c6b5SAndroid Build Coastguard Worker buffer[--len] = '\0';
99*c2e0c6b5SAndroid Build Coastguard Worker
100*c2e0c6b5SAndroid Build Coastguard Worker if (!len)
101*c2e0c6b5SAndroid Build Coastguard Worker sprintf(buffer, "Unknown Win32 error %lu", win32_error_id);
102*c2e0c6b5SAndroid Build Coastguard Worker
103*c2e0c6b5SAndroid Build Coastguard Worker return buffer;
104*c2e0c6b5SAndroid Build Coastguard Worker }
105*c2e0c6b5SAndroid Build Coastguard Worker
106*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_is_non_nt_system(void)107*c2e0c6b5SAndroid Build Coastguard Worker win32_is_non_nt_system(void)
108*c2e0c6b5SAndroid Build Coastguard Worker {
109*c2e0c6b5SAndroid Build Coastguard Worker OSVERSIONINFOA version;
110*c2e0c6b5SAndroid Build Coastguard Worker version.dwOSVersionInfoSize = sizeof(version);
111*c2e0c6b5SAndroid Build Coastguard Worker return GetVersionExA(&version) && version.dwPlatformId < VER_PLATFORM_WIN32_NT;
112*c2e0c6b5SAndroid Build Coastguard Worker }
113*c2e0c6b5SAndroid Build Coastguard Worker
114*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_is_32bit_on_64bit_system(void)115*c2e0c6b5SAndroid Build Coastguard Worker win32_is_32bit_on_64bit_system(void)
116*c2e0c6b5SAndroid Build Coastguard Worker {
117*c2e0c6b5SAndroid Build Coastguard Worker BOOL (WINAPI *MyIsWow64Process)(HANDLE, PBOOL);
118*c2e0c6b5SAndroid Build Coastguard Worker HMODULE kernel32;
119*c2e0c6b5SAndroid Build Coastguard Worker BOOL is_wow64;
120*c2e0c6b5SAndroid Build Coastguard Worker
121*c2e0c6b5SAndroid Build Coastguard Worker /*
122*c2e0c6b5SAndroid Build Coastguard Worker * Check for 64-bit system via IsWow64Process() function exported
123*c2e0c6b5SAndroid Build Coastguard Worker * from 32-bit kernel32.dll library available on the 64-bit systems.
124*c2e0c6b5SAndroid Build Coastguard Worker * Resolve pointer to this function at runtime as this code path is
125*c2e0c6b5SAndroid Build Coastguard Worker * primary running on 32-bit systems where are not available 64-bit
126*c2e0c6b5SAndroid Build Coastguard Worker * functions.
127*c2e0c6b5SAndroid Build Coastguard Worker */
128*c2e0c6b5SAndroid Build Coastguard Worker
129*c2e0c6b5SAndroid Build Coastguard Worker kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
130*c2e0c6b5SAndroid Build Coastguard Worker if (!kernel32)
131*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
132*c2e0c6b5SAndroid Build Coastguard Worker
133*c2e0c6b5SAndroid Build Coastguard Worker MyIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process");
134*c2e0c6b5SAndroid Build Coastguard Worker if (!MyIsWow64Process)
135*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
136*c2e0c6b5SAndroid Build Coastguard Worker
137*c2e0c6b5SAndroid Build Coastguard Worker if (!MyIsWow64Process(GetCurrentProcess(), &is_wow64))
138*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
139*c2e0c6b5SAndroid Build Coastguard Worker
140*c2e0c6b5SAndroid Build Coastguard Worker return is_wow64;
141*c2e0c6b5SAndroid Build Coastguard Worker }
142*c2e0c6b5SAndroid Build Coastguard Worker
143*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_is_32bit_on_win8_64bit_system(void)144*c2e0c6b5SAndroid Build Coastguard Worker win32_is_32bit_on_win8_64bit_system(void)
145*c2e0c6b5SAndroid Build Coastguard Worker {
146*c2e0c6b5SAndroid Build Coastguard Worker #ifdef _WIN64
147*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
148*c2e0c6b5SAndroid Build Coastguard Worker #else
149*c2e0c6b5SAndroid Build Coastguard Worker OSVERSIONINFOA version;
150*c2e0c6b5SAndroid Build Coastguard Worker
151*c2e0c6b5SAndroid Build Coastguard Worker /* Check for Windows 8 (NT 6.2). */
152*c2e0c6b5SAndroid Build Coastguard Worker version.dwOSVersionInfoSize = sizeof(version);
153*c2e0c6b5SAndroid Build Coastguard Worker if (!GetVersionExA(&version) ||
154*c2e0c6b5SAndroid Build Coastguard Worker version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
155*c2e0c6b5SAndroid Build Coastguard Worker version.dwMajorVersion < 6 ||
156*c2e0c6b5SAndroid Build Coastguard Worker (version.dwMajorVersion == 6 && version.dwMinorVersion < 2))
157*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
158*c2e0c6b5SAndroid Build Coastguard Worker
159*c2e0c6b5SAndroid Build Coastguard Worker return win32_is_32bit_on_64bit_system();
160*c2e0c6b5SAndroid Build Coastguard Worker #endif
161*c2e0c6b5SAndroid Build Coastguard Worker }
162*c2e0c6b5SAndroid Build Coastguard Worker
163*c2e0c6b5SAndroid Build Coastguard Worker /*
164*c2e0c6b5SAndroid Build Coastguard Worker * Change error mode of the current thread. If it is not possible then change
165*c2e0c6b5SAndroid Build Coastguard Worker * error mode of the whole process. Always returns previous error mode.
166*c2e0c6b5SAndroid Build Coastguard Worker */
167*c2e0c6b5SAndroid Build Coastguard Worker UINT
win32_change_error_mode(UINT new_mode)168*c2e0c6b5SAndroid Build Coastguard Worker win32_change_error_mode(UINT new_mode)
169*c2e0c6b5SAndroid Build Coastguard Worker {
170*c2e0c6b5SAndroid Build Coastguard Worker SetThreadErrorModeProt MySetThreadErrorMode = NULL;
171*c2e0c6b5SAndroid Build Coastguard Worker HMODULE kernel32;
172*c2e0c6b5SAndroid Build Coastguard Worker DWORD old_mode;
173*c2e0c6b5SAndroid Build Coastguard Worker
174*c2e0c6b5SAndroid Build Coastguard Worker /*
175*c2e0c6b5SAndroid Build Coastguard Worker * Function SetThreadErrorMode() was introduced in Windows 7, so use
176*c2e0c6b5SAndroid Build Coastguard Worker * GetProcAddress() for compatibility with older systems.
177*c2e0c6b5SAndroid Build Coastguard Worker */
178*c2e0c6b5SAndroid Build Coastguard Worker kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
179*c2e0c6b5SAndroid Build Coastguard Worker if (kernel32)
180*c2e0c6b5SAndroid Build Coastguard Worker MySetThreadErrorMode = (SetThreadErrorModeProt)(LPVOID)GetProcAddress(kernel32, "SetThreadErrorMode");
181*c2e0c6b5SAndroid Build Coastguard Worker
182*c2e0c6b5SAndroid Build Coastguard Worker if (MySetThreadErrorMode &&
183*c2e0c6b5SAndroid Build Coastguard Worker MySetThreadErrorMode(new_mode, &old_mode))
184*c2e0c6b5SAndroid Build Coastguard Worker return old_mode;
185*c2e0c6b5SAndroid Build Coastguard Worker
186*c2e0c6b5SAndroid Build Coastguard Worker /*
187*c2e0c6b5SAndroid Build Coastguard Worker * Fallback to function SetErrorMode() which modifies error mode of the
188*c2e0c6b5SAndroid Build Coastguard Worker * whole process and returns old mode.
189*c2e0c6b5SAndroid Build Coastguard Worker */
190*c2e0c6b5SAndroid Build Coastguard Worker return SetErrorMode(new_mode);
191*c2e0c6b5SAndroid Build Coastguard Worker }
192*c2e0c6b5SAndroid Build Coastguard Worker
193*c2e0c6b5SAndroid Build Coastguard Worker /*
194*c2e0c6b5SAndroid Build Coastguard Worker * Check if the current thread has particular privilege in current active access
195*c2e0c6b5SAndroid Build Coastguard Worker * token. Case when it not possible to determinate it (e.g. current thread does
196*c2e0c6b5SAndroid Build Coastguard Worker * not have permission to open its own current active access token) is evaluated
197*c2e0c6b5SAndroid Build Coastguard Worker * as thread does not have that privilege.
198*c2e0c6b5SAndroid Build Coastguard Worker */
199*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_have_privilege(LUID luid_privilege)200*c2e0c6b5SAndroid Build Coastguard Worker win32_have_privilege(LUID luid_privilege)
201*c2e0c6b5SAndroid Build Coastguard Worker {
202*c2e0c6b5SAndroid Build Coastguard Worker PRIVILEGE_SET priv;
203*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
204*c2e0c6b5SAndroid Build Coastguard Worker BOOL ret;
205*c2e0c6b5SAndroid Build Coastguard Worker
206*c2e0c6b5SAndroid Build Coastguard Worker /*
207*c2e0c6b5SAndroid Build Coastguard Worker * If the current thread does not have active access token then thread
208*c2e0c6b5SAndroid Build Coastguard Worker * uses primary process access token for all permission checks.
209*c2e0c6b5SAndroid Build Coastguard Worker */
210*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token) &&
211*c2e0c6b5SAndroid Build Coastguard Worker (GetLastError() != ERROR_NO_TOKEN ||
212*c2e0c6b5SAndroid Build Coastguard Worker !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)))
213*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
214*c2e0c6b5SAndroid Build Coastguard Worker
215*c2e0c6b5SAndroid Build Coastguard Worker priv.PrivilegeCount = 1;
216*c2e0c6b5SAndroid Build Coastguard Worker priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
217*c2e0c6b5SAndroid Build Coastguard Worker priv.Privilege[0].Luid = luid_privilege;
218*c2e0c6b5SAndroid Build Coastguard Worker priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
219*c2e0c6b5SAndroid Build Coastguard Worker
220*c2e0c6b5SAndroid Build Coastguard Worker if (!PrivilegeCheck(token, &priv, &ret))
221*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
222*c2e0c6b5SAndroid Build Coastguard Worker
223*c2e0c6b5SAndroid Build Coastguard Worker return ret;
224*c2e0c6b5SAndroid Build Coastguard Worker }
225*c2e0c6b5SAndroid Build Coastguard Worker
226*c2e0c6b5SAndroid Build Coastguard Worker /*
227*c2e0c6b5SAndroid Build Coastguard Worker * Enable or disable particular privilege in specified access token.
228*c2e0c6b5SAndroid Build Coastguard Worker *
229*c2e0c6b5SAndroid Build Coastguard Worker * Note that it is not possible to disable privilege in access token with
230*c2e0c6b5SAndroid Build Coastguard Worker * SE_PRIVILEGE_ENABLED_BY_DEFAULT attribute. This function does not check
231*c2e0c6b5SAndroid Build Coastguard Worker * this case and incorrectly returns no error even when disabling failed.
232*c2e0c6b5SAndroid Build Coastguard Worker * Rationale for this decision: Simplification of this function as WinAPI
233*c2e0c6b5SAndroid Build Coastguard Worker * call AdjustTokenPrivileges() does not signal error in this case too.
234*c2e0c6b5SAndroid Build Coastguard Worker */
235*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
set_privilege(HANDLE token,LUID luid_privilege,BOOL enable)236*c2e0c6b5SAndroid Build Coastguard Worker set_privilege(HANDLE token, LUID luid_privilege, BOOL enable)
237*c2e0c6b5SAndroid Build Coastguard Worker {
238*c2e0c6b5SAndroid Build Coastguard Worker TOKEN_PRIVILEGES token_privileges;
239*c2e0c6b5SAndroid Build Coastguard Worker
240*c2e0c6b5SAndroid Build Coastguard Worker token_privileges.PrivilegeCount = 1;
241*c2e0c6b5SAndroid Build Coastguard Worker token_privileges.Privileges[0].Luid = luid_privilege;
242*c2e0c6b5SAndroid Build Coastguard Worker token_privileges.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
243*c2e0c6b5SAndroid Build Coastguard Worker
244*c2e0c6b5SAndroid Build Coastguard Worker /*
245*c2e0c6b5SAndroid Build Coastguard Worker * WinAPI function AdjustTokenPrivileges() success also when not all
246*c2e0c6b5SAndroid Build Coastguard Worker * privileges were enabled. It is always required to check for failure
247*c2e0c6b5SAndroid Build Coastguard Worker * via GetLastError() call. AdjustTokenPrivileges() always sets error
248*c2e0c6b5SAndroid Build Coastguard Worker * also when it success, as opposite to other WinAPI functions.
249*c2e0c6b5SAndroid Build Coastguard Worker */
250*c2e0c6b5SAndroid Build Coastguard Worker if (!AdjustTokenPrivileges(token, FALSE, &token_privileges, sizeof(token_privileges), NULL, NULL) ||
251*c2e0c6b5SAndroid Build Coastguard Worker GetLastError() != ERROR_SUCCESS)
252*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
253*c2e0c6b5SAndroid Build Coastguard Worker
254*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
255*c2e0c6b5SAndroid Build Coastguard Worker }
256*c2e0c6b5SAndroid Build Coastguard Worker
257*c2e0c6b5SAndroid Build Coastguard Worker /*
258*c2e0c6b5SAndroid Build Coastguard Worker * Change access token for the current thread to new specified access token.
259*c2e0c6b5SAndroid Build Coastguard Worker * Previously active access token is stored in old_token variable and can be
260*c2e0c6b5SAndroid Build Coastguard Worker * used for reverting to this access token. It is set to NULL if the current
261*c2e0c6b5SAndroid Build Coastguard Worker * thread previously used primary process access token.
262*c2e0c6b5SAndroid Build Coastguard Worker */
263*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_change_token(HANDLE new_token,HANDLE * old_token)264*c2e0c6b5SAndroid Build Coastguard Worker win32_change_token(HANDLE new_token, HANDLE *old_token)
265*c2e0c6b5SAndroid Build Coastguard Worker {
266*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
267*c2e0c6b5SAndroid Build Coastguard Worker
268*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &token))
269*c2e0c6b5SAndroid Build Coastguard Worker {
270*c2e0c6b5SAndroid Build Coastguard Worker if (GetLastError() != ERROR_NO_TOKEN)
271*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
272*c2e0c6b5SAndroid Build Coastguard Worker token = NULL;
273*c2e0c6b5SAndroid Build Coastguard Worker }
274*c2e0c6b5SAndroid Build Coastguard Worker
275*c2e0c6b5SAndroid Build Coastguard Worker if (!ImpersonateLoggedOnUser(new_token))
276*c2e0c6b5SAndroid Build Coastguard Worker {
277*c2e0c6b5SAndroid Build Coastguard Worker if (token)
278*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
279*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
280*c2e0c6b5SAndroid Build Coastguard Worker }
281*c2e0c6b5SAndroid Build Coastguard Worker
282*c2e0c6b5SAndroid Build Coastguard Worker *old_token = token;
283*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
284*c2e0c6b5SAndroid Build Coastguard Worker }
285*c2e0c6b5SAndroid Build Coastguard Worker
286*c2e0c6b5SAndroid Build Coastguard Worker /*
287*c2e0c6b5SAndroid Build Coastguard Worker * Change access token for the current thread to the primary process access
288*c2e0c6b5SAndroid Build Coastguard Worker * token. This function fails also when the current thread already uses primary
289*c2e0c6b5SAndroid Build Coastguard Worker * process access token.
290*c2e0c6b5SAndroid Build Coastguard Worker */
291*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
change_token_to_primary(HANDLE * old_token)292*c2e0c6b5SAndroid Build Coastguard Worker change_token_to_primary(HANDLE *old_token)
293*c2e0c6b5SAndroid Build Coastguard Worker {
294*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
295*c2e0c6b5SAndroid Build Coastguard Worker
296*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &token))
297*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
298*c2e0c6b5SAndroid Build Coastguard Worker
299*c2e0c6b5SAndroid Build Coastguard Worker RevertToSelf();
300*c2e0c6b5SAndroid Build Coastguard Worker
301*c2e0c6b5SAndroid Build Coastguard Worker *old_token = token;
302*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
303*c2e0c6b5SAndroid Build Coastguard Worker }
304*c2e0c6b5SAndroid Build Coastguard Worker
305*c2e0c6b5SAndroid Build Coastguard Worker /*
306*c2e0c6b5SAndroid Build Coastguard Worker * Revert to the specified access token for the current thread. When access
307*c2e0c6b5SAndroid Build Coastguard Worker * token is specified as NULL then revert to the primary process access token.
308*c2e0c6b5SAndroid Build Coastguard Worker * Use to revert after win32_change_token() or change_token_to_primary() call.
309*c2e0c6b5SAndroid Build Coastguard Worker */
310*c2e0c6b5SAndroid Build Coastguard Worker VOID
win32_revert_to_token(HANDLE token)311*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(HANDLE token)
312*c2e0c6b5SAndroid Build Coastguard Worker {
313*c2e0c6b5SAndroid Build Coastguard Worker /*
314*c2e0c6b5SAndroid Build Coastguard Worker * If SetThreadToken() call fails then there is no option to revert to
315*c2e0c6b5SAndroid Build Coastguard Worker * the specified previous thread access token. So in this case revert to
316*c2e0c6b5SAndroid Build Coastguard Worker * the primary process access token.
317*c2e0c6b5SAndroid Build Coastguard Worker */
318*c2e0c6b5SAndroid Build Coastguard Worker if (!token || !SetThreadToken(NULL, token))
319*c2e0c6b5SAndroid Build Coastguard Worker RevertToSelf();
320*c2e0c6b5SAndroid Build Coastguard Worker if (token)
321*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
322*c2e0c6b5SAndroid Build Coastguard Worker }
323*c2e0c6b5SAndroid Build Coastguard Worker
324*c2e0c6b5SAndroid Build Coastguard Worker /*
325*c2e0c6b5SAndroid Build Coastguard Worker * Enable particular privilege for the current thread. And set method how to
326*c2e0c6b5SAndroid Build Coastguard Worker * revert this privilege (if to revert whole token or only privilege).
327*c2e0c6b5SAndroid Build Coastguard Worker */
328*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_enable_privilege(LUID luid_privilege,HANDLE * revert_token,BOOL * revert_only_privilege)329*c2e0c6b5SAndroid Build Coastguard Worker win32_enable_privilege(LUID luid_privilege, HANDLE *revert_token, BOOL *revert_only_privilege)
330*c2e0c6b5SAndroid Build Coastguard Worker {
331*c2e0c6b5SAndroid Build Coastguard Worker HANDLE thread_token;
332*c2e0c6b5SAndroid Build Coastguard Worker HANDLE new_token;
333*c2e0c6b5SAndroid Build Coastguard Worker
334*c2e0c6b5SAndroid Build Coastguard Worker if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &thread_token))
335*c2e0c6b5SAndroid Build Coastguard Worker {
336*c2e0c6b5SAndroid Build Coastguard Worker if (set_privilege(thread_token, luid_privilege, TRUE))
337*c2e0c6b5SAndroid Build Coastguard Worker {
338*c2e0c6b5SAndroid Build Coastguard Worker /*
339*c2e0c6b5SAndroid Build Coastguard Worker * Indicate that correct revert method is just to
340*c2e0c6b5SAndroid Build Coastguard Worker * disable privilege in access token.
341*c2e0c6b5SAndroid Build Coastguard Worker */
342*c2e0c6b5SAndroid Build Coastguard Worker if (revert_token && revert_only_privilege)
343*c2e0c6b5SAndroid Build Coastguard Worker {
344*c2e0c6b5SAndroid Build Coastguard Worker *revert_token = thread_token;
345*c2e0c6b5SAndroid Build Coastguard Worker *revert_only_privilege = TRUE;
346*c2e0c6b5SAndroid Build Coastguard Worker }
347*c2e0c6b5SAndroid Build Coastguard Worker else
348*c2e0c6b5SAndroid Build Coastguard Worker {
349*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(thread_token);
350*c2e0c6b5SAndroid Build Coastguard Worker }
351*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
352*c2e0c6b5SAndroid Build Coastguard Worker }
353*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(thread_token);
354*c2e0c6b5SAndroid Build Coastguard Worker /*
355*c2e0c6b5SAndroid Build Coastguard Worker * If enabling privilege failed then try to enable it via
356*c2e0c6b5SAndroid Build Coastguard Worker * primary process access token.
357*c2e0c6b5SAndroid Build Coastguard Worker */
358*c2e0c6b5SAndroid Build Coastguard Worker }
359*c2e0c6b5SAndroid Build Coastguard Worker
360*c2e0c6b5SAndroid Build Coastguard Worker /*
361*c2e0c6b5SAndroid Build Coastguard Worker * If the current thread has already active thread access token then
362*c2e0c6b5SAndroid Build Coastguard Worker * open it with just impersonate right as it would be used only for
363*c2e0c6b5SAndroid Build Coastguard Worker * future revert.
364*c2e0c6b5SAndroid Build Coastguard Worker */
365*c2e0c6b5SAndroid Build Coastguard Worker if (revert_token && revert_only_privilege)
366*c2e0c6b5SAndroid Build Coastguard Worker {
367*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &thread_token))
368*c2e0c6b5SAndroid Build Coastguard Worker {
369*c2e0c6b5SAndroid Build Coastguard Worker if (GetLastError() != ERROR_NO_TOKEN)
370*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
371*c2e0c6b5SAndroid Build Coastguard Worker thread_token = NULL;
372*c2e0c6b5SAndroid Build Coastguard Worker }
373*c2e0c6b5SAndroid Build Coastguard Worker
374*c2e0c6b5SAndroid Build Coastguard Worker /*
375*c2e0c6b5SAndroid Build Coastguard Worker * If current thread has no access token (and uses primary
376*c2e0c6b5SAndroid Build Coastguard Worker * process access token) or it does not have permission to
377*c2e0c6b5SAndroid Build Coastguard Worker * adjust privileges or it does not have specified privilege
378*c2e0c6b5SAndroid Build Coastguard Worker * then create a copy of the primary process access token,
379*c2e0c6b5SAndroid Build Coastguard Worker * assign it for the current thread (= impersonate self)
380*c2e0c6b5SAndroid Build Coastguard Worker * and then try adjusting privilege again.
381*c2e0c6b5SAndroid Build Coastguard Worker */
382*c2e0c6b5SAndroid Build Coastguard Worker if (!ImpersonateSelf(SecurityImpersonation))
383*c2e0c6b5SAndroid Build Coastguard Worker {
384*c2e0c6b5SAndroid Build Coastguard Worker if (thread_token)
385*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(thread_token);
386*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
387*c2e0c6b5SAndroid Build Coastguard Worker }
388*c2e0c6b5SAndroid Build Coastguard Worker }
389*c2e0c6b5SAndroid Build Coastguard Worker
390*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &new_token))
391*c2e0c6b5SAndroid Build Coastguard Worker {
392*c2e0c6b5SAndroid Build Coastguard Worker /* thread_token is set only when we were asked for revert method. */
393*c2e0c6b5SAndroid Build Coastguard Worker if (revert_token && revert_only_privilege)
394*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(thread_token);
395*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
396*c2e0c6b5SAndroid Build Coastguard Worker }
397*c2e0c6b5SAndroid Build Coastguard Worker
398*c2e0c6b5SAndroid Build Coastguard Worker if (!set_privilege(new_token, luid_privilege, TRUE))
399*c2e0c6b5SAndroid Build Coastguard Worker {
400*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(new_token);
401*c2e0c6b5SAndroid Build Coastguard Worker /* thread_token is set only when we were asked for revert method. */
402*c2e0c6b5SAndroid Build Coastguard Worker if (revert_token && revert_only_privilege)
403*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(thread_token);
404*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
405*c2e0c6b5SAndroid Build Coastguard Worker }
406*c2e0c6b5SAndroid Build Coastguard Worker
407*c2e0c6b5SAndroid Build Coastguard Worker /*
408*c2e0c6b5SAndroid Build Coastguard Worker * Indicate that correct revert method is to change to the previous
409*c2e0c6b5SAndroid Build Coastguard Worker * access token. Either to the primary process access token or to the
410*c2e0c6b5SAndroid Build Coastguard Worker * previous thread access token.
411*c2e0c6b5SAndroid Build Coastguard Worker */
412*c2e0c6b5SAndroid Build Coastguard Worker if (revert_token && revert_only_privilege)
413*c2e0c6b5SAndroid Build Coastguard Worker {
414*c2e0c6b5SAndroid Build Coastguard Worker *revert_token = thread_token;
415*c2e0c6b5SAndroid Build Coastguard Worker *revert_only_privilege = FALSE;
416*c2e0c6b5SAndroid Build Coastguard Worker }
417*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
418*c2e0c6b5SAndroid Build Coastguard Worker }
419*c2e0c6b5SAndroid Build Coastguard Worker
420*c2e0c6b5SAndroid Build Coastguard Worker /*
421*c2e0c6b5SAndroid Build Coastguard Worker * Revert particular privilege for the current thread was previously enabled by
422*c2e0c6b5SAndroid Build Coastguard Worker * win32_enable_privilege() call. Either disable privilege in specified access token
423*c2e0c6b5SAndroid Build Coastguard Worker * or revert to previous access token.
424*c2e0c6b5SAndroid Build Coastguard Worker */
425*c2e0c6b5SAndroid Build Coastguard Worker VOID
win32_revert_privilege(LUID luid_privilege,HANDLE revert_token,BOOL revert_only_privilege)426*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_privilege(LUID luid_privilege, HANDLE revert_token, BOOL revert_only_privilege)
427*c2e0c6b5SAndroid Build Coastguard Worker {
428*c2e0c6b5SAndroid Build Coastguard Worker if (revert_only_privilege)
429*c2e0c6b5SAndroid Build Coastguard Worker {
430*c2e0c6b5SAndroid Build Coastguard Worker set_privilege(revert_token, luid_privilege, FALSE);
431*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(revert_token);
432*c2e0c6b5SAndroid Build Coastguard Worker }
433*c2e0c6b5SAndroid Build Coastguard Worker else
434*c2e0c6b5SAndroid Build Coastguard Worker {
435*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(revert_token);
436*c2e0c6b5SAndroid Build Coastguard Worker }
437*c2e0c6b5SAndroid Build Coastguard Worker }
438*c2e0c6b5SAndroid Build Coastguard Worker
439*c2e0c6b5SAndroid Build Coastguard Worker /*
440*c2e0c6b5SAndroid Build Coastguard Worker * Return owner of the access token used by the current thread. Buffer for
441*c2e0c6b5SAndroid Build Coastguard Worker * returned owner needs to be released by LocalFree() call.
442*c2e0c6b5SAndroid Build Coastguard Worker */
443*c2e0c6b5SAndroid Build Coastguard Worker static TOKEN_OWNER *
get_current_token_owner(VOID)444*c2e0c6b5SAndroid Build Coastguard Worker get_current_token_owner(VOID)
445*c2e0c6b5SAndroid Build Coastguard Worker {
446*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
447*c2e0c6b5SAndroid Build Coastguard Worker DWORD length;
448*c2e0c6b5SAndroid Build Coastguard Worker TOKEN_OWNER *owner;
449*c2e0c6b5SAndroid Build Coastguard Worker
450*c2e0c6b5SAndroid Build Coastguard Worker /*
451*c2e0c6b5SAndroid Build Coastguard Worker * If the current thread does not have active access token then thread
452*c2e0c6b5SAndroid Build Coastguard Worker * uses primary process access token for all permission checks.
453*c2e0c6b5SAndroid Build Coastguard Worker */
454*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token) &&
455*c2e0c6b5SAndroid Build Coastguard Worker (GetLastError() != ERROR_NO_TOKEN ||
456*c2e0c6b5SAndroid Build Coastguard Worker !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)))
457*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
458*c2e0c6b5SAndroid Build Coastguard Worker
459*c2e0c6b5SAndroid Build Coastguard Worker if (!GetTokenInformation(token, TokenOwner, NULL, 0, &length) &&
460*c2e0c6b5SAndroid Build Coastguard Worker GetLastError() != ERROR_INSUFFICIENT_BUFFER)
461*c2e0c6b5SAndroid Build Coastguard Worker {
462*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
463*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
464*c2e0c6b5SAndroid Build Coastguard Worker }
465*c2e0c6b5SAndroid Build Coastguard Worker
466*c2e0c6b5SAndroid Build Coastguard Worker retry:
467*c2e0c6b5SAndroid Build Coastguard Worker owner = (TOKEN_OWNER *)LocalAlloc(LPTR, length);
468*c2e0c6b5SAndroid Build Coastguard Worker if (!owner)
469*c2e0c6b5SAndroid Build Coastguard Worker {
470*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
471*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
472*c2e0c6b5SAndroid Build Coastguard Worker }
473*c2e0c6b5SAndroid Build Coastguard Worker
474*c2e0c6b5SAndroid Build Coastguard Worker if (!GetTokenInformation(token, TokenOwner, owner, length, &length))
475*c2e0c6b5SAndroid Build Coastguard Worker {
476*c2e0c6b5SAndroid Build Coastguard Worker /*
477*c2e0c6b5SAndroid Build Coastguard Worker * Length of token owner (SID) buffer between two get calls may
478*c2e0c6b5SAndroid Build Coastguard Worker * changes (e.g. by another thread of process), so retry.
479*c2e0c6b5SAndroid Build Coastguard Worker */
480*c2e0c6b5SAndroid Build Coastguard Worker if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
481*c2e0c6b5SAndroid Build Coastguard Worker {
482*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
483*c2e0c6b5SAndroid Build Coastguard Worker goto retry;
484*c2e0c6b5SAndroid Build Coastguard Worker }
485*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
486*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
487*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
488*c2e0c6b5SAndroid Build Coastguard Worker }
489*c2e0c6b5SAndroid Build Coastguard Worker
490*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
491*c2e0c6b5SAndroid Build Coastguard Worker return owner;
492*c2e0c6b5SAndroid Build Coastguard Worker }
493*c2e0c6b5SAndroid Build Coastguard Worker
494*c2e0c6b5SAndroid Build Coastguard Worker /*
495*c2e0c6b5SAndroid Build Coastguard Worker * Create a new security descriptor in absolute form from relative form.
496*c2e0c6b5SAndroid Build Coastguard Worker * Newly created security descriptor in absolute form is stored in linear buffer.
497*c2e0c6b5SAndroid Build Coastguard Worker */
498*c2e0c6b5SAndroid Build Coastguard Worker static PSECURITY_DESCRIPTOR
create_relsd_from_abssd(PSECURITY_DESCRIPTOR rel_security_descriptor)499*c2e0c6b5SAndroid Build Coastguard Worker create_relsd_from_abssd(PSECURITY_DESCRIPTOR rel_security_descriptor)
500*c2e0c6b5SAndroid Build Coastguard Worker {
501*c2e0c6b5SAndroid Build Coastguard Worker PBYTE abs_security_descriptor_buffer;
502*c2e0c6b5SAndroid Build Coastguard Worker DWORD abs_security_descriptor_size=0, abs_dacl_size=0, abs_sacl_size=0, abs_owner_size=0, abs_primary_group_size=0;
503*c2e0c6b5SAndroid Build Coastguard Worker
504*c2e0c6b5SAndroid Build Coastguard Worker if (!MakeAbsoluteSD(rel_security_descriptor,
505*c2e0c6b5SAndroid Build Coastguard Worker NULL, &abs_security_descriptor_size,
506*c2e0c6b5SAndroid Build Coastguard Worker NULL, &abs_dacl_size,
507*c2e0c6b5SAndroid Build Coastguard Worker NULL, &abs_sacl_size,
508*c2e0c6b5SAndroid Build Coastguard Worker NULL, &abs_owner_size,
509*c2e0c6b5SAndroid Build Coastguard Worker NULL, &abs_primary_group_size) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
510*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
511*c2e0c6b5SAndroid Build Coastguard Worker
512*c2e0c6b5SAndroid Build Coastguard Worker abs_security_descriptor_buffer = (PBYTE)LocalAlloc(LPTR, abs_security_descriptor_size+abs_dacl_size+abs_sacl_size+abs_owner_size+abs_primary_group_size);
513*c2e0c6b5SAndroid Build Coastguard Worker if (!abs_security_descriptor_buffer)
514*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
515*c2e0c6b5SAndroid Build Coastguard Worker
516*c2e0c6b5SAndroid Build Coastguard Worker if (!MakeAbsoluteSD(rel_security_descriptor,
517*c2e0c6b5SAndroid Build Coastguard Worker (PSECURITY_DESCRIPTOR)abs_security_descriptor_buffer, &abs_security_descriptor_size,
518*c2e0c6b5SAndroid Build Coastguard Worker (PACL)(abs_security_descriptor_buffer+abs_security_descriptor_size), &abs_dacl_size,
519*c2e0c6b5SAndroid Build Coastguard Worker (PACL)(abs_security_descriptor_buffer+abs_security_descriptor_size+abs_dacl_size), &abs_sacl_size,
520*c2e0c6b5SAndroid Build Coastguard Worker (PSID)(abs_security_descriptor_buffer+abs_security_descriptor_size+abs_dacl_size+abs_sacl_size), &abs_owner_size,
521*c2e0c6b5SAndroid Build Coastguard Worker (PSID)(abs_security_descriptor_buffer+abs_security_descriptor_size+abs_dacl_size+abs_sacl_size+abs_owner_size), &abs_primary_group_size))
522*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
523*c2e0c6b5SAndroid Build Coastguard Worker
524*c2e0c6b5SAndroid Build Coastguard Worker return (PSECURITY_DESCRIPTOR)abs_security_descriptor_buffer;
525*c2e0c6b5SAndroid Build Coastguard Worker }
526*c2e0c6b5SAndroid Build Coastguard Worker
527*c2e0c6b5SAndroid Build Coastguard Worker /*
528*c2e0c6b5SAndroid Build Coastguard Worker * Prepare security descriptor obtained by GetKernelObjectSecurity() so it can be
529*c2e0c6b5SAndroid Build Coastguard Worker * passed to SetKernelObjectSecurity() as identity operation. It modifies control
530*c2e0c6b5SAndroid Build Coastguard Worker * flags of security descriptor, which is needed for Windows 2000 and new.
531*c2e0c6b5SAndroid Build Coastguard Worker */
532*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
prepare_security_descriptor_for_set_operation(PSECURITY_DESCRIPTOR security_descriptor)533*c2e0c6b5SAndroid Build Coastguard Worker prepare_security_descriptor_for_set_operation(PSECURITY_DESCRIPTOR security_descriptor)
534*c2e0c6b5SAndroid Build Coastguard Worker {
535*c2e0c6b5SAndroid Build Coastguard Worker SetSecurityDescriptorControlProt MySetSecurityDescriptorControl;
536*c2e0c6b5SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR_CONTROL bits_mask;
537*c2e0c6b5SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR_CONTROL bits_set;
538*c2e0c6b5SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR_CONTROL control;
539*c2e0c6b5SAndroid Build Coastguard Worker OSVERSIONINFO version;
540*c2e0c6b5SAndroid Build Coastguard Worker HMODULE advapi32;
541*c2e0c6b5SAndroid Build Coastguard Worker DWORD revision;
542*c2e0c6b5SAndroid Build Coastguard Worker
543*c2e0c6b5SAndroid Build Coastguard Worker /*
544*c2e0c6b5SAndroid Build Coastguard Worker * SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED are flags introduced in
545*c2e0c6b5SAndroid Build Coastguard Worker * Windows 2000 to control client-side automatic inheritance (client - user
546*c2e0c6b5SAndroid Build Coastguard Worker * process - is responsible for propagating inherited ACEs to subobjects).
547*c2e0c6b5SAndroid Build Coastguard Worker * To prevent applications which do not understand client-side automatic
548*c2e0c6b5SAndroid Build Coastguard Worker * inheritance (applications created prior Windows 2000 or which use low
549*c2e0c6b5SAndroid Build Coastguard Worker * level API like SetKernelObjectSecurity()) to unintentionally set those
550*c2e0c6b5SAndroid Build Coastguard Worker * SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED control flags when
551*c2e0c6b5SAndroid Build Coastguard Worker * coping them from other security descriptor.
552*c2e0c6b5SAndroid Build Coastguard Worker *
553*c2e0c6b5SAndroid Build Coastguard Worker * As we are not modifying existing ACEs, we are compatible with Windows 2000
554*c2e0c6b5SAndroid Build Coastguard Worker * client-side automatic inheritance model and therefore prepare security
555*c2e0c6b5SAndroid Build Coastguard Worker * descriptor for SetKernelObjectSecurity() to not clear existing automatic
556*c2e0c6b5SAndroid Build Coastguard Worker * inheritance control flags.
557*c2e0c6b5SAndroid Build Coastguard Worker *
558*c2e0c6b5SAndroid Build Coastguard Worker * Control flags SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED are set
559*c2e0c6b5SAndroid Build Coastguard Worker * into security object only when they are set together with set-only flags
560*c2e0c6b5SAndroid Build Coastguard Worker * SE_DACL_AUTO_INHERIT_REQ and SE_SACL_AUTO_INHERIT_REQ. Those flags are
561*c2e0c6b5SAndroid Build Coastguard Worker * never received by GetKernelObjectSecurity() and are just commands for
562*c2e0c6b5SAndroid Build Coastguard Worker * SetKernelObjectSecurity() how to interpret SE_DACL_AUTO_INHERITED and
563*c2e0c6b5SAndroid Build Coastguard Worker * SE_SACL_AUTO_INHERITED flags.
564*c2e0c6b5SAndroid Build Coastguard Worker *
565*c2e0c6b5SAndroid Build Coastguard Worker * Function symbol SetSecurityDescriptorControl is not available in the
566*c2e0c6b5SAndroid Build Coastguard Worker * older versions of advapi32.dll library, so resolve it at runtime.
567*c2e0c6b5SAndroid Build Coastguard Worker */
568*c2e0c6b5SAndroid Build Coastguard Worker
569*c2e0c6b5SAndroid Build Coastguard Worker version.dwOSVersionInfoSize = sizeof(version);
570*c2e0c6b5SAndroid Build Coastguard Worker if (!GetVersionEx(&version) ||
571*c2e0c6b5SAndroid Build Coastguard Worker version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
572*c2e0c6b5SAndroid Build Coastguard Worker version.dwMajorVersion < 5)
573*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
574*c2e0c6b5SAndroid Build Coastguard Worker
575*c2e0c6b5SAndroid Build Coastguard Worker if (!GetSecurityDescriptorControl(security_descriptor, &control, &revision))
576*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
577*c2e0c6b5SAndroid Build Coastguard Worker
578*c2e0c6b5SAndroid Build Coastguard Worker bits_mask = 0;
579*c2e0c6b5SAndroid Build Coastguard Worker bits_set = 0;
580*c2e0c6b5SAndroid Build Coastguard Worker
581*c2e0c6b5SAndroid Build Coastguard Worker if (control & SE_DACL_AUTO_INHERITED)
582*c2e0c6b5SAndroid Build Coastguard Worker {
583*c2e0c6b5SAndroid Build Coastguard Worker bits_mask |= SE_DACL_AUTO_INHERIT_REQ;
584*c2e0c6b5SAndroid Build Coastguard Worker bits_set |= SE_DACL_AUTO_INHERIT_REQ;
585*c2e0c6b5SAndroid Build Coastguard Worker }
586*c2e0c6b5SAndroid Build Coastguard Worker
587*c2e0c6b5SAndroid Build Coastguard Worker if (control & SE_SACL_AUTO_INHERITED)
588*c2e0c6b5SAndroid Build Coastguard Worker {
589*c2e0c6b5SAndroid Build Coastguard Worker bits_mask |= SE_SACL_AUTO_INHERIT_REQ;
590*c2e0c6b5SAndroid Build Coastguard Worker bits_set |= SE_SACL_AUTO_INHERIT_REQ;
591*c2e0c6b5SAndroid Build Coastguard Worker }
592*c2e0c6b5SAndroid Build Coastguard Worker
593*c2e0c6b5SAndroid Build Coastguard Worker if (!bits_mask)
594*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
595*c2e0c6b5SAndroid Build Coastguard Worker
596*c2e0c6b5SAndroid Build Coastguard Worker advapi32 = GetModuleHandle(TEXT("advapi32.dll"));
597*c2e0c6b5SAndroid Build Coastguard Worker if (!advapi32)
598*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
599*c2e0c6b5SAndroid Build Coastguard Worker
600*c2e0c6b5SAndroid Build Coastguard Worker MySetSecurityDescriptorControl = (SetSecurityDescriptorControlProt)(LPVOID)GetProcAddress(advapi32, "SetSecurityDescriptorControl");
601*c2e0c6b5SAndroid Build Coastguard Worker if (!MySetSecurityDescriptorControl)
602*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
603*c2e0c6b5SAndroid Build Coastguard Worker
604*c2e0c6b5SAndroid Build Coastguard Worker if (!MySetSecurityDescriptorControl(security_descriptor, bits_mask, bits_set))
605*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
606*c2e0c6b5SAndroid Build Coastguard Worker
607*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
608*c2e0c6b5SAndroid Build Coastguard Worker }
609*c2e0c6b5SAndroid Build Coastguard Worker
610*c2e0c6b5SAndroid Build Coastguard Worker /*
611*c2e0c6b5SAndroid Build Coastguard Worker * Grant particular permissions in the primary access token of the specified
612*c2e0c6b5SAndroid Build Coastguard Worker * process for the owner of current thread token and set old DACL of the
613*c2e0c6b5SAndroid Build Coastguard Worker * process access token for reverting permissions. Security descriptor is
614*c2e0c6b5SAndroid Build Coastguard Worker * just memory buffer for old DACL.
615*c2e0c6b5SAndroid Build Coastguard Worker */
616*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
grant_process_token_dacl_permissions(HANDLE process,DWORD permissions,HANDLE * token,PSECURITY_DESCRIPTOR * old_security_descriptor)617*c2e0c6b5SAndroid Build Coastguard Worker grant_process_token_dacl_permissions(HANDLE process, DWORD permissions, HANDLE *token, PSECURITY_DESCRIPTOR *old_security_descriptor)
618*c2e0c6b5SAndroid Build Coastguard Worker {
619*c2e0c6b5SAndroid Build Coastguard Worker TOKEN_OWNER *owner;
620*c2e0c6b5SAndroid Build Coastguard Worker PACL old_dacl;
621*c2e0c6b5SAndroid Build Coastguard Worker BOOL old_dacl_present;
622*c2e0c6b5SAndroid Build Coastguard Worker BOOL old_dacl_defaulted;
623*c2e0c6b5SAndroid Build Coastguard Worker PACL new_dacl;
624*c2e0c6b5SAndroid Build Coastguard Worker WORD new_dacl_size;
625*c2e0c6b5SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR new_security_descriptor;
626*c2e0c6b5SAndroid Build Coastguard Worker DWORD length;
627*c2e0c6b5SAndroid Build Coastguard Worker
628*c2e0c6b5SAndroid Build Coastguard Worker owner = get_current_token_owner();
629*c2e0c6b5SAndroid Build Coastguard Worker if (!owner)
630*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
631*c2e0c6b5SAndroid Build Coastguard Worker
632*c2e0c6b5SAndroid Build Coastguard Worker /*
633*c2e0c6b5SAndroid Build Coastguard Worker * READ_CONTROL is required for GetSecurityInfo(DACL_SECURITY_INFORMATION)
634*c2e0c6b5SAndroid Build Coastguard Worker * and WRITE_DAC is required for SetSecurityInfo(DACL_SECURITY_INFORMATION).
635*c2e0c6b5SAndroid Build Coastguard Worker */
636*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenProcessToken(process, READ_CONTROL | WRITE_DAC, token))
637*c2e0c6b5SAndroid Build Coastguard Worker {
638*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
639*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
640*c2e0c6b5SAndroid Build Coastguard Worker }
641*c2e0c6b5SAndroid Build Coastguard Worker
642*c2e0c6b5SAndroid Build Coastguard Worker if (!GetKernelObjectSecurity(*token, DACL_SECURITY_INFORMATION, NULL, 0, &length) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
643*c2e0c6b5SAndroid Build Coastguard Worker {
644*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
645*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
646*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
647*c2e0c6b5SAndroid Build Coastguard Worker }
648*c2e0c6b5SAndroid Build Coastguard Worker
649*c2e0c6b5SAndroid Build Coastguard Worker retry:
650*c2e0c6b5SAndroid Build Coastguard Worker *old_security_descriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, length);
651*c2e0c6b5SAndroid Build Coastguard Worker if (!*old_security_descriptor)
652*c2e0c6b5SAndroid Build Coastguard Worker {
653*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
654*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
655*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
656*c2e0c6b5SAndroid Build Coastguard Worker }
657*c2e0c6b5SAndroid Build Coastguard Worker
658*c2e0c6b5SAndroid Build Coastguard Worker if (!GetKernelObjectSecurity(*token, DACL_SECURITY_INFORMATION, *old_security_descriptor, length, &length))
659*c2e0c6b5SAndroid Build Coastguard Worker {
660*c2e0c6b5SAndroid Build Coastguard Worker /*
661*c2e0c6b5SAndroid Build Coastguard Worker * Length of the security descriptor between two get calls
662*c2e0c6b5SAndroid Build Coastguard Worker * may changes (e.g. by another thread of process), so retry.
663*c2e0c6b5SAndroid Build Coastguard Worker */
664*c2e0c6b5SAndroid Build Coastguard Worker if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
665*c2e0c6b5SAndroid Build Coastguard Worker {
666*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
667*c2e0c6b5SAndroid Build Coastguard Worker goto retry;
668*c2e0c6b5SAndroid Build Coastguard Worker }
669*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
670*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
671*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
672*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
673*c2e0c6b5SAndroid Build Coastguard Worker }
674*c2e0c6b5SAndroid Build Coastguard Worker
675*c2e0c6b5SAndroid Build Coastguard Worker if (!prepare_security_descriptor_for_set_operation(*old_security_descriptor))
676*c2e0c6b5SAndroid Build Coastguard Worker {
677*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
678*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
679*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
680*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
681*c2e0c6b5SAndroid Build Coastguard Worker }
682*c2e0c6b5SAndroid Build Coastguard Worker
683*c2e0c6b5SAndroid Build Coastguard Worker /* Retrieve the current DACL from security descriptor including present and defaulted properties. */
684*c2e0c6b5SAndroid Build Coastguard Worker if (!GetSecurityDescriptorDacl(*old_security_descriptor, &old_dacl_present, &old_dacl, &old_dacl_defaulted))
685*c2e0c6b5SAndroid Build Coastguard Worker {
686*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
687*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
688*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
689*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
690*c2e0c6b5SAndroid Build Coastguard Worker }
691*c2e0c6b5SAndroid Build Coastguard Worker
692*c2e0c6b5SAndroid Build Coastguard Worker /*
693*c2e0c6b5SAndroid Build Coastguard Worker * If DACL is not present then system grants full access to everyone. It this
694*c2e0c6b5SAndroid Build Coastguard Worker * case do not modify DACL as it just adds one ACL allow rule for us, which
695*c2e0c6b5SAndroid Build Coastguard Worker * automatically disallow access to anybody else which had access before.
696*c2e0c6b5SAndroid Build Coastguard Worker */
697*c2e0c6b5SAndroid Build Coastguard Worker if (!old_dacl_present || !old_dacl)
698*c2e0c6b5SAndroid Build Coastguard Worker {
699*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
700*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
701*c2e0c6b5SAndroid Build Coastguard Worker *old_security_descriptor = NULL;
702*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
703*c2e0c6b5SAndroid Build Coastguard Worker }
704*c2e0c6b5SAndroid Build Coastguard Worker
705*c2e0c6b5SAndroid Build Coastguard Worker /* Create new DACL which would be copy of the current old one. */
706*c2e0c6b5SAndroid Build Coastguard Worker new_dacl_size = old_dacl->AclSize + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(owner->Owner) - sizeof(DWORD);
707*c2e0c6b5SAndroid Build Coastguard Worker new_dacl = (PACL)LocalAlloc(LPTR, new_dacl_size);
708*c2e0c6b5SAndroid Build Coastguard Worker if (!new_dacl)
709*c2e0c6b5SAndroid Build Coastguard Worker {
710*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
711*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
712*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
713*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
714*c2e0c6b5SAndroid Build Coastguard Worker }
715*c2e0c6b5SAndroid Build Coastguard Worker
716*c2e0c6b5SAndroid Build Coastguard Worker /*
717*c2e0c6b5SAndroid Build Coastguard Worker * Initialize new DACL structure to the same format as was the old one.
718*c2e0c6b5SAndroid Build Coastguard Worker * Set new explicit access for the owner of the current thread access
719*c2e0c6b5SAndroid Build Coastguard Worker * token with non-inherited granting access to specified permissions.
720*c2e0c6b5SAndroid Build Coastguard Worker * This permission is added in the first ACE, so has the highest priority.
721*c2e0c6b5SAndroid Build Coastguard Worker */
722*c2e0c6b5SAndroid Build Coastguard Worker if (!InitializeAcl(new_dacl, new_dacl_size, old_dacl->AclRevision) ||
723*c2e0c6b5SAndroid Build Coastguard Worker !AddAccessAllowedAce(new_dacl, ACL_REVISION2, permissions, owner->Owner))
724*c2e0c6b5SAndroid Build Coastguard Worker {
725*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_dacl);
726*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
727*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
728*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
729*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
730*c2e0c6b5SAndroid Build Coastguard Worker }
731*c2e0c6b5SAndroid Build Coastguard Worker
732*c2e0c6b5SAndroid Build Coastguard Worker /*
733*c2e0c6b5SAndroid Build Coastguard Worker * Now (after setting our new permissions) append all ACE entries from the
734*c2e0c6b5SAndroid Build Coastguard Worker * old DACL to the new DACL, which preserve all other existing permissions.
735*c2e0c6b5SAndroid Build Coastguard Worker */
736*c2e0c6b5SAndroid Build Coastguard Worker if (old_dacl->AceCount > 0)
737*c2e0c6b5SAndroid Build Coastguard Worker {
738*c2e0c6b5SAndroid Build Coastguard Worker WORD ace_index;
739*c2e0c6b5SAndroid Build Coastguard Worker LPVOID ace;
740*c2e0c6b5SAndroid Build Coastguard Worker
741*c2e0c6b5SAndroid Build Coastguard Worker for (ace_index = 0; ace_index < old_dacl->AceCount; ace_index++)
742*c2e0c6b5SAndroid Build Coastguard Worker {
743*c2e0c6b5SAndroid Build Coastguard Worker if (!GetAce(old_dacl, ace_index, &ace) ||
744*c2e0c6b5SAndroid Build Coastguard Worker !AddAce(new_dacl, old_dacl->AclRevision, MAXDWORD, ace, ((PACE_HEADER)ace)->AceSize))
745*c2e0c6b5SAndroid Build Coastguard Worker {
746*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_dacl);
747*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
748*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
749*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
750*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
751*c2e0c6b5SAndroid Build Coastguard Worker }
752*c2e0c6b5SAndroid Build Coastguard Worker }
753*c2e0c6b5SAndroid Build Coastguard Worker }
754*c2e0c6b5SAndroid Build Coastguard Worker
755*c2e0c6b5SAndroid Build Coastguard Worker /*
756*c2e0c6b5SAndroid Build Coastguard Worker * Create copy of the old security descriptor, so we can modify its DACL.
757*c2e0c6b5SAndroid Build Coastguard Worker * Function SetSecurityDescriptorDacl() works only with security descriptors
758*c2e0c6b5SAndroid Build Coastguard Worker * in absolute format. So use our helper function create_relsd_from_abssd()
759*c2e0c6b5SAndroid Build Coastguard Worker * for converting security descriptor from relative format (which is returned
760*c2e0c6b5SAndroid Build Coastguard Worker * by GetKernelObjectSecurity() function) to the absolute format.
761*c2e0c6b5SAndroid Build Coastguard Worker */
762*c2e0c6b5SAndroid Build Coastguard Worker new_security_descriptor = create_relsd_from_abssd(*old_security_descriptor);
763*c2e0c6b5SAndroid Build Coastguard Worker if (!new_security_descriptor)
764*c2e0c6b5SAndroid Build Coastguard Worker {
765*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_dacl);
766*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
767*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
768*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
769*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
770*c2e0c6b5SAndroid Build Coastguard Worker }
771*c2e0c6b5SAndroid Build Coastguard Worker
772*c2e0c6b5SAndroid Build Coastguard Worker /*
773*c2e0c6b5SAndroid Build Coastguard Worker * In the new security descriptor replace old DACL by the new DACL (which has
774*c2e0c6b5SAndroid Build Coastguard Worker * new permissions) and then set this new security descriptor to the token,
775*c2e0c6b5SAndroid Build Coastguard Worker * so token would have new access permissions.
776*c2e0c6b5SAndroid Build Coastguard Worker */
777*c2e0c6b5SAndroid Build Coastguard Worker if (!SetSecurityDescriptorDacl(new_security_descriptor, TRUE, new_dacl, FALSE) ||
778*c2e0c6b5SAndroid Build Coastguard Worker !SetKernelObjectSecurity(*token, DACL_SECURITY_INFORMATION, new_security_descriptor))
779*c2e0c6b5SAndroid Build Coastguard Worker {
780*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_security_descriptor);
781*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_dacl);
782*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(*old_security_descriptor);
783*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
784*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(*token);
785*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
786*c2e0c6b5SAndroid Build Coastguard Worker }
787*c2e0c6b5SAndroid Build Coastguard Worker
788*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_security_descriptor);
789*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(new_dacl);
790*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(owner);
791*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
792*c2e0c6b5SAndroid Build Coastguard Worker }
793*c2e0c6b5SAndroid Build Coastguard Worker
794*c2e0c6b5SAndroid Build Coastguard Worker /*
795*c2e0c6b5SAndroid Build Coastguard Worker * Revert particular granted permissions in specified access token done by
796*c2e0c6b5SAndroid Build Coastguard Worker * grant_process_token_dacl_permissions() call.
797*c2e0c6b5SAndroid Build Coastguard Worker */
798*c2e0c6b5SAndroid Build Coastguard Worker static VOID
revert_token_dacl_permissions(HANDLE token,PSECURITY_DESCRIPTOR old_security_descriptor)799*c2e0c6b5SAndroid Build Coastguard Worker revert_token_dacl_permissions(HANDLE token, PSECURITY_DESCRIPTOR old_security_descriptor)
800*c2e0c6b5SAndroid Build Coastguard Worker {
801*c2e0c6b5SAndroid Build Coastguard Worker SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, old_security_descriptor);
802*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(old_security_descriptor);
803*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(token);
804*c2e0c6b5SAndroid Build Coastguard Worker }
805*c2e0c6b5SAndroid Build Coastguard Worker
806*c2e0c6b5SAndroid Build Coastguard Worker /*
807*c2e0c6b5SAndroid Build Coastguard Worker * Open process handle specified by the process id with the query right and
808*c2e0c6b5SAndroid Build Coastguard Worker * optionally also with vm read right.
809*c2e0c6b5SAndroid Build Coastguard Worker */
810*c2e0c6b5SAndroid Build Coastguard Worker static HANDLE
open_process_for_query(DWORD pid,BOOL with_vm_read)811*c2e0c6b5SAndroid Build Coastguard Worker open_process_for_query(DWORD pid, BOOL with_vm_read)
812*c2e0c6b5SAndroid Build Coastguard Worker {
813*c2e0c6b5SAndroid Build Coastguard Worker BOOL revert_only_privilege;
814*c2e0c6b5SAndroid Build Coastguard Worker LUID luid_debug_privilege;
815*c2e0c6b5SAndroid Build Coastguard Worker OSVERSIONINFO version;
816*c2e0c6b5SAndroid Build Coastguard Worker DWORD process_right;
817*c2e0c6b5SAndroid Build Coastguard Worker HANDLE revert_token;
818*c2e0c6b5SAndroid Build Coastguard Worker HANDLE process;
819*c2e0c6b5SAndroid Build Coastguard Worker
820*c2e0c6b5SAndroid Build Coastguard Worker /*
821*c2e0c6b5SAndroid Build Coastguard Worker * Some processes on Windows Vista and higher systems can be opened only
822*c2e0c6b5SAndroid Build Coastguard Worker * with PROCESS_QUERY_LIMITED_INFORMATION right. This right is enough
823*c2e0c6b5SAndroid Build Coastguard Worker * for accessing primary process token. But this right is not supported
824*c2e0c6b5SAndroid Build Coastguard Worker * on older pre-Vista systems. When the current thread on these older
825*c2e0c6b5SAndroid Build Coastguard Worker * systems does not have Debug privilege then OpenProcess() fails with
826*c2e0c6b5SAndroid Build Coastguard Worker * ERROR_ACCESS_DENIED. If the current thread has Debug privilege then
827*c2e0c6b5SAndroid Build Coastguard Worker * OpenProcess() success and returns handle to requested process.
828*c2e0c6b5SAndroid Build Coastguard Worker * Problem is that this handle does not have PROCESS_QUERY_INFORMATION
829*c2e0c6b5SAndroid Build Coastguard Worker * right and so cannot be used for accessing primary process token
830*c2e0c6b5SAndroid Build Coastguard Worker * on those older systems. Moreover it has zero rights and therefore
831*c2e0c6b5SAndroid Build Coastguard Worker * such handle is fully useless. So never try to use open process with
832*c2e0c6b5SAndroid Build Coastguard Worker * PROCESS_QUERY_LIMITED_INFORMATION right on older systems than
833*c2e0c6b5SAndroid Build Coastguard Worker * Windows Vista (NT 6.0).
834*c2e0c6b5SAndroid Build Coastguard Worker */
835*c2e0c6b5SAndroid Build Coastguard Worker version.dwOSVersionInfoSize = sizeof(version);
836*c2e0c6b5SAndroid Build Coastguard Worker if (GetVersionEx(&version) &&
837*c2e0c6b5SAndroid Build Coastguard Worker version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
838*c2e0c6b5SAndroid Build Coastguard Worker version.dwMajorVersion >= 6)
839*c2e0c6b5SAndroid Build Coastguard Worker process_right = PROCESS_QUERY_LIMITED_INFORMATION;
840*c2e0c6b5SAndroid Build Coastguard Worker else
841*c2e0c6b5SAndroid Build Coastguard Worker process_right = PROCESS_QUERY_INFORMATION;
842*c2e0c6b5SAndroid Build Coastguard Worker
843*c2e0c6b5SAndroid Build Coastguard Worker if (with_vm_read)
844*c2e0c6b5SAndroid Build Coastguard Worker process_right |= PROCESS_VM_READ;
845*c2e0c6b5SAndroid Build Coastguard Worker
846*c2e0c6b5SAndroid Build Coastguard Worker process = OpenProcess(process_right, FALSE, pid);
847*c2e0c6b5SAndroid Build Coastguard Worker if (process)
848*c2e0c6b5SAndroid Build Coastguard Worker return process;
849*c2e0c6b5SAndroid Build Coastguard Worker
850*c2e0c6b5SAndroid Build Coastguard Worker /*
851*c2e0c6b5SAndroid Build Coastguard Worker * It is possible to open only processes to which owner of the current
852*c2e0c6b5SAndroid Build Coastguard Worker * thread access token has permissions. For opening other processing it
853*c2e0c6b5SAndroid Build Coastguard Worker * is required to have Debug privilege enabled. By default local
854*c2e0c6b5SAndroid Build Coastguard Worker * administrators have this privilege, but it is disabled. So try to
855*c2e0c6b5SAndroid Build Coastguard Worker * enable it and then try to open process again.
856*c2e0c6b5SAndroid Build Coastguard Worker */
857*c2e0c6b5SAndroid Build Coastguard Worker
858*c2e0c6b5SAndroid Build Coastguard Worker if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid_debug_privilege))
859*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
860*c2e0c6b5SAndroid Build Coastguard Worker
861*c2e0c6b5SAndroid Build Coastguard Worker if (!win32_enable_privilege(luid_debug_privilege, &revert_token, &revert_only_privilege))
862*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
863*c2e0c6b5SAndroid Build Coastguard Worker
864*c2e0c6b5SAndroid Build Coastguard Worker process = OpenProcess(process_right, FALSE, pid);
865*c2e0c6b5SAndroid Build Coastguard Worker
866*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_privilege(luid_debug_privilege, revert_token, revert_only_privilege);
867*c2e0c6b5SAndroid Build Coastguard Worker
868*c2e0c6b5SAndroid Build Coastguard Worker return process;
869*c2e0c6b5SAndroid Build Coastguard Worker }
870*c2e0c6b5SAndroid Build Coastguard Worker
871*c2e0c6b5SAndroid Build Coastguard Worker /*
872*c2e0c6b5SAndroid Build Coastguard Worker * Check if process image path name (wide string) matches exe file name
873*c2e0c6b5SAndroid Build Coastguard Worker * (7-bit ASCII string). Do case-insensitive string comparison. Process
874*c2e0c6b5SAndroid Build Coastguard Worker * image path name can be in any namespace format (DOS, Win32, UNC, ...).
875*c2e0c6b5SAndroid Build Coastguard Worker */
876*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
check_process_name(LPCWSTR path,DWORD path_length,LPCSTR exe_file)877*c2e0c6b5SAndroid Build Coastguard Worker check_process_name(LPCWSTR path, DWORD path_length, LPCSTR exe_file)
878*c2e0c6b5SAndroid Build Coastguard Worker {
879*c2e0c6b5SAndroid Build Coastguard Worker DWORD exe_file_length;
880*c2e0c6b5SAndroid Build Coastguard Worker WCHAR c1;
881*c2e0c6b5SAndroid Build Coastguard Worker UCHAR c2;
882*c2e0c6b5SAndroid Build Coastguard Worker DWORD i;
883*c2e0c6b5SAndroid Build Coastguard Worker
884*c2e0c6b5SAndroid Build Coastguard Worker exe_file_length = 0;
885*c2e0c6b5SAndroid Build Coastguard Worker while (exe_file[exe_file_length] != '\0')
886*c2e0c6b5SAndroid Build Coastguard Worker exe_file_length++;
887*c2e0c6b5SAndroid Build Coastguard Worker
888*c2e0c6b5SAndroid Build Coastguard Worker /* Path must have backslash before exe file name. */
889*c2e0c6b5SAndroid Build Coastguard Worker if (exe_file_length >= path_length ||
890*c2e0c6b5SAndroid Build Coastguard Worker path[path_length-exe_file_length-1] != L'\\')
891*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
892*c2e0c6b5SAndroid Build Coastguard Worker
893*c2e0c6b5SAndroid Build Coastguard Worker for (i = 0; i < exe_file_length; i++)
894*c2e0c6b5SAndroid Build Coastguard Worker {
895*c2e0c6b5SAndroid Build Coastguard Worker c1 = path[path_length-exe_file_length+i];
896*c2e0c6b5SAndroid Build Coastguard Worker c2 = exe_file[i];
897*c2e0c6b5SAndroid Build Coastguard Worker /*
898*c2e0c6b5SAndroid Build Coastguard Worker * Input string for comparison is 7-bit ASCII and file name part
899*c2e0c6b5SAndroid Build Coastguard Worker * of path must not contain backslash as it is path separator.
900*c2e0c6b5SAndroid Build Coastguard Worker */
901*c2e0c6b5SAndroid Build Coastguard Worker if (c1 >= 0x80 || c2 >= 0x80 || c1 == L'\\')
902*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
903*c2e0c6b5SAndroid Build Coastguard Worker if (c1 >= L'a' && c1 <= L'z')
904*c2e0c6b5SAndroid Build Coastguard Worker c1 -= L'a' - L'A';
905*c2e0c6b5SAndroid Build Coastguard Worker if (c2 >= 'a' && c2 <= 'z')
906*c2e0c6b5SAndroid Build Coastguard Worker c2 -= 'a' - 'A';
907*c2e0c6b5SAndroid Build Coastguard Worker if (c1 != c2)
908*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
909*c2e0c6b5SAndroid Build Coastguard Worker }
910*c2e0c6b5SAndroid Build Coastguard Worker
911*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
912*c2e0c6b5SAndroid Build Coastguard Worker }
913*c2e0c6b5SAndroid Build Coastguard Worker
914*c2e0c6b5SAndroid Build Coastguard Worker /* Open process handle with the query right specified by process exe file. */
915*c2e0c6b5SAndroid Build Coastguard Worker HANDLE
win32_find_and_open_process_for_query(LPCSTR exe_file)916*c2e0c6b5SAndroid Build Coastguard Worker win32_find_and_open_process_for_query(LPCSTR exe_file)
917*c2e0c6b5SAndroid Build Coastguard Worker {
918*c2e0c6b5SAndroid Build Coastguard Worker GetProcessImageFileNameWProt MyGetProcessImageFileNameW;
919*c2e0c6b5SAndroid Build Coastguard Worker GetModuleFileNameExWProt MyGetModuleFileNameExW;
920*c2e0c6b5SAndroid Build Coastguard Worker EnumProcessesProt MyEnumProcesses;
921*c2e0c6b5SAndroid Build Coastguard Worker HMODULE kernel32, psapi;
922*c2e0c6b5SAndroid Build Coastguard Worker UINT prev_error_mode;
923*c2e0c6b5SAndroid Build Coastguard Worker DWORD partial_retry;
924*c2e0c6b5SAndroid Build Coastguard Worker BOOL found_process;
925*c2e0c6b5SAndroid Build Coastguard Worker DWORD size, length;
926*c2e0c6b5SAndroid Build Coastguard Worker DWORD *processes;
927*c2e0c6b5SAndroid Build Coastguard Worker HANDLE process;
928*c2e0c6b5SAndroid Build Coastguard Worker LPWSTR path;
929*c2e0c6b5SAndroid Build Coastguard Worker DWORD error;
930*c2e0c6b5SAndroid Build Coastguard Worker DWORD count;
931*c2e0c6b5SAndroid Build Coastguard Worker DWORD i;
932*c2e0c6b5SAndroid Build Coastguard Worker
933*c2e0c6b5SAndroid Build Coastguard Worker psapi = NULL;
934*c2e0c6b5SAndroid Build Coastguard Worker kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
935*c2e0c6b5SAndroid Build Coastguard Worker if (!kernel32)
936*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
937*c2e0c6b5SAndroid Build Coastguard Worker
938*c2e0c6b5SAndroid Build Coastguard Worker /*
939*c2e0c6b5SAndroid Build Coastguard Worker * On Windows 7 and higher systems these functions are available in
940*c2e0c6b5SAndroid Build Coastguard Worker * kernel32.dll library with K32 prefix.
941*c2e0c6b5SAndroid Build Coastguard Worker */
942*c2e0c6b5SAndroid Build Coastguard Worker MyGetModuleFileNameExW = NULL;
943*c2e0c6b5SAndroid Build Coastguard Worker MyGetProcessImageFileNameW = (GetProcessImageFileNameWProt)(LPVOID)GetProcAddress(kernel32, "K32GetProcessImageFileNameW");
944*c2e0c6b5SAndroid Build Coastguard Worker MyEnumProcesses = (EnumProcessesProt)(LPVOID)GetProcAddress(kernel32, "K32EnumProcesses");
945*c2e0c6b5SAndroid Build Coastguard Worker if (!MyGetProcessImageFileNameW || !MyEnumProcesses)
946*c2e0c6b5SAndroid Build Coastguard Worker {
947*c2e0c6b5SAndroid Build Coastguard Worker /*
948*c2e0c6b5SAndroid Build Coastguard Worker * On older NT-based systems these functions are available in
949*c2e0c6b5SAndroid Build Coastguard Worker * psapi.dll library without K32 prefix.
950*c2e0c6b5SAndroid Build Coastguard Worker */
951*c2e0c6b5SAndroid Build Coastguard Worker prev_error_mode = win32_change_error_mode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
952*c2e0c6b5SAndroid Build Coastguard Worker psapi = LoadLibrary(TEXT("psapi.dll"));
953*c2e0c6b5SAndroid Build Coastguard Worker win32_change_error_mode(prev_error_mode);
954*c2e0c6b5SAndroid Build Coastguard Worker
955*c2e0c6b5SAndroid Build Coastguard Worker if (!psapi)
956*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
957*c2e0c6b5SAndroid Build Coastguard Worker
958*c2e0c6b5SAndroid Build Coastguard Worker /*
959*c2e0c6b5SAndroid Build Coastguard Worker * Function GetProcessImageFileNameW() is available in
960*c2e0c6b5SAndroid Build Coastguard Worker * Windows XP and higher systems. On older versions is
961*c2e0c6b5SAndroid Build Coastguard Worker * available function GetModuleFileNameExW().
962*c2e0c6b5SAndroid Build Coastguard Worker */
963*c2e0c6b5SAndroid Build Coastguard Worker MyGetProcessImageFileNameW = (GetProcessImageFileNameWProt)(LPVOID)GetProcAddress(psapi, "GetProcessImageFileNameW");
964*c2e0c6b5SAndroid Build Coastguard Worker MyGetModuleFileNameExW = (GetModuleFileNameExWProt)(LPVOID)GetProcAddress(psapi, "GetModuleFileNameExW");
965*c2e0c6b5SAndroid Build Coastguard Worker MyEnumProcesses = (EnumProcessesProt)(LPVOID)GetProcAddress(psapi, "EnumProcesses");
966*c2e0c6b5SAndroid Build Coastguard Worker if ((!MyGetProcessImageFileNameW && !MyGetModuleFileNameExW) || !MyEnumProcesses)
967*c2e0c6b5SAndroid Build Coastguard Worker {
968*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(psapi);
969*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
970*c2e0c6b5SAndroid Build Coastguard Worker }
971*c2e0c6b5SAndroid Build Coastguard Worker }
972*c2e0c6b5SAndroid Build Coastguard Worker
973*c2e0c6b5SAndroid Build Coastguard Worker /* Make initial buffer size for 1024 processes. */
974*c2e0c6b5SAndroid Build Coastguard Worker size = 1024 * sizeof(*processes);
975*c2e0c6b5SAndroid Build Coastguard Worker
976*c2e0c6b5SAndroid Build Coastguard Worker retry:
977*c2e0c6b5SAndroid Build Coastguard Worker processes = (DWORD *)LocalAlloc(LPTR, size);
978*c2e0c6b5SAndroid Build Coastguard Worker if (!processes)
979*c2e0c6b5SAndroid Build Coastguard Worker {
980*c2e0c6b5SAndroid Build Coastguard Worker if (psapi)
981*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(psapi);
982*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
983*c2e0c6b5SAndroid Build Coastguard Worker }
984*c2e0c6b5SAndroid Build Coastguard Worker
985*c2e0c6b5SAndroid Build Coastguard Worker if (!MyEnumProcesses(processes, size, &length))
986*c2e0c6b5SAndroid Build Coastguard Worker {
987*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(processes);
988*c2e0c6b5SAndroid Build Coastguard Worker if (psapi)
989*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(psapi);
990*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
991*c2e0c6b5SAndroid Build Coastguard Worker }
992*c2e0c6b5SAndroid Build Coastguard Worker else if (size == length)
993*c2e0c6b5SAndroid Build Coastguard Worker {
994*c2e0c6b5SAndroid Build Coastguard Worker /*
995*c2e0c6b5SAndroid Build Coastguard Worker * There is no indication given when the buffer is too small to
996*c2e0c6b5SAndroid Build Coastguard Worker * store all process identifiers. Therefore if returned length
997*c2e0c6b5SAndroid Build Coastguard Worker * is same as buffer size there can be more processes. Call
998*c2e0c6b5SAndroid Build Coastguard Worker * again with larger buffer.
999*c2e0c6b5SAndroid Build Coastguard Worker */
1000*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(processes);
1001*c2e0c6b5SAndroid Build Coastguard Worker size *= 2;
1002*c2e0c6b5SAndroid Build Coastguard Worker goto retry;
1003*c2e0c6b5SAndroid Build Coastguard Worker }
1004*c2e0c6b5SAndroid Build Coastguard Worker
1005*c2e0c6b5SAndroid Build Coastguard Worker process = NULL;
1006*c2e0c6b5SAndroid Build Coastguard Worker count = length / sizeof(*processes);
1007*c2e0c6b5SAndroid Build Coastguard Worker
1008*c2e0c6b5SAndroid Build Coastguard Worker for (i = 0; i < count; i++)
1009*c2e0c6b5SAndroid Build Coastguard Worker {
1010*c2e0c6b5SAndroid Build Coastguard Worker /* Skip System Idle Process. */
1011*c2e0c6b5SAndroid Build Coastguard Worker if (processes[i] == 0)
1012*c2e0c6b5SAndroid Build Coastguard Worker continue;
1013*c2e0c6b5SAndroid Build Coastguard Worker
1014*c2e0c6b5SAndroid Build Coastguard Worker /*
1015*c2e0c6b5SAndroid Build Coastguard Worker * Function GetModuleFileNameExW() requires additional
1016*c2e0c6b5SAndroid Build Coastguard Worker * PROCESS_VM_READ right as opposite to function
1017*c2e0c6b5SAndroid Build Coastguard Worker * GetProcessImageFileNameW() which does not need it.
1018*c2e0c6b5SAndroid Build Coastguard Worker */
1019*c2e0c6b5SAndroid Build Coastguard Worker process = open_process_for_query(processes[i], MyGetProcessImageFileNameW ? FALSE : TRUE);
1020*c2e0c6b5SAndroid Build Coastguard Worker if (!process)
1021*c2e0c6b5SAndroid Build Coastguard Worker continue;
1022*c2e0c6b5SAndroid Build Coastguard Worker
1023*c2e0c6b5SAndroid Build Coastguard Worker /*
1024*c2e0c6b5SAndroid Build Coastguard Worker * Set initial buffer size to 256 (wide) characters.
1025*c2e0c6b5SAndroid Build Coastguard Worker * Final path length on the modern NT-based systems can be also larger.
1026*c2e0c6b5SAndroid Build Coastguard Worker */
1027*c2e0c6b5SAndroid Build Coastguard Worker size = 256;
1028*c2e0c6b5SAndroid Build Coastguard Worker found_process = FALSE;
1029*c2e0c6b5SAndroid Build Coastguard Worker partial_retry = 0;
1030*c2e0c6b5SAndroid Build Coastguard Worker
1031*c2e0c6b5SAndroid Build Coastguard Worker retry_path:
1032*c2e0c6b5SAndroid Build Coastguard Worker path = (LPWSTR)LocalAlloc(LPTR, size * sizeof(*path));
1033*c2e0c6b5SAndroid Build Coastguard Worker if (!path)
1034*c2e0c6b5SAndroid Build Coastguard Worker goto end_path;
1035*c2e0c6b5SAndroid Build Coastguard Worker
1036*c2e0c6b5SAndroid Build Coastguard Worker if (MyGetProcessImageFileNameW)
1037*c2e0c6b5SAndroid Build Coastguard Worker length = MyGetProcessImageFileNameW(process, path, size);
1038*c2e0c6b5SAndroid Build Coastguard Worker else
1039*c2e0c6b5SAndroid Build Coastguard Worker length = MyGetModuleFileNameExW(process, NULL, path, size);
1040*c2e0c6b5SAndroid Build Coastguard Worker
1041*c2e0c6b5SAndroid Build Coastguard Worker error = GetLastError();
1042*c2e0c6b5SAndroid Build Coastguard Worker
1043*c2e0c6b5SAndroid Build Coastguard Worker /*
1044*c2e0c6b5SAndroid Build Coastguard Worker * GetModuleFileNameEx() returns zero and signal error ERROR_PARTIAL_COPY
1045*c2e0c6b5SAndroid Build Coastguard Worker * when remote process is in the middle of updating its module table.
1046*c2e0c6b5SAndroid Build Coastguard Worker * Sleep 10 ms and try again, max 10 attempts.
1047*c2e0c6b5SAndroid Build Coastguard Worker */
1048*c2e0c6b5SAndroid Build Coastguard Worker if (!MyGetProcessImageFileNameW)
1049*c2e0c6b5SAndroid Build Coastguard Worker {
1050*c2e0c6b5SAndroid Build Coastguard Worker if (length == 0 && error == ERROR_PARTIAL_COPY && partial_retry++ < 10)
1051*c2e0c6b5SAndroid Build Coastguard Worker {
1052*c2e0c6b5SAndroid Build Coastguard Worker Sleep(10);
1053*c2e0c6b5SAndroid Build Coastguard Worker goto retry_path;
1054*c2e0c6b5SAndroid Build Coastguard Worker }
1055*c2e0c6b5SAndroid Build Coastguard Worker partial_retry = 0;
1056*c2e0c6b5SAndroid Build Coastguard Worker }
1057*c2e0c6b5SAndroid Build Coastguard Worker
1058*c2e0c6b5SAndroid Build Coastguard Worker /*
1059*c2e0c6b5SAndroid Build Coastguard Worker * When buffer is too small then function GetModuleFileNameEx() returns
1060*c2e0c6b5SAndroid Build Coastguard Worker * its size argument on older systems (Windows XP) or its size minus
1061*c2e0c6b5SAndroid Build Coastguard Worker * argument one on new systems (Windows 10) without signalling any error.
1062*c2e0c6b5SAndroid Build Coastguard Worker * Function GetProcessImageFileNameW() on the other hand returns zero
1063*c2e0c6b5SAndroid Build Coastguard Worker * value and signals error ERROR_INSUFFICIENT_BUFFER. So in all these
1064*c2e0c6b5SAndroid Build Coastguard Worker * cases call function again with larger buffer.
1065*c2e0c6b5SAndroid Build Coastguard Worker */
1066*c2e0c6b5SAndroid Build Coastguard Worker
1067*c2e0c6b5SAndroid Build Coastguard Worker if (MyGetProcessImageFileNameW && length == 0 && error != ERROR_INSUFFICIENT_BUFFER)
1068*c2e0c6b5SAndroid Build Coastguard Worker goto end_path;
1069*c2e0c6b5SAndroid Build Coastguard Worker
1070*c2e0c6b5SAndroid Build Coastguard Worker if ((MyGetProcessImageFileNameW && length == 0) ||
1071*c2e0c6b5SAndroid Build Coastguard Worker (!MyGetProcessImageFileNameW && (length == size || length == size-1)))
1072*c2e0c6b5SAndroid Build Coastguard Worker {
1073*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(path);
1074*c2e0c6b5SAndroid Build Coastguard Worker size *= 2;
1075*c2e0c6b5SAndroid Build Coastguard Worker goto retry_path;
1076*c2e0c6b5SAndroid Build Coastguard Worker }
1077*c2e0c6b5SAndroid Build Coastguard Worker
1078*c2e0c6b5SAndroid Build Coastguard Worker if (length && check_process_name(path, length, exe_file))
1079*c2e0c6b5SAndroid Build Coastguard Worker found_process = TRUE;
1080*c2e0c6b5SAndroid Build Coastguard Worker
1081*c2e0c6b5SAndroid Build Coastguard Worker end_path:
1082*c2e0c6b5SAndroid Build Coastguard Worker if (path)
1083*c2e0c6b5SAndroid Build Coastguard Worker {
1084*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(path);
1085*c2e0c6b5SAndroid Build Coastguard Worker path = NULL;
1086*c2e0c6b5SAndroid Build Coastguard Worker }
1087*c2e0c6b5SAndroid Build Coastguard Worker
1088*c2e0c6b5SAndroid Build Coastguard Worker if (found_process)
1089*c2e0c6b5SAndroid Build Coastguard Worker break;
1090*c2e0c6b5SAndroid Build Coastguard Worker
1091*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(process);
1092*c2e0c6b5SAndroid Build Coastguard Worker process = NULL;
1093*c2e0c6b5SAndroid Build Coastguard Worker }
1094*c2e0c6b5SAndroid Build Coastguard Worker
1095*c2e0c6b5SAndroid Build Coastguard Worker LocalFree(processes);
1096*c2e0c6b5SAndroid Build Coastguard Worker
1097*c2e0c6b5SAndroid Build Coastguard Worker if (psapi)
1098*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(psapi);
1099*c2e0c6b5SAndroid Build Coastguard Worker
1100*c2e0c6b5SAndroid Build Coastguard Worker return process;
1101*c2e0c6b5SAndroid Build Coastguard Worker }
1102*c2e0c6b5SAndroid Build Coastguard Worker
1103*c2e0c6b5SAndroid Build Coastguard Worker /*
1104*c2e0c6b5SAndroid Build Coastguard Worker * Try to open primary access token of the particular process with specified
1105*c2e0c6b5SAndroid Build Coastguard Worker * rights. Before opening access token try to adjust DACL permissions of the
1106*c2e0c6b5SAndroid Build Coastguard Worker * primary process access token, so following open does not fail on error
1107*c2e0c6b5SAndroid Build Coastguard Worker * related to no open permissions. Revert DACL permissions after open attempt.
1108*c2e0c6b5SAndroid Build Coastguard Worker * As following steps are not atomic, try to execute them more times in case
1109*c2e0c6b5SAndroid Build Coastguard Worker * of possible race conditions caused by other threads or processes.
1110*c2e0c6b5SAndroid Build Coastguard Worker */
1111*c2e0c6b5SAndroid Build Coastguard Worker static HANDLE
try_grant_permissions_and_open_process_token(HANDLE process,DWORD rights)1112*c2e0c6b5SAndroid Build Coastguard Worker try_grant_permissions_and_open_process_token(HANDLE process, DWORD rights)
1113*c2e0c6b5SAndroid Build Coastguard Worker {
1114*c2e0c6b5SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR old_security_descriptor;
1115*c2e0c6b5SAndroid Build Coastguard Worker HANDLE grant_token;
1116*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
1117*c2e0c6b5SAndroid Build Coastguard Worker DWORD retry;
1118*c2e0c6b5SAndroid Build Coastguard Worker DWORD error;
1119*c2e0c6b5SAndroid Build Coastguard Worker
1120*c2e0c6b5SAndroid Build Coastguard Worker /*
1121*c2e0c6b5SAndroid Build Coastguard Worker * This code is not atomic. Between grant and open calls can other
1122*c2e0c6b5SAndroid Build Coastguard Worker * thread or process change or revert permissions. So try to execute
1123*c2e0c6b5SAndroid Build Coastguard Worker * it more times.
1124*c2e0c6b5SAndroid Build Coastguard Worker */
1125*c2e0c6b5SAndroid Build Coastguard Worker for (retry = 0; retry < 10; retry++)
1126*c2e0c6b5SAndroid Build Coastguard Worker {
1127*c2e0c6b5SAndroid Build Coastguard Worker if (!grant_process_token_dacl_permissions(process, rights, &grant_token, &old_security_descriptor))
1128*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
1129*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenProcessToken(process, rights, &token))
1130*c2e0c6b5SAndroid Build Coastguard Worker {
1131*c2e0c6b5SAndroid Build Coastguard Worker token = NULL;
1132*c2e0c6b5SAndroid Build Coastguard Worker error = GetLastError();
1133*c2e0c6b5SAndroid Build Coastguard Worker }
1134*c2e0c6b5SAndroid Build Coastguard Worker if (old_security_descriptor)
1135*c2e0c6b5SAndroid Build Coastguard Worker revert_token_dacl_permissions(grant_token, old_security_descriptor);
1136*c2e0c6b5SAndroid Build Coastguard Worker if (token)
1137*c2e0c6b5SAndroid Build Coastguard Worker return token;
1138*c2e0c6b5SAndroid Build Coastguard Worker else if (error != ERROR_ACCESS_DENIED)
1139*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
1140*c2e0c6b5SAndroid Build Coastguard Worker }
1141*c2e0c6b5SAndroid Build Coastguard Worker
1142*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
1143*c2e0c6b5SAndroid Build Coastguard Worker }
1144*c2e0c6b5SAndroid Build Coastguard Worker
1145*c2e0c6b5SAndroid Build Coastguard Worker /*
1146*c2e0c6b5SAndroid Build Coastguard Worker * Open primary access token of particular process handle with specified rights.
1147*c2e0c6b5SAndroid Build Coastguard Worker * If permissions for specified rights are missing then try to grant them.
1148*c2e0c6b5SAndroid Build Coastguard Worker */
1149*c2e0c6b5SAndroid Build Coastguard Worker HANDLE
win32_open_process_token_with_rights(HANDLE process,DWORD rights)1150*c2e0c6b5SAndroid Build Coastguard Worker win32_open_process_token_with_rights(HANDLE process, DWORD rights)
1151*c2e0c6b5SAndroid Build Coastguard Worker {
1152*c2e0c6b5SAndroid Build Coastguard Worker HANDLE old_token;
1153*c2e0c6b5SAndroid Build Coastguard Worker HANDLE token;
1154*c2e0c6b5SAndroid Build Coastguard Worker
1155*c2e0c6b5SAndroid Build Coastguard Worker /* First try to open primary access token of process handle directly. */
1156*c2e0c6b5SAndroid Build Coastguard Worker if (OpenProcessToken(process, rights, &token))
1157*c2e0c6b5SAndroid Build Coastguard Worker return token;
1158*c2e0c6b5SAndroid Build Coastguard Worker
1159*c2e0c6b5SAndroid Build Coastguard Worker /*
1160*c2e0c6b5SAndroid Build Coastguard Worker * If opening failed then it means that owner of the current thread
1161*c2e0c6b5SAndroid Build Coastguard Worker * access token does not have permission for it. Try it again with
1162*c2e0c6b5SAndroid Build Coastguard Worker * primary process access token.
1163*c2e0c6b5SAndroid Build Coastguard Worker */
1164*c2e0c6b5SAndroid Build Coastguard Worker if (change_token_to_primary(&old_token))
1165*c2e0c6b5SAndroid Build Coastguard Worker {
1166*c2e0c6b5SAndroid Build Coastguard Worker if (!OpenProcessToken(process, rights, &token))
1167*c2e0c6b5SAndroid Build Coastguard Worker token = NULL;
1168*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(old_token);
1169*c2e0c6b5SAndroid Build Coastguard Worker if (token)
1170*c2e0c6b5SAndroid Build Coastguard Worker return token;
1171*c2e0c6b5SAndroid Build Coastguard Worker }
1172*c2e0c6b5SAndroid Build Coastguard Worker
1173*c2e0c6b5SAndroid Build Coastguard Worker /*
1174*c2e0c6b5SAndroid Build Coastguard Worker * If opening is still failing then try to grant specified permissions
1175*c2e0c6b5SAndroid Build Coastguard Worker * for the current thread and try to open it again.
1176*c2e0c6b5SAndroid Build Coastguard Worker */
1177*c2e0c6b5SAndroid Build Coastguard Worker token = try_grant_permissions_and_open_process_token(process, rights);
1178*c2e0c6b5SAndroid Build Coastguard Worker if (token)
1179*c2e0c6b5SAndroid Build Coastguard Worker return token;
1180*c2e0c6b5SAndroid Build Coastguard Worker
1181*c2e0c6b5SAndroid Build Coastguard Worker /*
1182*c2e0c6b5SAndroid Build Coastguard Worker * And if it is still failing then try it again with granting
1183*c2e0c6b5SAndroid Build Coastguard Worker * permissions for the primary process token of the current process.
1184*c2e0c6b5SAndroid Build Coastguard Worker */
1185*c2e0c6b5SAndroid Build Coastguard Worker if (change_token_to_primary(&old_token))
1186*c2e0c6b5SAndroid Build Coastguard Worker {
1187*c2e0c6b5SAndroid Build Coastguard Worker token = try_grant_permissions_and_open_process_token(process, rights);
1188*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(old_token);
1189*c2e0c6b5SAndroid Build Coastguard Worker if (token)
1190*c2e0c6b5SAndroid Build Coastguard Worker return token;
1191*c2e0c6b5SAndroid Build Coastguard Worker }
1192*c2e0c6b5SAndroid Build Coastguard Worker
1193*c2e0c6b5SAndroid Build Coastguard Worker /*
1194*c2e0c6b5SAndroid Build Coastguard Worker * TODO: Sorry, no other option for now...
1195*c2e0c6b5SAndroid Build Coastguard Worker * It could be possible to use Take Ownership Name privilege to
1196*c2e0c6b5SAndroid Build Coastguard Worker * temporary change token owner of specified process to the owner of
1197*c2e0c6b5SAndroid Build Coastguard Worker * the current thread token, grant permissions for current thread in
1198*c2e0c6b5SAndroid Build Coastguard Worker * that process token, change ownership back to original one, open
1199*c2e0c6b5SAndroid Build Coastguard Worker * that process token and revert granted permissions. But this is
1200*c2e0c6b5SAndroid Build Coastguard Worker * not implemented yet.
1201*c2e0c6b5SAndroid Build Coastguard Worker */
1202*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
1203*c2e0c6b5SAndroid Build Coastguard Worker }
1204*c2e0c6b5SAndroid Build Coastguard Worker
1205*c2e0c6b5SAndroid Build Coastguard Worker /*
1206*c2e0c6b5SAndroid Build Coastguard Worker * Call supplied function with its argument and if it fails with
1207*c2e0c6b5SAndroid Build Coastguard Worker * ERROR_PRIVILEGE_NOT_HELD then try to enable Tcb privilege and
1208*c2e0c6b5SAndroid Build Coastguard Worker * call function with its argument again.
1209*c2e0c6b5SAndroid Build Coastguard Worker */
1210*c2e0c6b5SAndroid Build Coastguard Worker BOOL
win32_call_func_with_tcb_privilege(BOOL (* function)(LPVOID),LPVOID argument)1211*c2e0c6b5SAndroid Build Coastguard Worker win32_call_func_with_tcb_privilege(BOOL (*function)(LPVOID), LPVOID argument)
1212*c2e0c6b5SAndroid Build Coastguard Worker {
1213*c2e0c6b5SAndroid Build Coastguard Worker LUID luid_tcb_privilege;
1214*c2e0c6b5SAndroid Build Coastguard Worker LUID luid_impersonate_privilege;
1215*c2e0c6b5SAndroid Build Coastguard Worker
1216*c2e0c6b5SAndroid Build Coastguard Worker HANDLE revert_token_tcb_privilege;
1217*c2e0c6b5SAndroid Build Coastguard Worker BOOL revert_only_tcb_privilege;
1218*c2e0c6b5SAndroid Build Coastguard Worker
1219*c2e0c6b5SAndroid Build Coastguard Worker HANDLE revert_token_impersonate_privilege;
1220*c2e0c6b5SAndroid Build Coastguard Worker BOOL revert_only_impersonate_privilege;
1221*c2e0c6b5SAndroid Build Coastguard Worker
1222*c2e0c6b5SAndroid Build Coastguard Worker BOOL impersonate_privilege_enabled;
1223*c2e0c6b5SAndroid Build Coastguard Worker
1224*c2e0c6b5SAndroid Build Coastguard Worker BOOL revert_to_old_token;
1225*c2e0c6b5SAndroid Build Coastguard Worker HANDLE old_token;
1226*c2e0c6b5SAndroid Build Coastguard Worker
1227*c2e0c6b5SAndroid Build Coastguard Worker HANDLE lsass_process;
1228*c2e0c6b5SAndroid Build Coastguard Worker HANDLE lsass_token;
1229*c2e0c6b5SAndroid Build Coastguard Worker
1230*c2e0c6b5SAndroid Build Coastguard Worker DWORD error;
1231*c2e0c6b5SAndroid Build Coastguard Worker BOOL ret;
1232*c2e0c6b5SAndroid Build Coastguard Worker
1233*c2e0c6b5SAndroid Build Coastguard Worker impersonate_privilege_enabled = FALSE;
1234*c2e0c6b5SAndroid Build Coastguard Worker revert_to_old_token = FALSE;
1235*c2e0c6b5SAndroid Build Coastguard Worker lsass_token = NULL;
1236*c2e0c6b5SAndroid Build Coastguard Worker old_token = NULL;
1237*c2e0c6b5SAndroid Build Coastguard Worker
1238*c2e0c6b5SAndroid Build Coastguard Worker /* Call supplied function. */
1239*c2e0c6b5SAndroid Build Coastguard Worker ret = function(argument);
1240*c2e0c6b5SAndroid Build Coastguard Worker if (ret || GetLastError() != ERROR_PRIVILEGE_NOT_HELD)
1241*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1242*c2e0c6b5SAndroid Build Coastguard Worker
1243*c2e0c6b5SAndroid Build Coastguard Worker /*
1244*c2e0c6b5SAndroid Build Coastguard Worker * If function call failed with ERROR_PRIVILEGE_NOT_HELD
1245*c2e0c6b5SAndroid Build Coastguard Worker * error then it means that the current thread token does not have
1246*c2e0c6b5SAndroid Build Coastguard Worker * Tcb privilege enabled. Try to enable it.
1247*c2e0c6b5SAndroid Build Coastguard Worker */
1248*c2e0c6b5SAndroid Build Coastguard Worker
1249*c2e0c6b5SAndroid Build Coastguard Worker if (!LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid_tcb_privilege))
1250*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1251*c2e0c6b5SAndroid Build Coastguard Worker
1252*c2e0c6b5SAndroid Build Coastguard Worker /*
1253*c2e0c6b5SAndroid Build Coastguard Worker * If the current thread has already Tcb privilege enabled then there
1254*c2e0c6b5SAndroid Build Coastguard Worker * is some additional unhanded restriction.
1255*c2e0c6b5SAndroid Build Coastguard Worker */
1256*c2e0c6b5SAndroid Build Coastguard Worker if (win32_have_privilege(luid_tcb_privilege))
1257*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1258*c2e0c6b5SAndroid Build Coastguard Worker
1259*c2e0c6b5SAndroid Build Coastguard Worker /* Try to enable Tcb privilege and try function call again. */
1260*c2e0c6b5SAndroid Build Coastguard Worker if (win32_enable_privilege(luid_tcb_privilege, &revert_token_tcb_privilege, &revert_only_tcb_privilege))
1261*c2e0c6b5SAndroid Build Coastguard Worker {
1262*c2e0c6b5SAndroid Build Coastguard Worker ret = function(argument);
1263*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_privilege(luid_tcb_privilege, revert_token_tcb_privilege, revert_only_tcb_privilege);
1264*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1265*c2e0c6b5SAndroid Build Coastguard Worker }
1266*c2e0c6b5SAndroid Build Coastguard Worker
1267*c2e0c6b5SAndroid Build Coastguard Worker /*
1268*c2e0c6b5SAndroid Build Coastguard Worker * If enabling of Tcb privilege failed then it means that current thread
1269*c2e0c6b5SAndroid Build Coastguard Worker * does not have this privilege. But current process may have it. So try it
1270*c2e0c6b5SAndroid Build Coastguard Worker * again with primary process access token.
1271*c2e0c6b5SAndroid Build Coastguard Worker */
1272*c2e0c6b5SAndroid Build Coastguard Worker
1273*c2e0c6b5SAndroid Build Coastguard Worker /*
1274*c2e0c6b5SAndroid Build Coastguard Worker * If system supports Impersonate privilege (Windows 2000 SP4 or higher) then
1275*c2e0c6b5SAndroid Build Coastguard Worker * all future actions in this function require this Impersonate privilege.
1276*c2e0c6b5SAndroid Build Coastguard Worker * So try to enable it in case it is currently disabled.
1277*c2e0c6b5SAndroid Build Coastguard Worker */
1278*c2e0c6b5SAndroid Build Coastguard Worker if (LookupPrivilegeValue(NULL, SE_IMPERSONATE_NAME, &luid_impersonate_privilege) &&
1279*c2e0c6b5SAndroid Build Coastguard Worker !win32_have_privilege(luid_impersonate_privilege))
1280*c2e0c6b5SAndroid Build Coastguard Worker {
1281*c2e0c6b5SAndroid Build Coastguard Worker /*
1282*c2e0c6b5SAndroid Build Coastguard Worker * If current thread does not have Impersonate privilege enabled
1283*c2e0c6b5SAndroid Build Coastguard Worker * then first try to enable it just for the current thread. If
1284*c2e0c6b5SAndroid Build Coastguard Worker * it is not possible to enable it just for the current thread
1285*c2e0c6b5SAndroid Build Coastguard Worker * then try it to enable globally for whole process (which
1286*c2e0c6b5SAndroid Build Coastguard Worker * affects all process threads). Both actions will be reverted
1287*c2e0c6b5SAndroid Build Coastguard Worker * at the end of this function.
1288*c2e0c6b5SAndroid Build Coastguard Worker */
1289*c2e0c6b5SAndroid Build Coastguard Worker if (win32_enable_privilege(luid_impersonate_privilege, &revert_token_impersonate_privilege, &revert_only_impersonate_privilege))
1290*c2e0c6b5SAndroid Build Coastguard Worker {
1291*c2e0c6b5SAndroid Build Coastguard Worker impersonate_privilege_enabled = TRUE;
1292*c2e0c6b5SAndroid Build Coastguard Worker }
1293*c2e0c6b5SAndroid Build Coastguard Worker else if (win32_enable_privilege(luid_impersonate_privilege, NULL, NULL))
1294*c2e0c6b5SAndroid Build Coastguard Worker {
1295*c2e0c6b5SAndroid Build Coastguard Worker impersonate_privilege_enabled = TRUE;
1296*c2e0c6b5SAndroid Build Coastguard Worker revert_token_impersonate_privilege = NULL;
1297*c2e0c6b5SAndroid Build Coastguard Worker revert_only_impersonate_privilege = TRUE;
1298*c2e0c6b5SAndroid Build Coastguard Worker }
1299*c2e0c6b5SAndroid Build Coastguard Worker else
1300*c2e0c6b5SAndroid Build Coastguard Worker {
1301*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1302*c2e0c6b5SAndroid Build Coastguard Worker }
1303*c2e0c6b5SAndroid Build Coastguard Worker
1304*c2e0c6b5SAndroid Build Coastguard Worker /*
1305*c2e0c6b5SAndroid Build Coastguard Worker * Now when Impersonate privilege is enabled, try to enable Tcb
1306*c2e0c6b5SAndroid Build Coastguard Worker * privilege again. Enabling other privileges for the current
1307*c2e0c6b5SAndroid Build Coastguard Worker * thread requires Impersonate privilege, so enabling Tcb again
1308*c2e0c6b5SAndroid Build Coastguard Worker * could now pass.
1309*c2e0c6b5SAndroid Build Coastguard Worker */
1310*c2e0c6b5SAndroid Build Coastguard Worker if (win32_enable_privilege(luid_tcb_privilege, &revert_token_tcb_privilege, &revert_only_tcb_privilege))
1311*c2e0c6b5SAndroid Build Coastguard Worker {
1312*c2e0c6b5SAndroid Build Coastguard Worker ret = function(argument);
1313*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_privilege(luid_tcb_privilege, revert_token_tcb_privilege, revert_only_tcb_privilege);
1314*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1315*c2e0c6b5SAndroid Build Coastguard Worker }
1316*c2e0c6b5SAndroid Build Coastguard Worker }
1317*c2e0c6b5SAndroid Build Coastguard Worker
1318*c2e0c6b5SAndroid Build Coastguard Worker /*
1319*c2e0c6b5SAndroid Build Coastguard Worker * If enabling Tcb privilege failed then it means that the current
1320*c2e0c6b5SAndroid Build Coastguard Worker * thread access token does not have this privilege or does not
1321*c2e0c6b5SAndroid Build Coastguard Worker * have permission to adjust privileges.
1322*c2e0c6b5SAndroid Build Coastguard Worker *
1323*c2e0c6b5SAndroid Build Coastguard Worker * Try to use more privileged token from Local Security Authority
1324*c2e0c6b5SAndroid Build Coastguard Worker * Subsystem Service process (lsass.exe) which has Tcb privilege.
1325*c2e0c6b5SAndroid Build Coastguard Worker * Retrieving this more privileged token is possible for local
1326*c2e0c6b5SAndroid Build Coastguard Worker * administrators (unless it was disabled by local administrators).
1327*c2e0c6b5SAndroid Build Coastguard Worker */
1328*c2e0c6b5SAndroid Build Coastguard Worker
1329*c2e0c6b5SAndroid Build Coastguard Worker lsass_process = win32_find_and_open_process_for_query("lsass.exe");
1330*c2e0c6b5SAndroid Build Coastguard Worker if (!lsass_process)
1331*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1332*c2e0c6b5SAndroid Build Coastguard Worker
1333*c2e0c6b5SAndroid Build Coastguard Worker /*
1334*c2e0c6b5SAndroid Build Coastguard Worker * Open primary lsass.exe process access token with query and duplicate
1335*c2e0c6b5SAndroid Build Coastguard Worker * rights. Just these two rights are required for impersonating other
1336*c2e0c6b5SAndroid Build Coastguard Worker * primary process token (impersonate right is really not required!).
1337*c2e0c6b5SAndroid Build Coastguard Worker */
1338*c2e0c6b5SAndroid Build Coastguard Worker lsass_token = win32_open_process_token_with_rights(lsass_process, TOKEN_QUERY | TOKEN_DUPLICATE);
1339*c2e0c6b5SAndroid Build Coastguard Worker
1340*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(lsass_process);
1341*c2e0c6b5SAndroid Build Coastguard Worker
1342*c2e0c6b5SAndroid Build Coastguard Worker if (!lsass_token)
1343*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1344*c2e0c6b5SAndroid Build Coastguard Worker
1345*c2e0c6b5SAndroid Build Coastguard Worker /*
1346*c2e0c6b5SAndroid Build Coastguard Worker * After successful open of the primary lsass.exe process access token,
1347*c2e0c6b5SAndroid Build Coastguard Worker * assign its copy for the current thread.
1348*c2e0c6b5SAndroid Build Coastguard Worker */
1349*c2e0c6b5SAndroid Build Coastguard Worker if (!win32_change_token(lsass_token, &old_token))
1350*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1351*c2e0c6b5SAndroid Build Coastguard Worker
1352*c2e0c6b5SAndroid Build Coastguard Worker revert_to_old_token = TRUE;
1353*c2e0c6b5SAndroid Build Coastguard Worker
1354*c2e0c6b5SAndroid Build Coastguard Worker ret = function(argument);
1355*c2e0c6b5SAndroid Build Coastguard Worker if (ret || GetLastError() != ERROR_PRIVILEGE_NOT_HELD)
1356*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1357*c2e0c6b5SAndroid Build Coastguard Worker
1358*c2e0c6b5SAndroid Build Coastguard Worker /*
1359*c2e0c6b5SAndroid Build Coastguard Worker * Now current thread is not using primary process token anymore
1360*c2e0c6b5SAndroid Build Coastguard Worker * but is using custom access token. There is no need to revert
1361*c2e0c6b5SAndroid Build Coastguard Worker * enabled Tcb privilege as the whole custom access token would
1362*c2e0c6b5SAndroid Build Coastguard Worker * be reverted. So there is no need to setup revert method for
1363*c2e0c6b5SAndroid Build Coastguard Worker * enabling privilege.
1364*c2e0c6b5SAndroid Build Coastguard Worker */
1365*c2e0c6b5SAndroid Build Coastguard Worker if (win32_have_privilege(luid_tcb_privilege) ||
1366*c2e0c6b5SAndroid Build Coastguard Worker !win32_enable_privilege(luid_tcb_privilege, NULL, NULL))
1367*c2e0c6b5SAndroid Build Coastguard Worker goto err_privilege_not_held;
1368*c2e0c6b5SAndroid Build Coastguard Worker
1369*c2e0c6b5SAndroid Build Coastguard Worker ret = function(argument);
1370*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1371*c2e0c6b5SAndroid Build Coastguard Worker
1372*c2e0c6b5SAndroid Build Coastguard Worker err_privilege_not_held:
1373*c2e0c6b5SAndroid Build Coastguard Worker SetLastError(ERROR_PRIVILEGE_NOT_HELD);
1374*c2e0c6b5SAndroid Build Coastguard Worker ret = FALSE;
1375*c2e0c6b5SAndroid Build Coastguard Worker goto ret;
1376*c2e0c6b5SAndroid Build Coastguard Worker
1377*c2e0c6b5SAndroid Build Coastguard Worker ret:
1378*c2e0c6b5SAndroid Build Coastguard Worker error = GetLastError();
1379*c2e0c6b5SAndroid Build Coastguard Worker
1380*c2e0c6b5SAndroid Build Coastguard Worker if (revert_to_old_token)
1381*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_to_token(old_token);
1382*c2e0c6b5SAndroid Build Coastguard Worker
1383*c2e0c6b5SAndroid Build Coastguard Worker if (impersonate_privilege_enabled)
1384*c2e0c6b5SAndroid Build Coastguard Worker win32_revert_privilege(luid_impersonate_privilege, revert_token_impersonate_privilege, revert_only_impersonate_privilege);
1385*c2e0c6b5SAndroid Build Coastguard Worker
1386*c2e0c6b5SAndroid Build Coastguard Worker if (lsass_token)
1387*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(lsass_token);
1388*c2e0c6b5SAndroid Build Coastguard Worker
1389*c2e0c6b5SAndroid Build Coastguard Worker SetLastError(error);
1390*c2e0c6b5SAndroid Build Coastguard Worker
1391*c2e0c6b5SAndroid Build Coastguard Worker return ret;
1392*c2e0c6b5SAndroid Build Coastguard Worker }
1393