LibreOffice Module onlineupdate (master) 1
uachelper.cxx
Go to the documentation of this file.
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#ifdef _WIN32
6#include <windows.h>
7#include <wtsapi32.h>
8#include "uachelper.h"
9#include "updatelogging.h"
10
11// See the MSDN documentation with title: Privilege Constants
12// At the time of this writing, this documentation is located at:
13// http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx
15{
16 SE_ASSIGNPRIMARYTOKEN_NAME,
17 SE_AUDIT_NAME,
18 SE_BACKUP_NAME,
19 // CreateProcess will succeed but the app will fail to launch on some WinXP
20 // machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens
21 // for limited user accounts on those machines. The define is kept here as a
22 // reminder that it should never be re-added.
23 // This permission is for directory watching but also from MSDN: "This
24 // privilege also causes the system to skip all traversal access checks."
25 // SE_CHANGE_NOTIFY_NAME,
26 SE_CREATE_GLOBAL_NAME,
27 SE_CREATE_PAGEFILE_NAME,
28 SE_CREATE_PERMANENT_NAME,
29 SE_CREATE_SYMBOLIC_LINK_NAME,
30 SE_CREATE_TOKEN_NAME,
31 SE_DEBUG_NAME,
32 SE_ENABLE_DELEGATION_NAME,
33 SE_IMPERSONATE_NAME,
34 SE_INC_BASE_PRIORITY_NAME,
35 SE_INCREASE_QUOTA_NAME,
36 SE_INC_WORKING_SET_NAME,
37 SE_LOAD_DRIVER_NAME,
38 SE_LOCK_MEMORY_NAME,
39 SE_MACHINE_ACCOUNT_NAME,
40 SE_MANAGE_VOLUME_NAME,
41 SE_PROF_SINGLE_PROCESS_NAME,
42 SE_RELABEL_NAME,
43 SE_REMOTE_SHUTDOWN_NAME,
44 SE_RESTORE_NAME,
45 SE_SECURITY_NAME,
46 SE_SHUTDOWN_NAME,
47 SE_SYNC_AGENT_NAME,
48 SE_SYSTEM_ENVIRONMENT_NAME,
49 SE_SYSTEM_PROFILE_NAME,
50 SE_SYSTEMTIME_NAME,
51 SE_TAKE_OWNERSHIP_NAME,
52 SE_TCB_NAME,
53 SE_TIME_ZONE_NAME,
54 SE_TRUSTED_CREDMAN_ACCESS_NAME,
55 SE_UNDOCK_NAME,
56 SE_UNSOLICITED_INPUT_NAME
57};
58
66HANDLE
67UACHelper::OpenUserToken(DWORD sessionID)
68{
69 HMODULE module = LoadLibraryW(L"wtsapi32.dll");
70 HANDLE token = nullptr;
71 decltype(WTSQueryUserToken)* wtsQueryUserToken =
72 (decltype(WTSQueryUserToken)*) GetProcAddress(module, "WTSQueryUserToken");
73 if (wtsQueryUserToken)
74 {
75 wtsQueryUserToken(sessionID, &token);
76 }
77 FreeLibrary(module);
78 return token;
79}
80
88HANDLE
90{
91 // Magic below...
92 // UAC creates 2 tokens. One is the restricted token which we have.
93 // the other is the UAC elevated one. Since we are running as a service
94 // as the system account we have access to both.
95 TOKEN_LINKED_TOKEN tlt;
96 HANDLE hNewLinkedToken = nullptr;
97 DWORD len;
98 if (GetTokenInformation(token, (TOKEN_INFORMATION_CLASS)TokenLinkedToken,
99 &tlt, sizeof(TOKEN_LINKED_TOKEN), &len))
100 {
101 token = tlt.LinkedToken;
102 hNewLinkedToken = token;
103 }
104 return hNewLinkedToken;
105}
106
107
116BOOL
117UACHelper::SetPrivilege(HANDLE token, LPCTSTR priv, BOOL enable)
118{
119 LUID luidOfPriv;
120 if (!LookupPrivilegeValue(nullptr, priv, &luidOfPriv))
121 {
122 return FALSE;
123 }
124
125 TOKEN_PRIVILEGES tokenPriv;
126 tokenPriv.PrivilegeCount = 1;
127 tokenPriv.Privileges[0].Luid = luidOfPriv;
128 tokenPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
129
130 SetLastError(ERROR_SUCCESS);
131 if (!AdjustTokenPrivileges(token, false, &tokenPriv,
132 sizeof(tokenPriv), nullptr, nullptr))
133 {
134 return FALSE;
135 }
136
137 return GetLastError() == ERROR_SUCCESS;
138}
139
150BOOL
152 LPCTSTR *unneededPrivs,
153 size_t count)
154{
155 HANDLE obtainedToken = nullptr;
156 if (!token)
157 {
158 // Note: This handle is a pseudo-handle and need not be closed
159 HANDLE process = GetCurrentProcess();
160 if (!OpenProcessToken(process, TOKEN_ALL_ACCESS_P, &obtainedToken))
161 {
162 LOG_WARN(("Could not obtain token for current process, no "
163 "privileges changed. (%d)", GetLastError()));
164 return FALSE;
165 }
166 token = obtainedToken;
167 }
168
169 BOOL result = TRUE;
170 for (size_t i = 0; i < count; i++)
171 {
172 if (SetPrivilege(token, unneededPrivs[i], FALSE))
173 {
174 LOG(("Disabled unneeded token privilege: %s.",
175 unneededPrivs[i]));
176 }
177 else
178 {
179 LOG(("Could not disable token privilege value: %s. (%d)",
180 unneededPrivs[i], GetLastError()));
181 result = FALSE;
182 }
183 }
184
185 if (obtainedToken)
186 {
187 CloseHandle(obtainedToken);
188 }
189 return result;
190}
191
202BOOL
204{
205 static const size_t PrivsToDisableSize =
207
209 PrivsToDisableSize);
210}
211
218bool
220{
221 HANDLE token;
222 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
223 {
224 return false;
225 }
226
227 TOKEN_ELEVATION_TYPE elevationType;
228 DWORD len;
229 bool canElevate = GetTokenInformation(token, TokenElevationType,
230 &elevationType,
231 sizeof(elevationType), &len) &&
232 (elevationType == TokenElevationTypeLimited);
233 CloseHandle(token);
234
235 return canElevate;
236}
237#endif
static BOOL DisableUnneededPrivileges(HANDLE token, LPCTSTR *unneededPrivs, size_t count)
static LPCTSTR PrivsToDisable[]
Definition: uachelper.h:20
static HANDLE OpenLinkedToken(HANDLE token)
static bool CanUserElevate()
static HANDLE OpenUserToken(DWORD sessionID)
static BOOL SetPrivilege(HANDLE token, LPCTSTR privs, BOOL enable)
static BOOL DisablePrivileges(HANDLE token)
#define TRUE
#define FALSE
int i
module
const wchar_t *typedef BOOL
Any result
#define LOG_WARN(args)
Definition: updatelogging.h:38
#define LOG(args)
Definition: updatelogging.h:39