xref: /aosp_15_r20/external/cronet/base/win/access_token_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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