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