Added GetState, GetManagedProperties, CreateNetwork methods to WiFiService.
[chromium-blink-merge.git] / sandbox / win / src / restricted_token.cc
blob6948d8ada4027c7e523bcd68a311f0601b880bca
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/win/src/restricted_token.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "sandbox/win/src/acl.h"
11 #include "sandbox/win/src/win_utils.h"
14 namespace sandbox {
16 unsigned RestrictedToken::Init(const HANDLE effective_token) {
17 DCHECK(!init_);
18 if (init_)
19 return ERROR_ALREADY_INITIALIZED;
21 if (effective_token) {
22 // We duplicate the handle to be able to use it even if the original handle
23 // is closed.
24 HANDLE effective_token_dup;
25 if (::DuplicateHandle(::GetCurrentProcess(),
26 effective_token,
27 ::GetCurrentProcess(),
28 &effective_token_dup,
30 FALSE,
31 DUPLICATE_SAME_ACCESS)) {
32 effective_token_ = effective_token_dup;
33 } else {
34 return ::GetLastError();
36 } else {
37 if (!::OpenProcessToken(::GetCurrentProcess(),
38 TOKEN_ALL_ACCESS,
39 &effective_token_))
40 return ::GetLastError();
43 init_ = true;
44 return ERROR_SUCCESS;
47 unsigned RestrictedToken::GetRestrictedTokenHandle(HANDLE *token_handle) const {
48 DCHECK(init_);
49 if (!init_)
50 return ERROR_NO_TOKEN;
52 size_t deny_size = sids_for_deny_only_.size();
53 size_t restrict_size = sids_to_restrict_.size();
54 size_t privileges_size = privileges_to_disable_.size();
56 SID_AND_ATTRIBUTES *deny_only_array = NULL;
57 if (deny_size) {
58 deny_only_array = new SID_AND_ATTRIBUTES[deny_size];
60 for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
61 deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
62 deny_only_array[i].Sid =
63 const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
67 SID_AND_ATTRIBUTES *sids_to_restrict_array = NULL;
68 if (restrict_size) {
69 sids_to_restrict_array = new SID_AND_ATTRIBUTES[restrict_size];
71 for (unsigned int i = 0; i < restrict_size; ++i) {
72 sids_to_restrict_array[i].Attributes = 0;
73 sids_to_restrict_array[i].Sid =
74 const_cast<SID*>(sids_to_restrict_[i].GetPSID());
78 LUID_AND_ATTRIBUTES *privileges_to_disable_array = NULL;
79 if (privileges_size) {
80 privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size];
82 for (unsigned int i = 0; i < privileges_size; ++i) {
83 privileges_to_disable_array[i].Attributes = 0;
84 privileges_to_disable_array[i].Luid = privileges_to_disable_[i];
88 BOOL result = TRUE;
89 HANDLE new_token = NULL;
90 // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell
91 // if a token has ben restricted given the limiations of IsTokenRestricted()
92 // but it appears that in Windows 7 it hints the AppLocker subsystem to
93 // leave us alone.
94 if (deny_size || restrict_size || privileges_size) {
95 result = ::CreateRestrictedToken(effective_token_,
96 SANDBOX_INERT,
97 static_cast<DWORD>(deny_size),
98 deny_only_array,
99 static_cast<DWORD>(privileges_size),
100 privileges_to_disable_array,
101 static_cast<DWORD>(restrict_size),
102 sids_to_restrict_array,
103 &new_token);
104 } else {
105 // Duplicate the token even if it's not modified at this point
106 // because any subsequent changes to this token would also affect the
107 // current process.
108 result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL,
109 SecurityIdentification, TokenPrimary,
110 &new_token);
113 if (deny_only_array)
114 delete[] deny_only_array;
116 if (sids_to_restrict_array)
117 delete[] sids_to_restrict_array;
119 if (privileges_to_disable_array)
120 delete[] privileges_to_disable_array;
122 if (!result)
123 return ::GetLastError();
125 // Modify the default dacl on the token to contain Restricted and the user.
126 if (!AddSidToDefaultDacl(new_token, WinRestrictedCodeSid, GENERIC_ALL))
127 return ::GetLastError();
129 if (!AddUserSidToDefaultDacl(new_token, GENERIC_ALL))
130 return ::GetLastError();
132 DWORD error = SetTokenIntegrityLevel(new_token, integrity_level_);
133 if (ERROR_SUCCESS != error)
134 return error;
136 BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
137 new_token,
138 ::GetCurrentProcess(),
139 token_handle,
140 TOKEN_ALL_ACCESS,
141 FALSE, // Don't inherit.
144 if (new_token != effective_token_)
145 ::CloseHandle(new_token);
147 if (!status)
148 return ::GetLastError();
150 return ERROR_SUCCESS;
153 unsigned RestrictedToken::GetRestrictedTokenHandleForImpersonation(
154 HANDLE *token_handle) const {
155 DCHECK(init_);
156 if (!init_)
157 return ERROR_NO_TOKEN;
159 HANDLE restricted_token_handle;
160 unsigned err_code = GetRestrictedTokenHandle(&restricted_token_handle);
161 if (ERROR_SUCCESS != err_code)
162 return err_code;
164 HANDLE impersonation_token;
165 if (!::DuplicateToken(restricted_token_handle,
166 SecurityImpersonation,
167 &impersonation_token)) {
168 ::CloseHandle(restricted_token_handle);
169 return ::GetLastError();
172 ::CloseHandle(restricted_token_handle);
174 BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
175 impersonation_token,
176 ::GetCurrentProcess(),
177 token_handle,
178 TOKEN_ALL_ACCESS,
179 FALSE, // Don't inherit.
182 ::CloseHandle(impersonation_token);
184 if (!status)
185 return ::GetLastError();
187 return ERROR_SUCCESS;
190 unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) {
191 DCHECK(init_);
192 if (!init_)
193 return ERROR_NO_TOKEN;
195 TOKEN_GROUPS *token_groups = NULL;
196 DWORD size = 0;
198 BOOL result = ::GetTokenInformation(effective_token_,
199 TokenGroups,
200 NULL, // No buffer.
201 0, // Size is 0.
202 &size);
203 if (!size)
204 return ::GetLastError();
206 token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
207 result = ::GetTokenInformation(effective_token_,
208 TokenGroups,
209 token_groups,
210 size,
211 &size);
212 if (!result) {
213 delete[] reinterpret_cast<BYTE*>(token_groups);
214 return ::GetLastError();
217 // Build the list of the deny only group SIDs
218 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
219 if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
220 (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
221 bool should_ignore = false;
222 if (exceptions) {
223 for (unsigned int j = 0; j < exceptions->size(); ++j) {
224 if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
225 token_groups->Groups[i].Sid)) {
226 should_ignore = true;
227 break;
231 if (!should_ignore) {
232 sids_for_deny_only_.push_back(
233 reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
238 delete[] reinterpret_cast<BYTE*>(token_groups);
240 return ERROR_SUCCESS;
243 unsigned RestrictedToken::AddSidForDenyOnly(const Sid &sid) {
244 DCHECK(init_);
245 if (!init_)
246 return ERROR_NO_TOKEN;
248 sids_for_deny_only_.push_back(sid);
249 return ERROR_SUCCESS;
252 unsigned RestrictedToken::AddUserSidForDenyOnly() {
253 DCHECK(init_);
254 if (!init_)
255 return ERROR_NO_TOKEN;
257 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
258 TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);
260 BOOL result = ::GetTokenInformation(effective_token_,
261 TokenUser,
262 token_user,
263 size,
264 &size);
266 if (!result) {
267 delete[] reinterpret_cast<BYTE*>(token_user);
268 return ::GetLastError();
271 Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
272 sids_for_deny_only_.push_back(user);
274 delete[] reinterpret_cast<BYTE*>(token_user);
276 return ERROR_SUCCESS;
279 unsigned RestrictedToken::DeleteAllPrivileges(
280 const std::vector<std::wstring> *exceptions) {
281 DCHECK(init_);
282 if (!init_)
283 return ERROR_NO_TOKEN;
285 // Get the list of privileges in the token
286 TOKEN_PRIVILEGES *token_privileges = NULL;
287 DWORD size = 0;
289 BOOL result = ::GetTokenInformation(effective_token_,
290 TokenPrivileges,
291 NULL, // No buffer.
292 0, // Size is 0.
293 &size);
294 if (!size)
295 return ::GetLastError();
297 token_privileges = reinterpret_cast<TOKEN_PRIVILEGES*>(new BYTE[size]);
298 result = ::GetTokenInformation(effective_token_,
299 TokenPrivileges,
300 token_privileges,
301 size,
302 &size);
303 if (!result) {
304 delete[] reinterpret_cast<BYTE *>(token_privileges);
305 return ::GetLastError();
309 // Build the list of privileges to disable
310 for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
311 bool should_ignore = false;
312 if (exceptions) {
313 for (unsigned int j = 0; j < exceptions->size(); ++j) {
314 LUID luid = {0};
315 ::LookupPrivilegeValue(NULL, (*exceptions)[j].c_str(), &luid);
316 if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
317 token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
318 should_ignore = true;
319 break;
323 if (!should_ignore) {
324 privileges_to_disable_.push_back(token_privileges->Privileges[i].Luid);
328 delete[] reinterpret_cast<BYTE *>(token_privileges);
330 return ERROR_SUCCESS;
333 unsigned RestrictedToken::DeletePrivilege(const wchar_t *privilege) {
334 DCHECK(init_);
335 if (!init_)
336 return ERROR_NO_TOKEN;
338 LUID luid = {0};
339 if (LookupPrivilegeValue(NULL, privilege, &luid))
340 privileges_to_disable_.push_back(luid);
341 else
342 return ::GetLastError();
344 return ERROR_SUCCESS;
347 unsigned RestrictedToken::AddRestrictingSid(const Sid &sid) {
348 DCHECK(init_);
349 if (!init_)
350 return ERROR_NO_TOKEN;
352 sids_to_restrict_.push_back(sid); // No attributes
353 return ERROR_SUCCESS;
356 unsigned RestrictedToken::AddRestrictingSidLogonSession() {
357 DCHECK(init_);
358 if (!init_)
359 return ERROR_NO_TOKEN;
361 TOKEN_GROUPS *token_groups = NULL;
362 DWORD size = 0;
364 BOOL result = ::GetTokenInformation(effective_token_,
365 TokenGroups,
366 NULL, // No buffer.
367 0, // Size is 0.
368 &size);
369 if (!size)
370 return ::GetLastError();
372 token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
373 result = ::GetTokenInformation(effective_token_,
374 TokenGroups,
375 token_groups,
376 size,
377 &size);
378 if (!result) {
379 delete[] reinterpret_cast<BYTE*>(token_groups);
380 return ::GetLastError();
383 SID *logon_sid = NULL;
384 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
385 if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
386 logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid);
387 break;
391 if (logon_sid)
392 sids_to_restrict_.push_back(logon_sid);
394 delete[] reinterpret_cast<BYTE*>(token_groups);
396 return ERROR_SUCCESS;
399 unsigned RestrictedToken::AddRestrictingSidCurrentUser() {
400 DCHECK(init_);
401 if (!init_)
402 return ERROR_NO_TOKEN;
404 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
405 TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);
407 BOOL result = ::GetTokenInformation(effective_token_,
408 TokenUser,
409 token_user,
410 size,
411 &size);
413 if (!result) {
414 delete[] reinterpret_cast<BYTE*>(token_user);
415 return ::GetLastError();
418 Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
419 sids_to_restrict_.push_back(user);
421 delete[] reinterpret_cast<BYTE*>(token_user);
423 return ERROR_SUCCESS;
426 unsigned RestrictedToken::AddRestrictingSidAllSids() {
427 DCHECK(init_);
428 if (!init_)
429 return ERROR_NO_TOKEN;
431 // Add the current user to the list.
432 unsigned error = AddRestrictingSidCurrentUser();
433 if (ERROR_SUCCESS != error)
434 return error;
436 TOKEN_GROUPS *token_groups = NULL;
437 DWORD size = 0;
439 // Get the buffer size required.
440 BOOL result = ::GetTokenInformation(effective_token_, TokenGroups, NULL, 0,
441 &size);
442 if (!size)
443 return ::GetLastError();
445 token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
446 result = ::GetTokenInformation(effective_token_,
447 TokenGroups,
448 token_groups,
449 size,
450 &size);
451 if (!result) {
452 delete[] reinterpret_cast<BYTE*>(token_groups);
453 return ::GetLastError();
456 // Build the list of restricting sids from all groups.
457 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
458 if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0)
459 AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
462 delete[] reinterpret_cast<BYTE*>(token_groups);
464 return ERROR_SUCCESS;
467 unsigned RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) {
468 integrity_level_ = integrity_level;
469 return ERROR_SUCCESS;
472 } // namespace sandbox