Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: sandbox/win/src/restricted_token.cc

Issue 1851213002: Remove sandbox on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nacl compile issues Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/win/src/restricted_token.h ('k') | sandbox/win/src/restricted_token_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "sandbox/win/src/restricted_token.h"
6
7 #include <stddef.h>
8
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "sandbox/win/src/acl.h"
14 #include "sandbox/win/src/win_utils.h"
15
16 namespace {
17
18 // Calls GetTokenInformation with the desired |info_class| and returns a buffer
19 // with the result.
20 scoped_ptr<BYTE[]> GetTokenInfo(const base::win::ScopedHandle& token,
21 TOKEN_INFORMATION_CLASS info_class,
22 DWORD* error) {
23 // Get the required buffer size.
24 DWORD size = 0;
25 ::GetTokenInformation(token.Get(), info_class, NULL, 0, &size);
26 if (!size) {
27 *error = ::GetLastError();
28 return nullptr;
29 }
30
31 scoped_ptr<BYTE[]> buffer(new BYTE[size]);
32 if (!::GetTokenInformation(token.Get(), info_class, buffer.get(), size,
33 &size)) {
34 *error = ::GetLastError();
35 return nullptr;
36 }
37
38 *error = ERROR_SUCCESS;
39 return buffer;
40 }
41
42 } // namespace
43
44 namespace sandbox {
45
46 RestrictedToken::RestrictedToken()
47 : integrity_level_(INTEGRITY_LEVEL_LAST),
48 init_(false),
49 lockdown_default_dacl_(false) {}
50
51 RestrictedToken::~RestrictedToken() {
52 }
53
54 DWORD RestrictedToken::Init(const HANDLE effective_token) {
55 if (init_)
56 return ERROR_ALREADY_INITIALIZED;
57
58 HANDLE temp_token;
59 if (effective_token) {
60 // We duplicate the handle to be able to use it even if the original handle
61 // is closed.
62 if (!::DuplicateHandle(::GetCurrentProcess(), effective_token,
63 ::GetCurrentProcess(), &temp_token,
64 0, FALSE, DUPLICATE_SAME_ACCESS)) {
65 return ::GetLastError();
66 }
67 } else {
68 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
69 &temp_token)) {
70 return ::GetLastError();
71 }
72 }
73 effective_token_.Set(temp_token);
74
75 init_ = true;
76 return ERROR_SUCCESS;
77 }
78
79 DWORD RestrictedToken::GetRestrictedToken(
80 base::win::ScopedHandle* token) const {
81 DCHECK(init_);
82 if (!init_)
83 return ERROR_NO_TOKEN;
84
85 size_t deny_size = sids_for_deny_only_.size();
86 size_t restrict_size = sids_to_restrict_.size();
87 size_t privileges_size = privileges_to_disable_.size();
88
89 SID_AND_ATTRIBUTES *deny_only_array = NULL;
90 if (deny_size) {
91 deny_only_array = new SID_AND_ATTRIBUTES[deny_size];
92
93 for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
94 deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
95 deny_only_array[i].Sid =
96 const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
97 }
98 }
99
100 SID_AND_ATTRIBUTES *sids_to_restrict_array = NULL;
101 if (restrict_size) {
102 sids_to_restrict_array = new SID_AND_ATTRIBUTES[restrict_size];
103
104 for (unsigned int i = 0; i < restrict_size; ++i) {
105 sids_to_restrict_array[i].Attributes = 0;
106 sids_to_restrict_array[i].Sid =
107 const_cast<SID*>(sids_to_restrict_[i].GetPSID());
108 }
109 }
110
111 LUID_AND_ATTRIBUTES *privileges_to_disable_array = NULL;
112 if (privileges_size) {
113 privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size];
114
115 for (unsigned int i = 0; i < privileges_size; ++i) {
116 privileges_to_disable_array[i].Attributes = 0;
117 privileges_to_disable_array[i].Luid = privileges_to_disable_[i];
118 }
119 }
120
121 BOOL result = TRUE;
122 HANDLE new_token_handle = NULL;
123 // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell
124 // if a token has ben restricted given the limiations of IsTokenRestricted()
125 // but it appears that in Windows 7 it hints the AppLocker subsystem to
126 // leave us alone.
127 if (deny_size || restrict_size || privileges_size) {
128 result = ::CreateRestrictedToken(effective_token_.Get(),
129 SANDBOX_INERT,
130 static_cast<DWORD>(deny_size),
131 deny_only_array,
132 static_cast<DWORD>(privileges_size),
133 privileges_to_disable_array,
134 static_cast<DWORD>(restrict_size),
135 sids_to_restrict_array,
136 &new_token_handle);
137 } else {
138 // Duplicate the token even if it's not modified at this point
139 // because any subsequent changes to this token would also affect the
140 // current process.
141 result = ::DuplicateTokenEx(effective_token_.Get(), TOKEN_ALL_ACCESS, NULL,
142 SecurityIdentification, TokenPrimary,
143 &new_token_handle);
144 }
145 auto last_error = ::GetLastError();
146
147 if (deny_only_array)
148 delete[] deny_only_array;
149
150 if (sids_to_restrict_array)
151 delete[] sids_to_restrict_array;
152
153 if (privileges_to_disable_array)
154 delete[] privileges_to_disable_array;
155
156 if (!result)
157 return last_error;
158
159 base::win::ScopedHandle new_token(new_token_handle);
160
161 if (lockdown_default_dacl_) {
162 // Don't add Restricted sid and also remove logon sid access.
163 if (!RevokeLogonSidFromDefaultDacl(new_token.Get()))
164 return ::GetLastError();
165 } else {
166 // Modify the default dacl on the token to contain Restricted.
167 if (!AddSidToDefaultDacl(new_token.Get(), WinRestrictedCodeSid,
168 GRANT_ACCESS, GENERIC_ALL)) {
169 return ::GetLastError();
170 }
171 }
172
173 // Add user to default dacl.
174 if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL))
175 return ::GetLastError();
176
177 DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_);
178 if (ERROR_SUCCESS != error)
179 return error;
180
181 HANDLE token_handle;
182 if (!::DuplicateHandle(::GetCurrentProcess(), new_token.Get(),
183 ::GetCurrentProcess(), &token_handle,
184 TOKEN_ALL_ACCESS, FALSE, // Don't inherit.
185 0)) {
186 return ::GetLastError();
187 }
188
189 token->Set(token_handle);
190 return ERROR_SUCCESS;
191 }
192
193 DWORD RestrictedToken::GetRestrictedTokenForImpersonation(
194 base::win::ScopedHandle* token) const {
195 DCHECK(init_);
196 if (!init_)
197 return ERROR_NO_TOKEN;
198
199 base::win::ScopedHandle restricted_token;
200 DWORD err_code = GetRestrictedToken(&restricted_token);
201 if (ERROR_SUCCESS != err_code)
202 return err_code;
203
204 HANDLE impersonation_token_handle;
205 if (!::DuplicateToken(restricted_token.Get(),
206 SecurityImpersonation,
207 &impersonation_token_handle)) {
208 return ::GetLastError();
209 }
210 base::win::ScopedHandle impersonation_token(impersonation_token_handle);
211
212 HANDLE token_handle;
213 if (!::DuplicateHandle(::GetCurrentProcess(), impersonation_token.Get(),
214 ::GetCurrentProcess(), &token_handle,
215 TOKEN_ALL_ACCESS, FALSE, // Don't inherit.
216 0)) {
217 return ::GetLastError();
218 }
219
220 token->Set(token_handle);
221 return ERROR_SUCCESS;
222 }
223
224 DWORD RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) {
225 DCHECK(init_);
226 if (!init_)
227 return ERROR_NO_TOKEN;
228
229 DWORD error;
230 scoped_ptr<BYTE[]> buffer =
231 GetTokenInfo(effective_token_, TokenGroups, &error);
232
233 if (!buffer)
234 return error;
235
236 TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
237
238 // Build the list of the deny only group SIDs
239 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
240 if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
241 (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
242 bool should_ignore = false;
243 if (exceptions) {
244 for (unsigned int j = 0; j < exceptions->size(); ++j) {
245 if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
246 token_groups->Groups[i].Sid)) {
247 should_ignore = true;
248 break;
249 }
250 }
251 }
252 if (!should_ignore) {
253 sids_for_deny_only_.push_back(
254 reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
255 }
256 }
257 }
258
259 return ERROR_SUCCESS;
260 }
261
262 DWORD RestrictedToken::AddSidForDenyOnly(const Sid &sid) {
263 DCHECK(init_);
264 if (!init_)
265 return ERROR_NO_TOKEN;
266
267 sids_for_deny_only_.push_back(sid);
268 return ERROR_SUCCESS;
269 }
270
271 DWORD RestrictedToken::AddUserSidForDenyOnly() {
272 DCHECK(init_);
273 if (!init_)
274 return ERROR_NO_TOKEN;
275
276 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
277 scoped_ptr<BYTE[]> buffer(new BYTE[size]);
278 TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get());
279
280 BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser,
281 token_user, size, &size);
282
283 if (!result)
284 return ::GetLastError();
285
286 Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
287 sids_for_deny_only_.push_back(user);
288
289 return ERROR_SUCCESS;
290 }
291
292 DWORD RestrictedToken::DeleteAllPrivileges(
293 const std::vector<base::string16> *exceptions) {
294 DCHECK(init_);
295 if (!init_)
296 return ERROR_NO_TOKEN;
297
298 DWORD error;
299 scoped_ptr<BYTE[]> buffer =
300 GetTokenInfo(effective_token_, TokenPrivileges, &error);
301
302 if (!buffer)
303 return error;
304
305 TOKEN_PRIVILEGES* token_privileges =
306 reinterpret_cast<TOKEN_PRIVILEGES*>(buffer.get());
307
308 // Build the list of privileges to disable
309 for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
310 bool should_ignore = false;
311 if (exceptions) {
312 for (unsigned int j = 0; j < exceptions->size(); ++j) {
313 LUID luid = {0};
314 ::LookupPrivilegeValue(NULL, (*exceptions)[j].c_str(), &luid);
315 if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
316 token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
317 should_ignore = true;
318 break;
319 }
320 }
321 }
322 if (!should_ignore) {
323 privileges_to_disable_.push_back(token_privileges->Privileges[i].Luid);
324 }
325 }
326
327 return ERROR_SUCCESS;
328 }
329
330 DWORD RestrictedToken::DeletePrivilege(const wchar_t *privilege) {
331 DCHECK(init_);
332 if (!init_)
333 return ERROR_NO_TOKEN;
334
335 LUID luid = {0};
336 if (LookupPrivilegeValue(NULL, privilege, &luid))
337 privileges_to_disable_.push_back(luid);
338 else
339 return ::GetLastError();
340
341 return ERROR_SUCCESS;
342 }
343
344 DWORD RestrictedToken::AddRestrictingSid(const Sid &sid) {
345 DCHECK(init_);
346 if (!init_)
347 return ERROR_NO_TOKEN;
348
349 sids_to_restrict_.push_back(sid); // No attributes
350 return ERROR_SUCCESS;
351 }
352
353 DWORD RestrictedToken::AddRestrictingSidLogonSession() {
354 DCHECK(init_);
355 if (!init_)
356 return ERROR_NO_TOKEN;
357
358 DWORD error;
359 scoped_ptr<BYTE[]> buffer =
360 GetTokenInfo(effective_token_, TokenGroups, &error);
361
362 if (!buffer)
363 return error;
364
365 TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
366
367 SID *logon_sid = NULL;
368 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
369 if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
370 logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid);
371 break;
372 }
373 }
374
375 if (logon_sid)
376 sids_to_restrict_.push_back(logon_sid);
377
378 return ERROR_SUCCESS;
379 }
380
381 DWORD RestrictedToken::AddRestrictingSidCurrentUser() {
382 DCHECK(init_);
383 if (!init_)
384 return ERROR_NO_TOKEN;
385
386 DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
387 scoped_ptr<BYTE[]> buffer(new BYTE[size]);
388 TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get());
389
390 BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser,
391 token_user, size, &size);
392
393 if (!result)
394 return ::GetLastError();
395
396 Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
397 sids_to_restrict_.push_back(user);
398
399 return ERROR_SUCCESS;
400 }
401
402 DWORD RestrictedToken::AddRestrictingSidAllSids() {
403 DCHECK(init_);
404 if (!init_)
405 return ERROR_NO_TOKEN;
406
407 // Add the current user to the list.
408 DWORD error = AddRestrictingSidCurrentUser();
409 if (ERROR_SUCCESS != error)
410 return error;
411
412 scoped_ptr<BYTE[]> buffer =
413 GetTokenInfo(effective_token_, TokenGroups, &error);
414
415 if (!buffer)
416 return error;
417
418 TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
419
420 // Build the list of restricting sids from all groups.
421 for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
422 if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0)
423 AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
424 }
425
426 return ERROR_SUCCESS;
427 }
428
429 DWORD RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) {
430 integrity_level_ = integrity_level;
431 return ERROR_SUCCESS;
432 }
433
434 void RestrictedToken::SetLockdownDefaultDacl() {
435 lockdown_default_dacl_ = true;
436 }
437
438 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/restricted_token.h ('k') | sandbox/win/src/restricted_token_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698