1 // Copyright 2021 The Chromium Authors
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 "base/win/access_token.h"
6
7 #include <windows.h>
8
9 #include <algorithm>
10 #include <cstdint>
11 #include <map>
12 #include <optional>
13 #include <utility>
14
15 #include "base/win/atl.h"
16 #include "base/win/scoped_handle.h"
17 #include "base/win/security_util.h"
18 #include "base/win/windows_version.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base::win {
22
23 namespace {
24
25 // All token access minus TOKEN_QUERY
26 constexpr ACCESS_MASK kTokenAllNoQuery = (TOKEN_ALL_ACCESS & ~TOKEN_QUERY);
27
CompareLuid(const CHROME_LUID & left,const LUID & right)28 bool CompareLuid(const CHROME_LUID& left, const LUID& right) {
29 return left.HighPart == right.HighPart && left.LowPart == right.LowPart;
30 }
31
ConvertLuid(const AccessToken::Privilege & priv)32 int64_t ConvertLuid(const AccessToken::Privilege& priv) {
33 CHROME_LUID luid = priv.GetLuid();
34 return (static_cast<int64_t>(luid.HighPart) << 32) | luid.LowPart;
35 }
36
ConvertLuid(const LUID & luid)37 int64_t ConvertLuid(const LUID& luid) {
38 return (static_cast<int64_t>(luid.HighPart) << 32) | luid.LowPart;
39 }
40
EqualSid(const Sid & left,const ATL::CSid & right)41 bool EqualSid(const Sid& left, const ATL::CSid& right) {
42 return left.Equal(const_cast<SID*>(right.GetPSID()));
43 }
44
CompareGroups(const std::vector<AccessToken::Group> & groups,const ATL::CSid::CSidArray & sids,const ATL::CAtlArray<DWORD> & attrs)45 void CompareGroups(const std::vector<AccessToken::Group>& groups,
46 const ATL::CSid::CSidArray& sids,
47 const ATL::CAtlArray<DWORD>& attrs) {
48 ASSERT_EQ(groups.size(), sids.GetCount());
49 ASSERT_EQ(sids.GetCount(), attrs.GetCount());
50 std::map<std::wstring, DWORD> group_map;
51 for (const AccessToken::Group& group : groups) {
52 std::optional<std::wstring> sddl = group.GetSid().ToSddlString();
53 ASSERT_TRUE(sddl);
54 group_map.insert({*sddl, group.GetAttributes()});
55 }
56 for (size_t index = 0; index < sids.GetCount(); ++index) {
57 auto found_group = group_map.find(sids[index].Sid());
58 ASSERT_NE(found_group, group_map.end());
59 EXPECT_EQ(found_group->second, attrs[index]);
60 }
61 }
62
CompareGroups(const std::vector<AccessToken::Group> & groups,const CTokenGroups & atl_groups)63 void CompareGroups(const std::vector<AccessToken::Group>& groups,
64 const CTokenGroups& atl_groups) {
65 ATL::CSid::CSidArray sids;
66 ATL::CAtlArray<DWORD> attrs;
67 atl_groups.GetSidsAndAttributes(&sids, &attrs);
68 CompareGroups(groups, sids, attrs);
69 }
70
ComparePrivileges(const std::vector<AccessToken::Privilege> & privs,const ATL::CTokenPrivileges & atl_privs)71 void ComparePrivileges(const std::vector<AccessToken::Privilege>& privs,
72 const ATL::CTokenPrivileges& atl_privs) {
73 CLUIDArray luids;
74 ATL::CTokenPrivileges::CAttributes attrs;
75 atl_privs.GetLuidsAndAttributes(&luids, &attrs);
76 ATL::CTokenPrivileges::CNames names;
77 atl_privs.GetNamesAndAttributes(&names);
78 ASSERT_EQ(privs.size(), luids.GetCount());
79 ASSERT_EQ(privs.size(), attrs.GetCount());
80 ASSERT_EQ(privs.size(), names.GetCount());
81
82 std::map<int64_t, const AccessToken::Privilege&> priv_map;
83 for (const AccessToken::Privilege& priv : privs) {
84 priv_map.insert({ConvertLuid(priv), priv});
85 }
86
87 for (size_t index = 0; index < luids.GetCount(); ++index) {
88 auto found_priv = priv_map.find(ConvertLuid(luids[index]));
89 ASSERT_NE(found_priv, priv_map.end());
90 EXPECT_TRUE(CompareLuid(found_priv->second.GetLuid(), luids[index]));
91 EXPECT_EQ(found_priv->second.GetAttributes(), attrs[index]);
92 EXPECT_EQ(found_priv->second.GetName().c_str(), names[index]);
93 }
94 }
95
CompareIntegrityLevel(const AccessToken & token,const ATL::CAccessToken & atl_token)96 void CompareIntegrityLevel(const AccessToken& token,
97 const ATL::CAccessToken& atl_token) {
98 char buffer[sizeof(TOKEN_MANDATORY_LABEL) + SECURITY_MAX_SID_SIZE];
99 DWORD size = sizeof(buffer);
100 ASSERT_TRUE(::GetTokenInformation(atl_token.GetHandle(), TokenIntegrityLevel,
101 buffer, size, &size));
102 TOKEN_MANDATORY_LABEL* label =
103 reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buffer);
104 ASSERT_TRUE(label->Label.Sid);
105 std::optional<Sid> il_sid = Sid::FromIntegrityLevel(token.IntegrityLevel());
106 ASSERT_TRUE(il_sid);
107 EXPECT_TRUE(il_sid->Equal(label->Label.Sid));
108 }
109
CompareElevated(const AccessToken & token,const ATL::CAccessToken & atl_token)110 void CompareElevated(const AccessToken& token,
111 const ATL::CAccessToken& atl_token) {
112 TOKEN_ELEVATION elevation;
113 DWORD size = sizeof(elevation);
114 ASSERT_TRUE(::GetTokenInformation(atl_token.GetHandle(), TokenElevation,
115 &elevation, size, &size));
116 EXPECT_EQ(token.IsElevated(), !!elevation.TokenIsElevated);
117 }
118
GetLinkedToken(const ATL::CAccessToken & token,ATL::CAccessToken * linked_token)119 bool GetLinkedToken(const ATL::CAccessToken& token,
120 ATL::CAccessToken* linked_token) {
121 TOKEN_LINKED_TOKEN value;
122 DWORD size = sizeof(value);
123 if (!::GetTokenInformation(token.GetHandle(), TokenLinkedToken, &value, size,
124 &size)) {
125 return false;
126 }
127 linked_token->Attach(value.LinkedToken);
128 return true;
129 }
130
CompareDefaultDacl(const AccessToken & token,const ATL::CAccessToken & atl_token)131 void CompareDefaultDacl(const AccessToken& token,
132 const ATL::CAccessToken& atl_token) {
133 CDacl atl_dacl;
134 ASSERT_TRUE(atl_token.GetDefaultDacl(&atl_dacl));
135 ATL::CSid::CSidArray sids;
136 CAcl::CAccessMaskArray access;
137 CAcl::CAceTypeArray types;
138 CAcl::CAceFlagArray flags;
139 atl_dacl.GetAclEntries(&sids, &access, &types, &flags);
140 std::optional<AccessControlList> dacl = token.DefaultDacl();
141 ASSERT_TRUE(dacl);
142 ACL* acl_ptr = dacl->get();
143 ASSERT_TRUE(acl_ptr);
144 DWORD ace_count = acl_ptr->AceCount;
145 ASSERT_EQ(ace_count, sids.GetCount());
146 ASSERT_EQ(ace_count, access.GetCount());
147 ASSERT_EQ(ace_count, types.GetCount());
148 ASSERT_EQ(ace_count, flags.GetCount());
149 for (DWORD index = 0; index < ace_count; ++index) {
150 ACE_HEADER* ace_header;
151 ASSERT_TRUE(GetAce(acl_ptr, index, reinterpret_cast<LPVOID*>(&ace_header)));
152 ASSERT_EQ(ace_header->AceType, types[index]);
153 ASSERT_EQ(ace_header->AceFlags, flags[index]);
154 // We only do a full comparison for these types of ACE.
155 if (ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE ||
156 ace_header->AceType == ACCESS_DENIED_ACE_TYPE) {
157 // ACCESS_ALLOWED_ACE and ACCESS_DENIED_ACE have the same layout.
158 ACCESS_ALLOWED_ACE* ace =
159 reinterpret_cast<ACCESS_ALLOWED_ACE*>(ace_header);
160 EXPECT_EQ(ace->Mask, access[index]);
161 std::optional<Sid> sid = Sid::FromPSID(&ace->SidStart);
162 ASSERT_TRUE(sid);
163 EXPECT_TRUE(EqualSid(*sid, sids[index]));
164 }
165 }
166 }
167
CompareTokens(const AccessToken & token,const ATL::CAccessToken & atl_token,bool compare_linked_token=true)168 void CompareTokens(const AccessToken& token,
169 const ATL::CAccessToken& atl_token,
170 bool compare_linked_token = true) {
171 LUID luid;
172 // Only compare IDs if we're not comparing a token's linked token as the ID
173 // will be different.
174 if (compare_linked_token) {
175 ASSERT_TRUE(atl_token.GetTokenId(&luid));
176 EXPECT_TRUE(CompareLuid(token.Id(), luid));
177 }
178 ASSERT_TRUE(atl_token.GetLogonSessionId(&luid));
179 EXPECT_TRUE(CompareLuid(token.AuthenticationId(), luid));
180 ATL::CSid user_sid;
181 ASSERT_TRUE(atl_token.GetUser(&user_sid));
182 EXPECT_TRUE(EqualSid(token.User(), user_sid));
183 AccessToken::Group user_group = token.UserGroup();
184 EXPECT_TRUE(EqualSid(user_group.GetSid(), user_sid));
185 EXPECT_EQ(0U, user_group.GetAttributes());
186 ATL::CSid owner_sid;
187 ASSERT_TRUE(atl_token.GetOwner(&owner_sid));
188 EXPECT_TRUE(EqualSid(token.Owner(), owner_sid));
189 ATL::CSid primary_group;
190 ASSERT_TRUE(atl_token.GetPrimaryGroup(&primary_group));
191 EXPECT_TRUE(EqualSid(token.PrimaryGroup(), primary_group));
192 std::optional<Sid> logon_sid = token.LogonId();
193 if (!logon_sid) {
194 EXPECT_EQ(DWORD{ERROR_NOT_FOUND}, ::GetLastError());
195 }
196 ATL::CSid atl_logon_sid;
197 if (!atl_token.GetLogonSid(&atl_logon_sid)) {
198 EXPECT_FALSE(logon_sid);
199 } else {
200 ASSERT_TRUE(logon_sid);
201 EXPECT_TRUE(EqualSid(*logon_sid, atl_logon_sid));
202 }
203 DWORD session_id;
204 ASSERT_TRUE(atl_token.GetTerminalServicesSessionId(&session_id));
205 EXPECT_EQ(token.SessionId(), session_id);
206 CompareIntegrityLevel(token, atl_token);
207 CompareElevated(token, atl_token);
208 EXPECT_EQ(token.IsRestricted(), atl_token.IsTokenRestricted());
209 TOKEN_TYPE token_type;
210 ASSERT_TRUE(atl_token.GetType(&token_type));
211 EXPECT_EQ(token.IsImpersonation(), token_type == TokenImpersonation);
212 if (token_type == TokenImpersonation) {
213 SECURITY_IMPERSONATION_LEVEL imp_level;
214 ASSERT_TRUE(atl_token.GetImpersonationLevel(&imp_level));
215 EXPECT_EQ(static_cast<int>(token.ImpersonationLevel()), imp_level);
216 }
217 CTokenGroups atl_groups;
218 ASSERT_TRUE(atl_token.GetGroups(&atl_groups));
219 CompareGroups(token.Groups(), atl_groups);
220 ATL::CTokenPrivileges atl_privs;
221 ASSERT_TRUE(atl_token.GetPrivileges(&atl_privs));
222 ComparePrivileges(token.Privileges(), atl_privs);
223 CompareDefaultDacl(token, atl_token);
224 std::optional<AccessToken> linked_token = token.LinkedToken();
225 ATL::CAccessToken atl_linked_token;
226 bool result = GetLinkedToken(atl_token, &atl_linked_token);
227 if (!linked_token) {
228 EXPECT_FALSE(result);
229 } else {
230 ASSERT_TRUE(result);
231 if (compare_linked_token)
232 CompareTokens(*linked_token, atl_linked_token, false);
233 }
234 }
235
DuplicateTokenWithSecurityDescriptor(const ATL::CAccessToken & token,DWORD desired_access,LPCWSTR security_descriptor,ATL::CAccessToken * new_token)236 bool DuplicateTokenWithSecurityDescriptor(const ATL::CAccessToken& token,
237 DWORD desired_access,
238 LPCWSTR security_descriptor,
239 ATL::CAccessToken* new_token) {
240 ATL::CSecurityDesc sd;
241 if (!sd.FromString(security_descriptor))
242 return false;
243 ATL::CSecurityAttributes sa;
244 sa.Set(sd);
245 return token.CreatePrimaryToken(new_token, desired_access, &sa);
246 }
247
CreateImpersonationToken(SECURITY_IMPERSONATION_LEVEL impersonation_level,ATL::CAccessToken * imp_token)248 bool CreateImpersonationToken(SECURITY_IMPERSONATION_LEVEL impersonation_level,
249 ATL::CAccessToken* imp_token) {
250 ATL::CAccessToken token;
251 if (!token.GetProcessToken(MAXIMUM_ALLOWED))
252 return false;
253 return token.CreateImpersonationToken(imp_token, impersonation_level);
254 }
255
CheckTokenError(const std::optional<AccessToken> & token,DWORD expected_error)256 void CheckTokenError(const std::optional<AccessToken>& token,
257 DWORD expected_error) {
258 DWORD error = ::GetLastError();
259 EXPECT_FALSE(token);
260 EXPECT_EQ(expected_error, error);
261 }
262
CheckError(bool result,DWORD expected_error)263 void CheckError(bool result, DWORD expected_error) {
264 DWORD error = ::GetLastError();
265 EXPECT_FALSE(result);
266 EXPECT_EQ(expected_error, error);
267 }
268
CheckAccessTokenGroup(DWORD attributes,bool integrity,bool enabled,bool deny_only,bool logon_id)269 void CheckAccessTokenGroup(DWORD attributes,
270 bool integrity,
271 bool enabled,
272 bool deny_only,
273 bool logon_id) {
274 AccessToken::Group group(Sid(WellKnownSid::kWorld), attributes);
275 EXPECT_EQ(L"S-1-1-0", *group.GetSid().ToSddlString());
276 EXPECT_EQ(integrity, group.IsIntegrity());
277 EXPECT_EQ(enabled, group.IsEnabled());
278 EXPECT_EQ(deny_only, group.IsDenyOnly());
279 EXPECT_EQ(logon_id, group.IsLogonId());
280 }
281
CheckAccessTokenPrivilege(LPCWSTR name,DWORD attributes,bool enabled)282 void CheckAccessTokenPrivilege(LPCWSTR name, DWORD attributes, bool enabled) {
283 LUID luid;
284 ASSERT_TRUE(::LookupPrivilegeValue(nullptr, name, &luid));
285 CHROME_LUID chrome_luid;
286 chrome_luid.LowPart = luid.LowPart;
287 chrome_luid.HighPart = luid.HighPart;
288 AccessToken::Privilege priv(chrome_luid, attributes);
289 EXPECT_TRUE(CompareLuid(priv.GetLuid(), luid));
290 EXPECT_EQ(name, priv.GetName());
291 EXPECT_EQ(attributes, priv.GetAttributes());
292 EXPECT_EQ(enabled, priv.IsEnabled());
293 }
294
295 typedef NTSTATUS(WINAPI* NtCreateLowBoxToken)(OUT PHANDLE token,
296 IN HANDLE original_handle,
297 IN ACCESS_MASK access,
298 IN PVOID object_attribute,
299 IN PSID appcontainer_sid,
300 IN DWORD capabilityCount,
301 IN PSID_AND_ATTRIBUTES
302 capabilities,
303 IN DWORD handle_count,
304 IN PHANDLE handles);
305
CompareAppContainer(const Sid & package_sid,const std::vector<Sid> & caps)306 void CompareAppContainer(const Sid& package_sid, const std::vector<Sid>& caps) {
307 static NtCreateLowBoxToken pNtCreateLowBoxToken =
308 reinterpret_cast<NtCreateLowBoxToken>(::GetProcAddress(
309 ::GetModuleHandle(L"ntdll.dll"), "NtCreateLowBoxToken"));
310 ASSERT_TRUE(pNtCreateLowBoxToken);
311 ATL::CTokenGroups capabilities;
312 for (const Sid& cap : caps) {
313 capabilities.Add(ATL::CSid(static_cast<SID*>(cap.GetPSID())),
314 SE_GROUP_ENABLED);
315 }
316 ATL::CAccessToken process_token;
317 ASSERT_TRUE(process_token.GetProcessToken(TOKEN_ALL_ACCESS));
318 UINT cap_count = capabilities.GetCount();
319 PTOKEN_GROUPS cap_groups =
320 const_cast<PTOKEN_GROUPS>(capabilities.GetPTOKEN_GROUPS());
321 HANDLE tmp_token;
322 NTSTATUS status = pNtCreateLowBoxToken(
323 &tmp_token, process_token.GetHandle(), TOKEN_ALL_ACCESS, nullptr,
324 package_sid.GetPSID(), cap_count,
325 cap_count > 0 ? cap_groups->Groups : nullptr, 0, nullptr);
326 ASSERT_EQ(0, status);
327 ScopedHandle scoped_tmp_token(tmp_token);
328 std::optional<AccessToken> ac_token =
329 AccessToken::FromToken(scoped_tmp_token.get());
330 ASSERT_TRUE(ac_token);
331 EXPECT_TRUE(ac_token->IsAppContainer());
332 EXPECT_EQ(ac_token->AppContainerSid(), package_sid);
333 CompareGroups(ac_token->Capabilities(), capabilities);
334 }
335
GetTokenAccess(const AccessToken & token)336 ACCESS_MASK GetTokenAccess(const AccessToken& token) {
337 std::optional<ACCESS_MASK> granted_access = GetGrantedAccess(token.get());
338 CHECK(granted_access);
339 return *granted_access;
340 }
341
GroupsToSids(const std::vector<AccessToken::Group> & groups)342 std::vector<Sid> GroupsToSids(const std::vector<AccessToken::Group>& groups) {
343 std::vector<Sid> sids;
344 for (const AccessToken::Group& group : groups) {
345 sids.push_back(group.GetSid().Clone());
346 }
347 return sids;
348 }
349
PrivilegesToNames(const std::vector<AccessToken::Privilege> & privs)350 std::vector<std::wstring> PrivilegesToNames(
351 const std::vector<AccessToken::Privilege>& privs) {
352 std::vector<std::wstring> sids;
353 for (const AccessToken::Privilege& priv : privs) {
354 sids.push_back(priv.GetName());
355 }
356 return sids;
357 }
358 } // namespace
359
TEST(AccessTokenTest,FromToken)360 TEST(AccessTokenTest, FromToken) {
361 ATL::CAccessToken atl_token;
362 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_QUERY));
363
364 std::optional<AccessToken> token =
365 AccessToken::FromToken(atl_token.GetHandle());
366 ASSERT_TRUE(token);
367 CompareTokens(*token, atl_token);
368 EXPECT_EQ(GetTokenAccess(*token), DWORD{TOKEN_QUERY});
369
370 std::optional<AccessToken> all_access_token =
371 AccessToken::FromToken(atl_token.GetHandle(), kTokenAllNoQuery);
372 ASSERT_TRUE(all_access_token);
373 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
374
375 // Check that we duplicated the handle.
376 LUID luid;
377 ASSERT_TRUE(atl_token.GetTokenId(&luid));
378 ::CloseHandle(atl_token.Detach());
379 LUID temp_luid;
380 ASSERT_FALSE(atl_token.GetTokenId(&temp_luid));
381 EXPECT_TRUE(CompareLuid(token->Id(), luid));
382
383 // Check that we duplicate with the correct access rights.
384 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_QUERY_SOURCE));
385 ASSERT_FALSE(atl_token.GetTokenId(&temp_luid));
386 std::optional<AccessToken> token2 =
387 AccessToken::FromToken(atl_token.GetHandle());
388 ASSERT_TRUE(token2);
389 EXPECT_TRUE(CompareLuid(token2->Id(), luid));
390
391 // Check that we fail if we don't have access to the token object.
392 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_DUPLICATE));
393 ATL::CAccessToken pri_token;
394 ASSERT_TRUE(DuplicateTokenWithSecurityDescriptor(
395 atl_token, TOKEN_QUERY_SOURCE, L"D:", &pri_token));
396 CheckTokenError(AccessToken::FromToken(pri_token.GetHandle()),
397 ERROR_ACCESS_DENIED);
398
399 CheckTokenError(AccessToken::FromToken(ScopedHandle(nullptr)),
400 ERROR_INVALID_HANDLE);
401 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_QUERY));
402 ScopedHandle token_handle(atl_token.Detach());
403 token = AccessToken::FromToken(std::move(token_handle));
404 ASSERT_TRUE(token);
405 EXPECT_FALSE(token_handle.is_valid());
406 EXPECT_TRUE(token->is_valid());
407 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_DUPLICATE));
408 token_handle.Set(atl_token.Detach());
409 CheckTokenError(AccessToken::FromToken(std::move(token_handle)),
410 ERROR_ACCESS_DENIED);
411 }
412
TEST(AccessTokenTest,FromProcess)413 TEST(AccessTokenTest, FromProcess) {
414 ScopedHandle process(
415 ::OpenProcess(PROCESS_TERMINATE, FALSE, ::GetCurrentProcessId()));
416 ASSERT_TRUE(process.is_valid());
417 CheckTokenError(AccessToken::FromProcess(process.get()), ERROR_ACCESS_DENIED);
418 CheckTokenError(AccessToken::FromProcess(process.get(), true),
419 ERROR_ACCESS_DENIED);
420 process.Set(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
421 ::GetCurrentProcessId()));
422 ASSERT_TRUE(process.is_valid());
423 std::optional<AccessToken> token = AccessToken::FromProcess(process.get());
424 ASSERT_TRUE(token);
425 EXPECT_EQ(GetTokenAccess(*token), DWORD{TOKEN_QUERY});
426 ASSERT_FALSE(token->IsImpersonation());
427 ATL::CAccessToken atl_token;
428 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_QUERY, process.get()));
429 CompareTokens(*token, atl_token);
430 std::optional<AccessToken> imp_token =
431 AccessToken::FromProcess(process.get(), true);
432 ASSERT_TRUE(imp_token);
433 ASSERT_TRUE(imp_token->IsImpersonation());
434 ASSERT_TRUE(imp_token->IsIdentification());
435
436 std::optional<AccessToken> all_access_token =
437 AccessToken::FromProcess(process.get(), false, kTokenAllNoQuery);
438 ASSERT_TRUE(all_access_token);
439 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
440
441 all_access_token =
442 AccessToken::FromProcess(process.get(), true, kTokenAllNoQuery);
443 ASSERT_TRUE(all_access_token);
444 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
445 }
446
TEST(AccessTokenTest,FromCurrentProcess)447 TEST(AccessTokenTest, FromCurrentProcess) {
448 std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
449 ASSERT_TRUE(token);
450 ASSERT_FALSE(token->IsImpersonation());
451 ATL::CAccessToken atl_token;
452 ASSERT_TRUE(atl_token.GetProcessToken(TOKEN_QUERY));
453 CompareTokens(*token, atl_token);
454 std::optional<AccessToken> imp_token = AccessToken::FromCurrentProcess(true);
455 ASSERT_TRUE(imp_token);
456 ASSERT_TRUE(imp_token->IsImpersonation());
457 ASSERT_TRUE(imp_token->IsIdentification());
458
459 std::optional<AccessToken> all_access_token =
460 AccessToken::FromCurrentProcess(false, kTokenAllNoQuery);
461 ASSERT_TRUE(all_access_token);
462 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
463
464 all_access_token = AccessToken::FromCurrentProcess(true, kTokenAllNoQuery);
465 ASSERT_TRUE(all_access_token);
466 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
467 }
468
TEST(AccessTokenTest,FromThread)469 TEST(AccessTokenTest, FromThread) {
470 // Make sure we have no impersonation token before starting.
471 ::RevertToSelf();
472 // Check we
473 CheckTokenError(AccessToken::FromThread(::GetCurrentThread()),
474 ERROR_NO_TOKEN);
475 ScopedHandle thread(
476 ::OpenThread(THREAD_TERMINATE, FALSE, ::GetCurrentThreadId()));
477 ASSERT_TRUE(thread.is_valid());
478 CheckTokenError(AccessToken::FromThread(thread.get()), ERROR_ACCESS_DENIED);
479
480 ATL::CAccessToken atl_imp_token;
481 ASSERT_TRUE(CreateImpersonationToken(SecurityImpersonation, &atl_imp_token));
482 ASSERT_TRUE(atl_imp_token.Impersonate());
483 CAutoRevertImpersonation scoped_imp(&atl_imp_token);
484
485 thread.Set(::OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE,
486 ::GetCurrentThreadId()));
487 ASSERT_TRUE(thread.is_valid());
488 std::optional<AccessToken> imp_token = AccessToken::FromThread(thread.get());
489 std::optional<AccessToken> all_access_token =
490 AccessToken::FromThread(thread.get(), true, kTokenAllNoQuery);
491 atl_imp_token.Revert();
492 ASSERT_TRUE(imp_token);
493 EXPECT_EQ(GetTokenAccess(*imp_token), DWORD{TOKEN_QUERY});
494 ASSERT_TRUE(imp_token->IsImpersonation());
495 EXPECT_FALSE(imp_token->IsIdentification());
496 CompareTokens(*imp_token, atl_imp_token);
497 ASSERT_TRUE(all_access_token);
498 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
499
500 ATL::CAccessToken atl_id_token;
501 ASSERT_TRUE(CreateImpersonationToken(SecurityIdentification, &atl_id_token));
502 ASSERT_TRUE(atl_id_token.Impersonate());
503 CAutoRevertImpersonation scoped_imp2(&atl_id_token);
504 CheckTokenError(AccessToken::FromThread(thread.get(), false),
505 ERROR_BAD_IMPERSONATION_LEVEL);
506 std::optional<AccessToken> id_token =
507 AccessToken::FromThread(thread.get(), true);
508 atl_id_token.Revert();
509 ASSERT_TRUE(id_token);
510 EXPECT_TRUE(id_token->IsIdentification());
511 CompareTokens(*id_token, atl_id_token);
512 }
513
TEST(AccessTokenTest,FromCurrentThread)514 TEST(AccessTokenTest, FromCurrentThread) {
515 // Make sure we have no impersonation token before starting.
516 ::RevertToSelf();
517 // Check we don't have a token.
518 CheckTokenError(AccessToken::FromCurrentThread(), ERROR_NO_TOKEN);
519
520 ATL::CAccessToken atl_imp_token;
521 ASSERT_TRUE(CreateImpersonationToken(SecurityImpersonation, &atl_imp_token));
522 ASSERT_TRUE(atl_imp_token.Impersonate());
523 CAutoRevertImpersonation scoped_imp(&atl_imp_token);
524
525 std::optional<AccessToken> imp_token = AccessToken::FromCurrentThread();
526 std::optional<AccessToken> all_access_token =
527 AccessToken::FromCurrentThread(true, kTokenAllNoQuery);
528 atl_imp_token.Revert();
529 ASSERT_TRUE(imp_token);
530 EXPECT_EQ(GetTokenAccess(*imp_token), DWORD{TOKEN_QUERY});
531 ASSERT_TRUE(imp_token->IsImpersonation());
532 EXPECT_FALSE(imp_token->IsIdentification());
533 CompareTokens(*imp_token, atl_imp_token);
534 ASSERT_TRUE(all_access_token);
535 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
536
537 ATL::CAccessToken atl_id_token;
538 ASSERT_TRUE(CreateImpersonationToken(SecurityIdentification, &atl_id_token));
539 ASSERT_TRUE(atl_id_token.Impersonate());
540 ATL::CAutoRevertImpersonation scoped_imp2(&atl_id_token);
541 CheckTokenError(AccessToken::FromCurrentThread(false),
542 ERROR_BAD_IMPERSONATION_LEVEL);
543 std::optional<AccessToken> id_token = AccessToken::FromCurrentThread(true);
544 atl_id_token.Revert();
545 ASSERT_TRUE(id_token);
546 EXPECT_TRUE(id_token->IsIdentification());
547 CompareTokens(*id_token, atl_id_token);
548 }
549
TEST(AccessTokenTest,FromEffective)550 TEST(AccessTokenTest, FromEffective) {
551 // Make sure we have no impersonation token before starting.
552 ::RevertToSelf();
553 std::optional<base::win::AccessToken> primary_token =
554 AccessToken::FromEffective();
555 std::optional<base::win::AccessToken> all_access_token =
556 AccessToken::FromEffective(kTokenAllNoQuery);
557 ASSERT_TRUE(primary_token);
558 EXPECT_EQ(GetTokenAccess(*primary_token), DWORD{TOKEN_QUERY});
559 EXPECT_FALSE(primary_token->IsImpersonation());
560 ASSERT_TRUE(all_access_token);
561 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
562
563 ATL::CAccessToken atl_primary_token;
564 ASSERT_TRUE(atl_primary_token.GetProcessToken(TOKEN_QUERY));
565 CompareTokens(*primary_token, atl_primary_token);
566
567 ATL::CAccessToken atl_imp_token;
568 ASSERT_TRUE(CreateImpersonationToken(SecurityImpersonation, &atl_imp_token));
569 ASSERT_TRUE(atl_imp_token.Impersonate());
570 CAutoRevertImpersonation scoped_imp(&atl_imp_token);
571
572 std::optional<AccessToken> imp_token = AccessToken::FromEffective();
573 all_access_token = AccessToken::FromEffective(kTokenAllNoQuery);
574 atl_imp_token.Revert();
575 ASSERT_TRUE(imp_token);
576 ASSERT_TRUE(imp_token->IsImpersonation());
577 EXPECT_FALSE(imp_token->IsIdentification());
578 CompareTokens(*imp_token, atl_imp_token);
579 ASSERT_TRUE(all_access_token);
580 EXPECT_EQ(GetTokenAccess(*all_access_token), DWORD{TOKEN_ALL_ACCESS});
581 }
582
TEST(AccessTokenTest,AccessTokenGroup)583 TEST(AccessTokenTest, AccessTokenGroup) {
584 CheckAccessTokenGroup(0, false, false, false, false);
585 CheckAccessTokenGroup(SE_GROUP_INTEGRITY, true, false, false, false);
586 CheckAccessTokenGroup(SE_GROUP_ENABLED, false, true, false, false);
587 CheckAccessTokenGroup(SE_GROUP_USE_FOR_DENY_ONLY, false, false, true, false);
588 CheckAccessTokenGroup(SE_GROUP_LOGON_ID, false, false, false, true);
589 CheckAccessTokenGroup(0xFFFFFFFF, true, true, true, true);
590 }
591
TEST(AccessTokenTest,AccessTokenPrivilege)592 TEST(AccessTokenTest, AccessTokenPrivilege) {
593 CheckAccessTokenPrivilege(SE_DEBUG_NAME, 0, false);
594 CheckAccessTokenPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED_BY_DEFAULT,
595 false);
596 CheckAccessTokenPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, true);
597 CheckAccessTokenPrivilege(
598 SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT,
599 true);
600 CheckAccessTokenPrivilege(SE_IMPERSONATE_NAME, 0, false);
601 CHROME_LUID luid{0x8181, 0x5656};
602 AccessToken::Privilege priv(luid, 0);
603 EXPECT_EQ(L"00005656-00008181", priv.GetName());
604 }
605
TEST(AccessTokenTest,IsMember)606 TEST(AccessTokenTest, IsMember) {
607 std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
608 ASSERT_TRUE(token);
609 ASSERT_FALSE(token->IsImpersonation());
610 CheckError(token->IsMember(WellKnownSid::kWorld),
611 ERROR_NO_IMPERSONATION_TOKEN);
612 std::optional<Sid> sid = Sid::FromSddlString(L"S-1-1-2-3-4-5-6-7-8");
613 ASSERT_TRUE(sid);
614 CheckError(token->IsMember(*sid), ERROR_NO_IMPERSONATION_TOKEN);
615
616 std::optional<AccessToken> imp_token = AccessToken::FromCurrentProcess(true);
617 EXPECT_TRUE(imp_token->IsMember(WellKnownSid::kWorld));
618 EXPECT_FALSE(imp_token->IsMember(WellKnownSid::kNull));
619 EXPECT_TRUE(imp_token->IsMember(imp_token->User()));
620 EXPECT_FALSE(imp_token->IsMember(*sid));
621 }
622
TEST(AccessTokenTest,Restricted)623 TEST(AccessTokenTest, Restricted) {
624 ATL::CAccessToken atl_token;
625 ASSERT_TRUE(atl_token.GetProcessToken(MAXIMUM_ALLOWED));
626 ATL::CTokenGroups disable_groups;
627 disable_groups.Add(ATL::Sids::World(), 0);
628 ATL::CTokenGroups restrict_groups;
629 restrict_groups.Add(ATL::Sids::RestrictedCode(), 0);
630 restrict_groups.Add(ATL::Sids::Users(), 0);
631 ATL::CAccessToken atl_restricted;
632 ASSERT_TRUE(atl_token.CreateRestrictedToken(&atl_restricted, disable_groups,
633 restrict_groups));
634 std::optional<AccessToken> restricted =
635 AccessToken::FromToken(atl_restricted.GetHandle());
636 ASSERT_TRUE(restricted);
637 EXPECT_TRUE(restricted->IsRestricted());
638 CompareTokens(*restricted, atl_restricted, false);
639 ATL::CSid::CSidArray sids;
640 restrict_groups.GetSidsAndAttributes(&sids);
641 ATL::CAtlArray<DWORD> attrs;
642 for (UINT index = 0; index < sids.GetCount(); ++index) {
643 attrs.Add(SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT |
644 SE_GROUP_ENABLED);
645 }
646 CompareGroups(restricted->RestrictedSids(), sids, attrs);
647 }
648
TEST(AccessTokenTest,AppContainer)649 TEST(AccessTokenTest, AppContainer) {
650 std::optional<Sid> package_sid =
651 Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-7");
652 ASSERT_TRUE(package_sid);
653 std::optional<std::vector<Sid>> caps =
654 Sid::FromKnownCapabilityVector({WellKnownCapability::kInternetClient,
655 WellKnownCapability::kDocumentsLibrary});
656 ASSERT_TRUE(caps);
657
658 CompareAppContainer(*package_sid, *caps);
659 CompareAppContainer(*package_sid, {});
660 }
661
TEST(AccessTokenTest,Anonymous)662 TEST(AccessTokenTest, Anonymous) {
663 ATL::CAccessToken atl_anon_token;
664 ASSERT_TRUE(::ImpersonateAnonymousToken(::GetCurrentThread()));
665 bool result = atl_anon_token.GetThreadToken(TOKEN_ALL_ACCESS);
666 ::RevertToSelf();
667 ASSERT_TRUE(result);
668 std::optional<AccessToken> anon_token =
669 AccessToken::FromToken(atl_anon_token.GetHandle());
670 ASSERT_TRUE(anon_token);
671 CompareTokens(*anon_token, atl_anon_token);
672 EXPECT_EQ(Sid(WellKnownSid::kAnonymous), anon_token->User());
673 std::optional<Sid> logon_sid = anon_token->LogonId();
674 EXPECT_FALSE(anon_token->LogonId());
675 EXPECT_EQ(DWORD{ERROR_NOT_FOUND}, ::GetLastError());
676 }
677
TEST(AccessTokenTest,SetDefaultDacl)678 TEST(AccessTokenTest, SetDefaultDacl) {
679 ATL::CAccessToken atl_token;
680 ASSERT_TRUE(atl_token.GetProcessToken(MAXIMUM_ALLOWED));
681 ATL::CAccessToken atl_dup_token;
682 ASSERT_TRUE(atl_token.CreatePrimaryToken(&atl_dup_token));
683 std::optional<AccessToken> read_only_token =
684 AccessToken::FromToken(atl_dup_token.GetHandle());
685 AccessControlList default_dacl;
686 Sid world_sid(WellKnownSid::kWorld);
687 ASSERT_TRUE(default_dacl.SetEntry(world_sid, SecurityAccessMode::kGrant,
688 GENERIC_ALL, 0));
689 EXPECT_FALSE(read_only_token->SetDefaultDacl(default_dacl));
690 std::optional<AccessToken> token =
691 AccessToken::FromToken(atl_dup_token.GetHandle(), TOKEN_ADJUST_DEFAULT);
692 EXPECT_TRUE(token->SetDefaultDacl(default_dacl));
693
694 CDacl atl_dacl;
695 ASSERT_TRUE(atl_dup_token.GetDefaultDacl(&atl_dacl));
696 ASSERT_EQ(atl_dacl.GetAceCount(), 1U);
697 ATL::CSid::CSidArray sids;
698 CAcl::CAccessMaskArray access;
699 CAcl::CAceTypeArray types;
700 CAcl::CAceFlagArray flags;
701 atl_dacl.GetAclEntries(&sids, &access, &types, &flags);
702 EXPECT_TRUE(EqualSid(world_sid, sids[0]));
703 EXPECT_EQ(access[0], DWORD{GENERIC_ALL});
704 EXPECT_EQ(types[0], ACCESS_ALLOWED_ACE_TYPE);
705 EXPECT_EQ(flags[0], 0U);
706 }
707
TEST(AccessTokenTest,SetIntegrityLevel)708 TEST(AccessTokenTest, SetIntegrityLevel) {
709 ATL::CAccessToken atl_token;
710 ASSERT_TRUE(atl_token.GetProcessToken(MAXIMUM_ALLOWED));
711 ATL::CAccessToken atl_dup_token;
712 ASSERT_TRUE(atl_token.CreatePrimaryToken(&atl_dup_token));
713 std::optional<AccessToken> read_only_token =
714 AccessToken::FromToken(atl_dup_token.GetHandle());
715 EXPECT_FALSE(
716 read_only_token->SetIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID));
717 std::optional<AccessToken> token =
718 AccessToken::FromToken(atl_dup_token.GetHandle(), TOKEN_ADJUST_DEFAULT);
719 EXPECT_TRUE(token->SetIntegrityLevel(SECURITY_MANDATORY_LOW_RID));
720 EXPECT_EQ(token->IntegrityLevel(), DWORD{SECURITY_MANDATORY_LOW_RID});
721 EXPECT_TRUE(token->SetIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID));
722 EXPECT_EQ(token->IntegrityLevel(), DWORD{SECURITY_MANDATORY_UNTRUSTED_RID});
723 }
724
TEST(AccessTokenTest,DuplicatePrimary)725 TEST(AccessTokenTest, DuplicatePrimary) {
726 std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
727 ASSERT_TRUE(token);
728 CheckTokenError(token->DuplicatePrimary(), ERROR_ACCESS_DENIED);
729 token = AccessToken::FromCurrentProcess(false, TOKEN_DUPLICATE);
730 ASSERT_TRUE(token);
731 std::optional<AccessToken> dup_token = token->DuplicatePrimary();
732 ASSERT_TRUE(dup_token);
733 EXPECT_FALSE(dup_token->IsImpersonation());
734 EXPECT_EQ(GetTokenAccess(*dup_token), DWORD{TOKEN_QUERY});
735 dup_token = token->DuplicatePrimary(kTokenAllNoQuery);
736 ASSERT_TRUE(dup_token);
737 EXPECT_FALSE(dup_token->IsImpersonation());
738 EXPECT_EQ(GetTokenAccess(*dup_token), DWORD{TOKEN_ALL_ACCESS});
739 }
740
TEST(AccessTokenTest,DuplicateImpersonation)741 TEST(AccessTokenTest, DuplicateImpersonation) {
742 std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
743 ASSERT_TRUE(token);
744 CheckTokenError(
745 token->DuplicateImpersonation(SecurityImpersonationLevel::kImpersonation),
746 ERROR_ACCESS_DENIED);
747 token = AccessToken::FromCurrentProcess(false, TOKEN_DUPLICATE);
748 ASSERT_TRUE(token);
749 std::optional<AccessToken> dup_token = token->DuplicateImpersonation();
750 ASSERT_TRUE(dup_token);
751 EXPECT_TRUE(dup_token->IsImpersonation());
752 EXPECT_FALSE(dup_token->IsIdentification());
753 EXPECT_EQ(dup_token->ImpersonationLevel(),
754 SecurityImpersonationLevel::kImpersonation);
755 dup_token =
756 token->DuplicateImpersonation(SecurityImpersonationLevel::kImpersonation);
757 ASSERT_TRUE(dup_token);
758 EXPECT_TRUE(dup_token->IsImpersonation());
759 EXPECT_FALSE(dup_token->IsIdentification());
760 EXPECT_EQ(dup_token->ImpersonationLevel(),
761 SecurityImpersonationLevel::kImpersonation);
762 dup_token =
763 token->DuplicateImpersonation(SecurityImpersonationLevel::kAnonymous);
764 ASSERT_TRUE(dup_token);
765 EXPECT_EQ(dup_token->ImpersonationLevel(),
766 SecurityImpersonationLevel::kAnonymous);
767 dup_token = token->DuplicateImpersonation(
768 SecurityImpersonationLevel::kIdentification);
769 ASSERT_TRUE(dup_token);
770 EXPECT_EQ(dup_token->ImpersonationLevel(),
771 SecurityImpersonationLevel::kIdentification);
772 dup_token =
773 token->DuplicateImpersonation(SecurityImpersonationLevel::kDelegation);
774 ASSERT_TRUE(dup_token);
775 EXPECT_EQ(dup_token->ImpersonationLevel(),
776 SecurityImpersonationLevel::kDelegation);
777 EXPECT_EQ(GetTokenAccess(*dup_token), DWORD{TOKEN_QUERY});
778 dup_token = token->DuplicateImpersonation(
779 SecurityImpersonationLevel::kImpersonation, kTokenAllNoQuery);
780 ASSERT_TRUE(dup_token);
781 EXPECT_TRUE(dup_token->IsImpersonation());
782 EXPECT_FALSE(dup_token->IsIdentification());
783 EXPECT_EQ(GetTokenAccess(*dup_token), DWORD{TOKEN_ALL_ACCESS});
784 dup_token = token->DuplicateImpersonation(
785 SecurityImpersonationLevel::kIdentification, TOKEN_DUPLICATE);
786 ASSERT_TRUE(dup_token);
787 CheckTokenError(dup_token->DuplicateImpersonation(
788 SecurityImpersonationLevel::kImpersonation),
789 ERROR_BAD_IMPERSONATION_LEVEL);
790 }
791
TEST(AccessTokenTest,CreateRestricted)792 TEST(AccessTokenTest, CreateRestricted) {
793 std::optional<AccessToken> primary_token = AccessToken::FromCurrentProcess();
794 ASSERT_TRUE(primary_token);
795 CheckTokenError(primary_token->CreateRestricted(0, {}, {}, {}),
796 ERROR_ACCESS_DENIED);
797 primary_token = AccessToken::FromCurrentProcess(false, TOKEN_ALL_ACCESS);
798 std::optional<AccessToken> restricted_token =
799 primary_token->CreateRestricted(DISABLE_MAX_PRIVILEGE, {}, {}, {});
800 ASSERT_TRUE(restricted_token);
801 EXPECT_FALSE(restricted_token->IsRestricted());
802 EXPECT_EQ(GetTokenAccess(*restricted_token), DWORD{TOKEN_QUERY});
803 restricted_token = primary_token->CreateRestricted(DISABLE_MAX_PRIVILEGE, {},
804 {}, {}, kTokenAllNoQuery);
805 ASSERT_TRUE(restricted_token);
806 EXPECT_EQ(GetTokenAccess(*restricted_token), DWORD{TOKEN_ALL_ACCESS});
807
808 std::vector<AccessToken::Privilege> privs = restricted_token->Privileges();
809 ASSERT_EQ(privs.size(), 1U);
810 EXPECT_EQ(privs[0].GetName(), SE_CHANGE_NOTIFY_NAME);
811 std::vector<std::wstring> priv_names = {L"ThisIsNotValid"};
812 EXPECT_FALSE(primary_token->CreateRestricted(0, {}, priv_names, {}));
813 restricted_token = primary_token->CreateRestricted(
814 0, {}, PrivilegesToNames(primary_token->Privileges()), {});
815 ASSERT_TRUE(restricted_token);
816 EXPECT_FALSE(restricted_token->IsRestricted());
817 EXPECT_TRUE(restricted_token->Privileges().empty());
818 std::vector<AccessToken::Group> groups = primary_token->Groups();
819 restricted_token =
820 primary_token->CreateRestricted(0, GroupsToSids(groups), {}, {});
821 ASSERT_TRUE(restricted_token);
822 EXPECT_FALSE(restricted_token->IsRestricted());
823 for (const AccessToken::Group& group : restricted_token->Groups()) {
824 if (!group.IsIntegrity()) {
825 EXPECT_TRUE(group.IsDenyOnly());
826 }
827 }
828 restricted_token =
829 primary_token->CreateRestricted(0, {}, {}, GroupsToSids(groups));
830 ASSERT_TRUE(restricted_token);
831 EXPECT_TRUE(restricted_token->IsRestricted());
832 std::vector<AccessToken::Group> restricted_sids =
833 restricted_token->RestrictedSids();
834 ASSERT_EQ(groups.size(), restricted_sids.size());
835 for (size_t i = 0; i < groups.size(); ++i) {
836 EXPECT_EQ(groups[i].GetSid(), restricted_sids[i].GetSid());
837 }
838 }
839
TEST(AccessTokenTest,CreateAppContainer)840 TEST(AccessTokenTest, CreateAppContainer) {
841 std::optional<AccessToken> primary_token = AccessToken::FromCurrentProcess();
842 ASSERT_TRUE(primary_token);
843 std::optional<Sid> package_sid =
844 Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-7");
845 ASSERT_TRUE(package_sid);
846 CheckTokenError(primary_token->CreateAppContainer(*package_sid, {}),
847 ERROR_ACCESS_DENIED);
848 primary_token = AccessToken::FromCurrentProcess(false, TOKEN_ALL_ACCESS);
849 std::optional<AccessToken> ac_token =
850 primary_token->CreateAppContainer(*package_sid, {});
851 ASSERT_TRUE(ac_token);
852 EXPECT_EQ(GetTokenAccess(*ac_token), DWORD{TOKEN_QUERY});
853 EXPECT_TRUE(ac_token->IsAppContainer());
854 EXPECT_EQ(ac_token->AppContainerSid(), package_sid);
855 EXPECT_EQ(ac_token->Capabilities().size(), 0U);
856 ac_token =
857 primary_token->CreateAppContainer(*package_sid, {}, kTokenAllNoQuery);
858 ASSERT_TRUE(ac_token);
859 EXPECT_TRUE(ac_token->IsAppContainer());
860 EXPECT_EQ(GetTokenAccess(*ac_token), DWORD{TOKEN_ALL_ACCESS});
861
862 std::optional<std::vector<Sid>> caps =
863 Sid::FromKnownCapabilityVector({WellKnownCapability::kInternetClient,
864 WellKnownCapability::kDocumentsLibrary});
865 ASSERT_TRUE(caps);
866 ac_token = primary_token->CreateAppContainer(*package_sid, *caps);
867 ASSERT_TRUE(ac_token);
868 EXPECT_EQ(GetTokenAccess(*ac_token), DWORD{TOKEN_QUERY});
869 EXPECT_TRUE(ac_token->IsAppContainer());
870 EXPECT_EQ(ac_token->AppContainerSid(), package_sid);
871 std::vector<AccessToken::Group> cap_groups = ac_token->Capabilities();
872 ASSERT_EQ(cap_groups.size(), caps->size());
873 for (size_t index = 0; index < cap_groups.size(); ++index) {
874 EXPECT_EQ(cap_groups[index].GetSid(), caps->at(index));
875 EXPECT_EQ(cap_groups[index].GetAttributes(), DWORD{SE_GROUP_ENABLED});
876 }
877 }
878
TEST(AccessTokenTest,SetPrivilege)879 TEST(AccessTokenTest, SetPrivilege) {
880 std::optional<AccessToken> token = AccessToken::FromCurrentProcess(true);
881 EXPECT_FALSE(token->SetPrivilege(SE_CHANGE_NOTIFY_NAME, false));
882 token = AccessToken::FromCurrentProcess(true, TOKEN_ADJUST_PRIVILEGES);
883 EXPECT_FALSE(token->SetPrivilege(L"ThisIsNotValid", false));
884 std::optional<bool> original_state =
885 token->SetPrivilege(SE_CHANGE_NOTIFY_NAME, false);
886 EXPECT_TRUE(original_state);
887 std::optional<bool> curr_state =
888 token->SetPrivilege(SE_CHANGE_NOTIFY_NAME, true);
889 EXPECT_TRUE(curr_state);
890 EXPECT_FALSE(*curr_state);
891 curr_state = token->SetPrivilege(SE_CHANGE_NOTIFY_NAME, false);
892 EXPECT_TRUE(curr_state);
893 EXPECT_TRUE(*curr_state);
894 EXPECT_TRUE(token->SetPrivilege(SE_CHANGE_NOTIFY_NAME, *original_state));
895 }
896
TEST(AccessTokenTest,RemovePrivilege)897 TEST(AccessTokenTest, RemovePrivilege) {
898 std::optional<AccessToken> token = AccessToken::FromCurrentProcess(true);
899 EXPECT_FALSE(token->RemovePrivilege(SE_CHANGE_NOTIFY_NAME));
900 token = AccessToken::FromCurrentProcess(true, TOKEN_ADJUST_PRIVILEGES);
901 EXPECT_FALSE(token->RemovePrivilege(L"ThisIsNotValid"));
902 EXPECT_TRUE(token->RemovePrivilege(SE_CHANGE_NOTIFY_NAME));
903 EXPECT_FALSE(token->RemovePrivilege(SE_CHANGE_NOTIFY_NAME));
904 }
905
TEST(AccessTokenTest,RemoveAllPrivileges)906 TEST(AccessTokenTest, RemoveAllPrivileges) {
907 std::optional<AccessToken> token = AccessToken::FromCurrentProcess(true);
908 EXPECT_FALSE(token->RemoveAllPrivileges());
909 token = AccessToken::FromCurrentProcess(true, TOKEN_ADJUST_PRIVILEGES);
910 EXPECT_TRUE(token->RemoveAllPrivileges());
911 EXPECT_EQ(token->Privileges().size(), 0U);
912 EXPECT_TRUE(token->RemoveAllPrivileges());
913 }
914
TEST(AccessTokenTest,CheckRelease)915 TEST(AccessTokenTest, CheckRelease) {
916 std::optional<AccessToken> token = AccessToken::FromCurrentProcess();
917 ASSERT_TRUE(token);
918 EXPECT_TRUE(token->is_valid());
919 ScopedHandle handle(token->release());
920 EXPECT_TRUE(handle.is_valid());
921 EXPECT_FALSE(token->is_valid());
922 EXPECT_EQ(token->get(), nullptr);
923 }
924
925 } // namespace base::win
926