xref: /aosp_15_r20/external/cronet/base/win/access_token.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 <memory>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/numerics/checked_math.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker namespace base::win {
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // The SECURITY_IMPERSONATION_LEVEL type is an enum and therefore can't be
22*6777b538SAndroid Build Coastguard Worker // forward declared in windows_types.h. Ensure our separate definition matches
23*6777b538SAndroid Build Coastguard Worker // the existing values for simplicity.
24*6777b538SAndroid Build Coastguard Worker static_assert(static_cast<int>(SecurityImpersonationLevel::kAnonymous) ==
25*6777b538SAndroid Build Coastguard Worker               SecurityAnonymous);
26*6777b538SAndroid Build Coastguard Worker static_assert(static_cast<int>(SecurityImpersonationLevel::kIdentification) ==
27*6777b538SAndroid Build Coastguard Worker               SecurityIdentification);
28*6777b538SAndroid Build Coastguard Worker static_assert(static_cast<int>(SecurityImpersonationLevel::kImpersonation) ==
29*6777b538SAndroid Build Coastguard Worker               SecurityImpersonation);
30*6777b538SAndroid Build Coastguard Worker static_assert(static_cast<int>(SecurityImpersonationLevel::kDelegation) ==
31*6777b538SAndroid Build Coastguard Worker               SecurityDelegation);
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker typedef BOOL(WINAPI* CreateAppContainerTokenFunction)(
34*6777b538SAndroid Build Coastguard Worker     HANDLE TokenHandle,
35*6777b538SAndroid Build Coastguard Worker     PSECURITY_CAPABILITIES SecurityCapabilities,
36*6777b538SAndroid Build Coastguard Worker     PHANDLE OutToken);
37*6777b538SAndroid Build Coastguard Worker 
UnwrapSid(std::optional<Sid> && sid)38*6777b538SAndroid Build Coastguard Worker Sid UnwrapSid(std::optional<Sid>&& sid) {
39*6777b538SAndroid Build Coastguard Worker   DCHECK(sid);
40*6777b538SAndroid Build Coastguard Worker   return std::move(*sid);
41*6777b538SAndroid Build Coastguard Worker }
42*6777b538SAndroid Build Coastguard Worker 
GetTokenInfo(HANDLE token,TOKEN_INFORMATION_CLASS info_class)43*6777b538SAndroid Build Coastguard Worker std::optional<std::vector<char>> GetTokenInfo(
44*6777b538SAndroid Build Coastguard Worker     HANDLE token,
45*6777b538SAndroid Build Coastguard Worker     TOKEN_INFORMATION_CLASS info_class) {
46*6777b538SAndroid Build Coastguard Worker   // Get the buffer size. The call to GetTokenInformation should never succeed.
47*6777b538SAndroid Build Coastguard Worker   DWORD size = 0;
48*6777b538SAndroid Build Coastguard Worker   if (::GetTokenInformation(token, info_class, nullptr, 0, &size) || !size)
49*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   std::vector<char> temp_buffer(size);
52*6777b538SAndroid Build Coastguard Worker   if (!::GetTokenInformation(token, info_class, temp_buffer.data(), size,
53*6777b538SAndroid Build Coastguard Worker                              &size)) {
54*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
55*6777b538SAndroid Build Coastguard Worker   }
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   return std::move(temp_buffer);
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker template <typename T>
GetTokenInfoFixed(HANDLE token,TOKEN_INFORMATION_CLASS info_class)61*6777b538SAndroid Build Coastguard Worker std::optional<T> GetTokenInfoFixed(HANDLE token,
62*6777b538SAndroid Build Coastguard Worker                                    TOKEN_INFORMATION_CLASS info_class) {
63*6777b538SAndroid Build Coastguard Worker   T result;
64*6777b538SAndroid Build Coastguard Worker   DWORD size = sizeof(T);
65*6777b538SAndroid Build Coastguard Worker   if (!::GetTokenInformation(token, info_class, &result, size, &size))
66*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   return result;
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker template <typename T>
GetType(std::optional<std::vector<char>> & info)72*6777b538SAndroid Build Coastguard Worker T* GetType(std::optional<std::vector<char>>& info) {
73*6777b538SAndroid Build Coastguard Worker   DCHECK(info);
74*6777b538SAndroid Build Coastguard Worker   DCHECK(info->size() >= sizeof(T));
75*6777b538SAndroid Build Coastguard Worker   return reinterpret_cast<T*>(info->data());
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker 
GetGroupsFromToken(HANDLE token,TOKEN_INFORMATION_CLASS info_class)78*6777b538SAndroid Build Coastguard Worker std::vector<AccessToken::Group> GetGroupsFromToken(
79*6777b538SAndroid Build Coastguard Worker     HANDLE token,
80*6777b538SAndroid Build Coastguard Worker     TOKEN_INFORMATION_CLASS info_class) {
81*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> groups = GetTokenInfo(token, info_class);
82*6777b538SAndroid Build Coastguard Worker   // Sometimes only the GroupCount field is returned which indicates an empty
83*6777b538SAndroid Build Coastguard Worker   // group set. If the buffer is smaller than the TOKEN_GROUPS structure then
84*6777b538SAndroid Build Coastguard Worker   // just return an empty vector.
85*6777b538SAndroid Build Coastguard Worker   if (!groups || (groups->size() < sizeof(TOKEN_GROUPS)))
86*6777b538SAndroid Build Coastguard Worker     return {};
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   TOKEN_GROUPS* groups_ptr = GetType<TOKEN_GROUPS>(groups);
89*6777b538SAndroid Build Coastguard Worker   std::vector<AccessToken::Group> ret;
90*6777b538SAndroid Build Coastguard Worker   ret.reserve(groups_ptr->GroupCount);
91*6777b538SAndroid Build Coastguard Worker   for (DWORD index = 0; index < groups_ptr->GroupCount; ++index) {
92*6777b538SAndroid Build Coastguard Worker     ret.emplace_back(UnwrapSid(Sid::FromPSID(groups_ptr->Groups[index].Sid)),
93*6777b538SAndroid Build Coastguard Worker                      groups_ptr->Groups[index].Attributes);
94*6777b538SAndroid Build Coastguard Worker   }
95*6777b538SAndroid Build Coastguard Worker   return ret;
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker 
GetTokenStatistics(HANDLE token)98*6777b538SAndroid Build Coastguard Worker TOKEN_STATISTICS GetTokenStatistics(HANDLE token) {
99*6777b538SAndroid Build Coastguard Worker   std::optional<TOKEN_STATISTICS> value =
100*6777b538SAndroid Build Coastguard Worker       GetTokenInfoFixed<TOKEN_STATISTICS>(token, TokenStatistics);
101*6777b538SAndroid Build Coastguard Worker   if (!value)
102*6777b538SAndroid Build Coastguard Worker     return {};
103*6777b538SAndroid Build Coastguard Worker   return *value;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker 
ConvertLuid(const LUID & luid)106*6777b538SAndroid Build Coastguard Worker CHROME_LUID ConvertLuid(const LUID& luid) {
107*6777b538SAndroid Build Coastguard Worker   CHROME_LUID ret;
108*6777b538SAndroid Build Coastguard Worker   ret.LowPart = luid.LowPart;
109*6777b538SAndroid Build Coastguard Worker   ret.HighPart = luid.HighPart;
110*6777b538SAndroid Build Coastguard Worker   return ret;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
DuplicateToken(HANDLE token,ACCESS_MASK desired_access,SECURITY_IMPERSONATION_LEVEL imp_level,TOKEN_TYPE type)113*6777b538SAndroid Build Coastguard Worker HANDLE DuplicateToken(HANDLE token,
114*6777b538SAndroid Build Coastguard Worker                       ACCESS_MASK desired_access,
115*6777b538SAndroid Build Coastguard Worker                       SECURITY_IMPERSONATION_LEVEL imp_level,
116*6777b538SAndroid Build Coastguard Worker                       TOKEN_TYPE type) {
117*6777b538SAndroid Build Coastguard Worker   HANDLE new_token;
118*6777b538SAndroid Build Coastguard Worker   if (!::DuplicateTokenEx(token, TOKEN_QUERY | desired_access, nullptr,
119*6777b538SAndroid Build Coastguard Worker                           imp_level, type, &new_token)) {
120*6777b538SAndroid Build Coastguard Worker     return nullptr;
121*6777b538SAndroid Build Coastguard Worker   }
122*6777b538SAndroid Build Coastguard Worker   return new_token;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
ConvertSids(const std::vector<Sid> & sids,DWORD attributes)125*6777b538SAndroid Build Coastguard Worker std::vector<SID_AND_ATTRIBUTES> ConvertSids(const std::vector<Sid>& sids,
126*6777b538SAndroid Build Coastguard Worker                                             DWORD attributes) {
127*6777b538SAndroid Build Coastguard Worker   std::vector<SID_AND_ATTRIBUTES> ret;
128*6777b538SAndroid Build Coastguard Worker   ret.reserve(sids.size());
129*6777b538SAndroid Build Coastguard Worker   for (const Sid& sid : sids) {
130*6777b538SAndroid Build Coastguard Worker     SID_AND_ATTRIBUTES entry = {};
131*6777b538SAndroid Build Coastguard Worker     entry.Sid = sid.GetPSID();
132*6777b538SAndroid Build Coastguard Worker     entry.Attributes = attributes;
133*6777b538SAndroid Build Coastguard Worker     ret.push_back(entry);
134*6777b538SAndroid Build Coastguard Worker   }
135*6777b538SAndroid Build Coastguard Worker   return ret;
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker 
LookupPrivilege(const std::wstring & name)138*6777b538SAndroid Build Coastguard Worker std::optional<LUID> LookupPrivilege(const std::wstring& name) {
139*6777b538SAndroid Build Coastguard Worker   LUID luid;
140*6777b538SAndroid Build Coastguard Worker   if (!::LookupPrivilegeValue(nullptr, name.c_str(), &luid)) {
141*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker   return luid;
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker 
ConvertPrivileges(const std::vector<std::wstring> & privs,DWORD attributes)146*6777b538SAndroid Build Coastguard Worker std::vector<LUID_AND_ATTRIBUTES> ConvertPrivileges(
147*6777b538SAndroid Build Coastguard Worker     const std::vector<std::wstring>& privs,
148*6777b538SAndroid Build Coastguard Worker     DWORD attributes) {
149*6777b538SAndroid Build Coastguard Worker   std::vector<LUID_AND_ATTRIBUTES> ret;
150*6777b538SAndroid Build Coastguard Worker   ret.reserve(privs.size());
151*6777b538SAndroid Build Coastguard Worker   for (const std::wstring& priv : privs) {
152*6777b538SAndroid Build Coastguard Worker     std::optional<LUID> luid = LookupPrivilege(priv);
153*6777b538SAndroid Build Coastguard Worker     if (!luid) {
154*6777b538SAndroid Build Coastguard Worker       return {};
155*6777b538SAndroid Build Coastguard Worker     }
156*6777b538SAndroid Build Coastguard Worker     LUID_AND_ATTRIBUTES entry = {};
157*6777b538SAndroid Build Coastguard Worker     entry.Luid = *luid;
158*6777b538SAndroid Build Coastguard Worker     entry.Attributes = attributes;
159*6777b538SAndroid Build Coastguard Worker     ret.push_back(entry);
160*6777b538SAndroid Build Coastguard Worker   }
161*6777b538SAndroid Build Coastguard Worker   return ret;
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker template <typename T>
GetPointer(std::vector<T> & values)165*6777b538SAndroid Build Coastguard Worker T* GetPointer(std::vector<T>& values) {
166*6777b538SAndroid Build Coastguard Worker   if (values.empty()) {
167*6777b538SAndroid Build Coastguard Worker     return nullptr;
168*6777b538SAndroid Build Coastguard Worker   }
169*6777b538SAndroid Build Coastguard Worker   return values.data();
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker template <typename T>
Set(const ScopedHandle & token,TOKEN_INFORMATION_CLASS info_class,T & value)173*6777b538SAndroid Build Coastguard Worker bool Set(const ScopedHandle& token,
174*6777b538SAndroid Build Coastguard Worker          TOKEN_INFORMATION_CLASS info_class,
175*6777b538SAndroid Build Coastguard Worker          T& value) {
176*6777b538SAndroid Build Coastguard Worker   return !!::SetTokenInformation(token.get(), info_class, &value,
177*6777b538SAndroid Build Coastguard Worker                                  sizeof(value));
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker 
AdjustPrivilege(const ScopedHandle & token,const std::wstring & priv,DWORD attributes)180*6777b538SAndroid Build Coastguard Worker std::optional<DWORD> AdjustPrivilege(const ScopedHandle& token,
181*6777b538SAndroid Build Coastguard Worker                                      const std::wstring& priv,
182*6777b538SAndroid Build Coastguard Worker                                      DWORD attributes) {
183*6777b538SAndroid Build Coastguard Worker   TOKEN_PRIVILEGES token_privs = {};
184*6777b538SAndroid Build Coastguard Worker   token_privs.PrivilegeCount = 1;
185*6777b538SAndroid Build Coastguard Worker   std::optional<LUID> luid = LookupPrivilege(priv);
186*6777b538SAndroid Build Coastguard Worker   if (!luid) {
187*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
188*6777b538SAndroid Build Coastguard Worker   }
189*6777b538SAndroid Build Coastguard Worker   token_privs.Privileges[0].Luid = *luid;
190*6777b538SAndroid Build Coastguard Worker   token_privs.Privileges[0].Attributes = attributes;
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker   TOKEN_PRIVILEGES out_privs = {};
193*6777b538SAndroid Build Coastguard Worker   DWORD out_length = 0;
194*6777b538SAndroid Build Coastguard Worker   if (!::AdjustTokenPrivileges(token.get(), FALSE, &token_privs,
195*6777b538SAndroid Build Coastguard Worker                                sizeof(out_privs), &out_privs, &out_length)) {
196*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
197*6777b538SAndroid Build Coastguard Worker   }
198*6777b538SAndroid Build Coastguard Worker   if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
199*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
200*6777b538SAndroid Build Coastguard Worker   }
201*6777b538SAndroid Build Coastguard Worker   if (out_privs.PrivilegeCount == 1) {
202*6777b538SAndroid Build Coastguard Worker     return out_privs.Privileges[0].Attributes;
203*6777b538SAndroid Build Coastguard Worker   }
204*6777b538SAndroid Build Coastguard Worker   return attributes;
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker }  // namespace
207*6777b538SAndroid Build Coastguard Worker 
IsIntegrity() const208*6777b538SAndroid Build Coastguard Worker bool AccessToken::Group::IsIntegrity() const {
209*6777b538SAndroid Build Coastguard Worker   return !!(attributes_ & SE_GROUP_INTEGRITY);
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker 
IsEnabled() const212*6777b538SAndroid Build Coastguard Worker bool AccessToken::Group::IsEnabled() const {
213*6777b538SAndroid Build Coastguard Worker   return !!(attributes_ & SE_GROUP_ENABLED);
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker 
IsDenyOnly() const216*6777b538SAndroid Build Coastguard Worker bool AccessToken::Group::IsDenyOnly() const {
217*6777b538SAndroid Build Coastguard Worker   return !!(attributes_ & SE_GROUP_USE_FOR_DENY_ONLY);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
IsLogonId() const220*6777b538SAndroid Build Coastguard Worker bool AccessToken::Group::IsLogonId() const {
221*6777b538SAndroid Build Coastguard Worker   return (attributes_ & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID;
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker 
Group(Sid && sid,DWORD attributes)224*6777b538SAndroid Build Coastguard Worker AccessToken::Group::Group(Sid&& sid, DWORD attributes)
225*6777b538SAndroid Build Coastguard Worker     : sid_(std::move(sid)), attributes_(attributes) {}
226*6777b538SAndroid Build Coastguard Worker AccessToken::Group::Group(Group&&) = default;
227*6777b538SAndroid Build Coastguard Worker AccessToken::Group::Group::~Group() = default;
228*6777b538SAndroid Build Coastguard Worker 
GetName() const229*6777b538SAndroid Build Coastguard Worker std::wstring AccessToken::Privilege::GetName() const {
230*6777b538SAndroid Build Coastguard Worker   WCHAR name[128];
231*6777b538SAndroid Build Coastguard Worker   LUID luid;
232*6777b538SAndroid Build Coastguard Worker   luid.LowPart = luid_.LowPart;
233*6777b538SAndroid Build Coastguard Worker   luid.HighPart = luid_.HighPart;
234*6777b538SAndroid Build Coastguard Worker   DWORD size = std::size(name);
235*6777b538SAndroid Build Coastguard Worker   return ::LookupPrivilegeName(nullptr, &luid, name, &size)
236*6777b538SAndroid Build Coastguard Worker              ? name
237*6777b538SAndroid Build Coastguard Worker              : ASCIIToWide(
238*6777b538SAndroid Build Coastguard Worker                    StringPrintf("%08lX-%08lX", luid.HighPart, luid.LowPart));
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker 
IsEnabled() const241*6777b538SAndroid Build Coastguard Worker bool AccessToken::Privilege::IsEnabled() const {
242*6777b538SAndroid Build Coastguard Worker   return !!(attributes_ & SE_PRIVILEGE_ENABLED);
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker 
Privilege(CHROME_LUID luid,DWORD attributes)245*6777b538SAndroid Build Coastguard Worker AccessToken::Privilege::Privilege(CHROME_LUID luid, DWORD attributes)
246*6777b538SAndroid Build Coastguard Worker     : luid_(luid), attributes_(attributes) {}
247*6777b538SAndroid Build Coastguard Worker 
FromToken(HANDLE token,ACCESS_MASK desired_access)248*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromToken(HANDLE token,
249*6777b538SAndroid Build Coastguard Worker                                                   ACCESS_MASK desired_access) {
250*6777b538SAndroid Build Coastguard Worker   HANDLE new_token;
251*6777b538SAndroid Build Coastguard Worker   if (!::DuplicateHandle(::GetCurrentProcess(), token, ::GetCurrentProcess(),
252*6777b538SAndroid Build Coastguard Worker                          &new_token, TOKEN_QUERY | desired_access, FALSE, 0)) {
253*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
254*6777b538SAndroid Build Coastguard Worker   }
255*6777b538SAndroid Build Coastguard Worker   return AccessToken(new_token);
256*6777b538SAndroid Build Coastguard Worker }
257*6777b538SAndroid Build Coastguard Worker 
FromToken(ScopedHandle && token)258*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromToken(ScopedHandle&& token) {
259*6777b538SAndroid Build Coastguard Worker   if (!token.is_valid()) {
260*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_INVALID_HANDLE);
261*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
262*6777b538SAndroid Build Coastguard Worker   }
263*6777b538SAndroid Build Coastguard Worker   if (!GetTokenInfoFixed<TOKEN_STATISTICS>(token.get(), TokenStatistics)) {
264*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
265*6777b538SAndroid Build Coastguard Worker   }
266*6777b538SAndroid Build Coastguard Worker   return AccessToken(token.release());
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker 
FromProcess(HANDLE process,bool impersonation,ACCESS_MASK desired_access)269*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromProcess(
270*6777b538SAndroid Build Coastguard Worker     HANDLE process,
271*6777b538SAndroid Build Coastguard Worker     bool impersonation,
272*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) {
273*6777b538SAndroid Build Coastguard Worker   HANDLE token = nullptr;
274*6777b538SAndroid Build Coastguard Worker   if (impersonation) {
275*6777b538SAndroid Build Coastguard Worker     if (!::OpenProcessToken(process, TOKEN_DUPLICATE, &token))
276*6777b538SAndroid Build Coastguard Worker       return std::nullopt;
277*6777b538SAndroid Build Coastguard Worker     ScopedHandle primary_token(token);
278*6777b538SAndroid Build Coastguard Worker     token = DuplicateToken(primary_token.get(), desired_access,
279*6777b538SAndroid Build Coastguard Worker                            SecurityIdentification, TokenImpersonation);
280*6777b538SAndroid Build Coastguard Worker     if (!token) {
281*6777b538SAndroid Build Coastguard Worker       return std::nullopt;
282*6777b538SAndroid Build Coastguard Worker     }
283*6777b538SAndroid Build Coastguard Worker   } else {
284*6777b538SAndroid Build Coastguard Worker     if (!::OpenProcessToken(process, TOKEN_QUERY | desired_access, &token))
285*6777b538SAndroid Build Coastguard Worker       return std::nullopt;
286*6777b538SAndroid Build Coastguard Worker   }
287*6777b538SAndroid Build Coastguard Worker   return AccessToken(token);
288*6777b538SAndroid Build Coastguard Worker }
289*6777b538SAndroid Build Coastguard Worker 
FromCurrentProcess(bool impersonation,ACCESS_MASK desired_access)290*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromCurrentProcess(
291*6777b538SAndroid Build Coastguard Worker     bool impersonation,
292*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) {
293*6777b538SAndroid Build Coastguard Worker   return FromProcess(::GetCurrentProcess(), impersonation, desired_access);
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker 
FromThread(HANDLE thread,bool open_as_self,ACCESS_MASK desired_access)296*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromThread(HANDLE thread,
297*6777b538SAndroid Build Coastguard Worker                                                    bool open_as_self,
298*6777b538SAndroid Build Coastguard Worker                                                    ACCESS_MASK desired_access) {
299*6777b538SAndroid Build Coastguard Worker   HANDLE token;
300*6777b538SAndroid Build Coastguard Worker   if (!::OpenThreadToken(thread, TOKEN_QUERY | desired_access, open_as_self,
301*6777b538SAndroid Build Coastguard Worker                          &token))
302*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
303*6777b538SAndroid Build Coastguard Worker   return AccessToken(token);
304*6777b538SAndroid Build Coastguard Worker }
305*6777b538SAndroid Build Coastguard Worker 
FromCurrentThread(bool open_as_self,ACCESS_MASK desired_access)306*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromCurrentThread(
307*6777b538SAndroid Build Coastguard Worker     bool open_as_self,
308*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) {
309*6777b538SAndroid Build Coastguard Worker   return FromThread(::GetCurrentThread(), open_as_self, desired_access);
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker 
FromEffective(ACCESS_MASK desired_access)312*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::FromEffective(
313*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) {
314*6777b538SAndroid Build Coastguard Worker   std::optional<AccessToken> token = FromCurrentThread(true, desired_access);
315*6777b538SAndroid Build Coastguard Worker   if (token)
316*6777b538SAndroid Build Coastguard Worker     return token;
317*6777b538SAndroid Build Coastguard Worker   if (::GetLastError() != ERROR_NO_TOKEN)
318*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
319*6777b538SAndroid Build Coastguard Worker   return FromCurrentProcess(false, desired_access);
320*6777b538SAndroid Build Coastguard Worker }
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker AccessToken::AccessToken(AccessToken&&) = default;
323*6777b538SAndroid Build Coastguard Worker AccessToken& AccessToken::operator=(AccessToken&&) = default;
324*6777b538SAndroid Build Coastguard Worker AccessToken::~AccessToken() = default;
325*6777b538SAndroid Build Coastguard Worker 
User() const326*6777b538SAndroid Build Coastguard Worker Sid AccessToken::User() const {
327*6777b538SAndroid Build Coastguard Worker   return UserGroup().GetSid().Clone();
328*6777b538SAndroid Build Coastguard Worker }
329*6777b538SAndroid Build Coastguard Worker 
UserGroup() const330*6777b538SAndroid Build Coastguard Worker AccessToken::Group AccessToken::UserGroup() const {
331*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> buffer =
332*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenUser);
333*6777b538SAndroid Build Coastguard Worker   SID_AND_ATTRIBUTES& user = GetType<TOKEN_USER>(buffer)->User;
334*6777b538SAndroid Build Coastguard Worker   return {UnwrapSid(Sid::FromPSID(user.Sid)), user.Attributes};
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker 
Owner() const337*6777b538SAndroid Build Coastguard Worker Sid AccessToken::Owner() const {
338*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> buffer =
339*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenOwner);
340*6777b538SAndroid Build Coastguard Worker   return UnwrapSid(Sid::FromPSID(GetType<TOKEN_OWNER>(buffer)->Owner));
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker 
PrimaryGroup() const343*6777b538SAndroid Build Coastguard Worker Sid AccessToken::PrimaryGroup() const {
344*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> buffer =
345*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenPrimaryGroup);
346*6777b538SAndroid Build Coastguard Worker   return UnwrapSid(
347*6777b538SAndroid Build Coastguard Worker       Sid::FromPSID(GetType<TOKEN_PRIMARY_GROUP>(buffer)->PrimaryGroup));
348*6777b538SAndroid Build Coastguard Worker }
349*6777b538SAndroid Build Coastguard Worker 
LogonId() const350*6777b538SAndroid Build Coastguard Worker std::optional<Sid> AccessToken::LogonId() const {
351*6777b538SAndroid Build Coastguard Worker   std::vector<AccessToken::Group> groups =
352*6777b538SAndroid Build Coastguard Worker       GetGroupsFromToken(token_.get(), TokenLogonSid);
353*6777b538SAndroid Build Coastguard Worker   for (const AccessToken::Group& group : groups) {
354*6777b538SAndroid Build Coastguard Worker     if (group.IsLogonId())
355*6777b538SAndroid Build Coastguard Worker       return group.GetSid().Clone();
356*6777b538SAndroid Build Coastguard Worker   }
357*6777b538SAndroid Build Coastguard Worker   return std::nullopt;
358*6777b538SAndroid Build Coastguard Worker }
359*6777b538SAndroid Build Coastguard Worker 
IntegrityLevel() const360*6777b538SAndroid Build Coastguard Worker DWORD AccessToken::IntegrityLevel() const {
361*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> buffer =
362*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenIntegrityLevel);
363*6777b538SAndroid Build Coastguard Worker   if (!buffer)
364*6777b538SAndroid Build Coastguard Worker     return MAXDWORD;
365*6777b538SAndroid Build Coastguard Worker 
366*6777b538SAndroid Build Coastguard Worker   PSID il_sid = GetType<TOKEN_MANDATORY_LABEL>(buffer)->Label.Sid;
367*6777b538SAndroid Build Coastguard Worker   return *::GetSidSubAuthority(
368*6777b538SAndroid Build Coastguard Worker       il_sid, static_cast<DWORD>(*::GetSidSubAuthorityCount(il_sid) - 1));
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker 
SetIntegrityLevel(DWORD integrity_level)371*6777b538SAndroid Build Coastguard Worker bool AccessToken::SetIntegrityLevel(DWORD integrity_level) {
372*6777b538SAndroid Build Coastguard Worker   std::optional<base::win::Sid> sid = Sid::FromIntegrityLevel(integrity_level);
373*6777b538SAndroid Build Coastguard Worker   if (!sid) {
374*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_INVALID_SID);
375*6777b538SAndroid Build Coastguard Worker     return false;
376*6777b538SAndroid Build Coastguard Worker   }
377*6777b538SAndroid Build Coastguard Worker 
378*6777b538SAndroid Build Coastguard Worker   TOKEN_MANDATORY_LABEL label = {};
379*6777b538SAndroid Build Coastguard Worker   label.Label.Attributes = SE_GROUP_INTEGRITY;
380*6777b538SAndroid Build Coastguard Worker   label.Label.Sid = sid->GetPSID();
381*6777b538SAndroid Build Coastguard Worker   return Set(token_, TokenIntegrityLevel, label);
382*6777b538SAndroid Build Coastguard Worker }
383*6777b538SAndroid Build Coastguard Worker 
SessionId() const384*6777b538SAndroid Build Coastguard Worker DWORD AccessToken::SessionId() const {
385*6777b538SAndroid Build Coastguard Worker   std::optional<DWORD> value =
386*6777b538SAndroid Build Coastguard Worker       GetTokenInfoFixed<DWORD>(token_.get(), TokenSessionId);
387*6777b538SAndroid Build Coastguard Worker   if (!value)
388*6777b538SAndroid Build Coastguard Worker     return MAXDWORD;
389*6777b538SAndroid Build Coastguard Worker   return *value;
390*6777b538SAndroid Build Coastguard Worker }
391*6777b538SAndroid Build Coastguard Worker 
Groups() const392*6777b538SAndroid Build Coastguard Worker std::vector<AccessToken::Group> AccessToken::Groups() const {
393*6777b538SAndroid Build Coastguard Worker   return GetGroupsFromToken(token_.get(), TokenGroups);
394*6777b538SAndroid Build Coastguard Worker }
395*6777b538SAndroid Build Coastguard Worker 
IsRestricted() const396*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsRestricted() const {
397*6777b538SAndroid Build Coastguard Worker   return !!::IsTokenRestricted(token_.get());
398*6777b538SAndroid Build Coastguard Worker }
399*6777b538SAndroid Build Coastguard Worker 
RestrictedSids() const400*6777b538SAndroid Build Coastguard Worker std::vector<AccessToken::Group> AccessToken::RestrictedSids() const {
401*6777b538SAndroid Build Coastguard Worker   return GetGroupsFromToken(token_.get(), TokenRestrictedSids);
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker 
IsAppContainer() const404*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsAppContainer() const {
405*6777b538SAndroid Build Coastguard Worker   std::optional<DWORD> value =
406*6777b538SAndroid Build Coastguard Worker       GetTokenInfoFixed<DWORD>(token_.get(), TokenIsAppContainer);
407*6777b538SAndroid Build Coastguard Worker   if (!value)
408*6777b538SAndroid Build Coastguard Worker     return false;
409*6777b538SAndroid Build Coastguard Worker   return !!*value;
410*6777b538SAndroid Build Coastguard Worker }
411*6777b538SAndroid Build Coastguard Worker 
AppContainerSid() const412*6777b538SAndroid Build Coastguard Worker std::optional<Sid> AccessToken::AppContainerSid() const {
413*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> buffer =
414*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenAppContainerSid);
415*6777b538SAndroid Build Coastguard Worker   if (!buffer)
416*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
417*6777b538SAndroid Build Coastguard Worker 
418*6777b538SAndroid Build Coastguard Worker   TOKEN_APPCONTAINER_INFORMATION* info =
419*6777b538SAndroid Build Coastguard Worker       GetType<TOKEN_APPCONTAINER_INFORMATION>(buffer);
420*6777b538SAndroid Build Coastguard Worker   if (!info->TokenAppContainer)
421*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
422*6777b538SAndroid Build Coastguard Worker   return Sid::FromPSID(info->TokenAppContainer);
423*6777b538SAndroid Build Coastguard Worker }
424*6777b538SAndroid Build Coastguard Worker 
Capabilities() const425*6777b538SAndroid Build Coastguard Worker std::vector<AccessToken::Group> AccessToken::Capabilities() const {
426*6777b538SAndroid Build Coastguard Worker   return GetGroupsFromToken(token_.get(), TokenCapabilities);
427*6777b538SAndroid Build Coastguard Worker }
428*6777b538SAndroid Build Coastguard Worker 
LinkedToken() const429*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::LinkedToken() const {
430*6777b538SAndroid Build Coastguard Worker   std::optional<TOKEN_LINKED_TOKEN> value =
431*6777b538SAndroid Build Coastguard Worker       GetTokenInfoFixed<TOKEN_LINKED_TOKEN>(token_.get(), TokenLinkedToken);
432*6777b538SAndroid Build Coastguard Worker   if (!value)
433*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
434*6777b538SAndroid Build Coastguard Worker   return AccessToken(value->LinkedToken);
435*6777b538SAndroid Build Coastguard Worker }
436*6777b538SAndroid Build Coastguard Worker 
DefaultDacl() const437*6777b538SAndroid Build Coastguard Worker std::optional<AccessControlList> AccessToken::DefaultDacl() const {
438*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> dacl_buffer =
439*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenDefaultDacl);
440*6777b538SAndroid Build Coastguard Worker   if (!dacl_buffer)
441*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
442*6777b538SAndroid Build Coastguard Worker   TOKEN_DEFAULT_DACL* dacl_ptr = GetType<TOKEN_DEFAULT_DACL>(dacl_buffer);
443*6777b538SAndroid Build Coastguard Worker   return AccessControlList::FromPACL(dacl_ptr->DefaultDacl);
444*6777b538SAndroid Build Coastguard Worker }
445*6777b538SAndroid Build Coastguard Worker 
SetDefaultDacl(const AccessControlList & default_dacl)446*6777b538SAndroid Build Coastguard Worker bool AccessToken::SetDefaultDacl(const AccessControlList& default_dacl) {
447*6777b538SAndroid Build Coastguard Worker   TOKEN_DEFAULT_DACL set_default_dacl = {};
448*6777b538SAndroid Build Coastguard Worker   set_default_dacl.DefaultDacl = default_dacl.get();
449*6777b538SAndroid Build Coastguard Worker   return Set(token_, TokenDefaultDacl, set_default_dacl);
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker 
Id() const452*6777b538SAndroid Build Coastguard Worker CHROME_LUID AccessToken::Id() const {
453*6777b538SAndroid Build Coastguard Worker   return ConvertLuid(GetTokenStatistics(token_.get()).TokenId);
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker 
AuthenticationId() const456*6777b538SAndroid Build Coastguard Worker CHROME_LUID AccessToken::AuthenticationId() const {
457*6777b538SAndroid Build Coastguard Worker   return ConvertLuid(GetTokenStatistics(token_.get()).AuthenticationId);
458*6777b538SAndroid Build Coastguard Worker }
459*6777b538SAndroid Build Coastguard Worker 
Privileges() const460*6777b538SAndroid Build Coastguard Worker std::vector<AccessToken::Privilege> AccessToken::Privileges() const {
461*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> privileges =
462*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenPrivileges);
463*6777b538SAndroid Build Coastguard Worker   if (!privileges)
464*6777b538SAndroid Build Coastguard Worker     return {};
465*6777b538SAndroid Build Coastguard Worker   TOKEN_PRIVILEGES* privileges_ptr = GetType<TOKEN_PRIVILEGES>(privileges);
466*6777b538SAndroid Build Coastguard Worker   std::vector<AccessToken::Privilege> ret;
467*6777b538SAndroid Build Coastguard Worker   ret.reserve(privileges_ptr->PrivilegeCount);
468*6777b538SAndroid Build Coastguard Worker   for (DWORD index = 0; index < privileges_ptr->PrivilegeCount; ++index) {
469*6777b538SAndroid Build Coastguard Worker     ret.emplace_back(ConvertLuid(privileges_ptr->Privileges[index].Luid),
470*6777b538SAndroid Build Coastguard Worker                      privileges_ptr->Privileges[index].Attributes);
471*6777b538SAndroid Build Coastguard Worker   }
472*6777b538SAndroid Build Coastguard Worker   return ret;
473*6777b538SAndroid Build Coastguard Worker }
474*6777b538SAndroid Build Coastguard Worker 
IsElevated() const475*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsElevated() const {
476*6777b538SAndroid Build Coastguard Worker   std::optional<TOKEN_ELEVATION> value =
477*6777b538SAndroid Build Coastguard Worker       GetTokenInfoFixed<TOKEN_ELEVATION>(token_.get(), TokenElevation);
478*6777b538SAndroid Build Coastguard Worker   if (!value)
479*6777b538SAndroid Build Coastguard Worker     return false;
480*6777b538SAndroid Build Coastguard Worker   return !!value->TokenIsElevated;
481*6777b538SAndroid Build Coastguard Worker }
482*6777b538SAndroid Build Coastguard Worker 
IsMember(const Sid & sid) const483*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsMember(const Sid& sid) const {
484*6777b538SAndroid Build Coastguard Worker   BOOL is_member = FALSE;
485*6777b538SAndroid Build Coastguard Worker   return ::CheckTokenMembership(token_.get(), sid.GetPSID(), &is_member) &&
486*6777b538SAndroid Build Coastguard Worker          !!is_member;
487*6777b538SAndroid Build Coastguard Worker }
488*6777b538SAndroid Build Coastguard Worker 
IsMember(WellKnownSid known_sid) const489*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsMember(WellKnownSid known_sid) const {
490*6777b538SAndroid Build Coastguard Worker   return IsMember(Sid(known_sid));
491*6777b538SAndroid Build Coastguard Worker }
492*6777b538SAndroid Build Coastguard Worker 
IsImpersonation() const493*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsImpersonation() const {
494*6777b538SAndroid Build Coastguard Worker   return GetTokenStatistics(token_.get()).TokenType == TokenImpersonation;
495*6777b538SAndroid Build Coastguard Worker }
496*6777b538SAndroid Build Coastguard Worker 
IsIdentification() const497*6777b538SAndroid Build Coastguard Worker bool AccessToken::IsIdentification() const {
498*6777b538SAndroid Build Coastguard Worker   return ImpersonationLevel() < SecurityImpersonationLevel::kImpersonation;
499*6777b538SAndroid Build Coastguard Worker }
500*6777b538SAndroid Build Coastguard Worker 
ImpersonationLevel() const501*6777b538SAndroid Build Coastguard Worker SecurityImpersonationLevel AccessToken::ImpersonationLevel() const {
502*6777b538SAndroid Build Coastguard Worker   TOKEN_STATISTICS stats = GetTokenStatistics(token_.get());
503*6777b538SAndroid Build Coastguard Worker   if (stats.TokenType != TokenImpersonation) {
504*6777b538SAndroid Build Coastguard Worker     return SecurityImpersonationLevel::kImpersonation;
505*6777b538SAndroid Build Coastguard Worker   }
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker   return static_cast<SecurityImpersonationLevel>(
508*6777b538SAndroid Build Coastguard Worker       GetTokenStatistics(token_.get()).ImpersonationLevel);
509*6777b538SAndroid Build Coastguard Worker }
510*6777b538SAndroid Build Coastguard Worker 
DuplicatePrimary(ACCESS_MASK desired_access) const511*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::DuplicatePrimary(
512*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) const {
513*6777b538SAndroid Build Coastguard Worker   HANDLE token = DuplicateToken(token_.get(), desired_access, SecurityAnonymous,
514*6777b538SAndroid Build Coastguard Worker                                 TokenPrimary);
515*6777b538SAndroid Build Coastguard Worker   if (!token) {
516*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
517*6777b538SAndroid Build Coastguard Worker   }
518*6777b538SAndroid Build Coastguard Worker   return AccessToken{token};
519*6777b538SAndroid Build Coastguard Worker }
520*6777b538SAndroid Build Coastguard Worker 
DuplicateImpersonation(SecurityImpersonationLevel impersonation_level,ACCESS_MASK desired_access) const521*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::DuplicateImpersonation(
522*6777b538SAndroid Build Coastguard Worker     SecurityImpersonationLevel impersonation_level,
523*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) const {
524*6777b538SAndroid Build Coastguard Worker   HANDLE token = DuplicateToken(
525*6777b538SAndroid Build Coastguard Worker       token_.get(), desired_access,
526*6777b538SAndroid Build Coastguard Worker       static_cast<SECURITY_IMPERSONATION_LEVEL>(impersonation_level),
527*6777b538SAndroid Build Coastguard Worker       TokenImpersonation);
528*6777b538SAndroid Build Coastguard Worker   if (!token) {
529*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
530*6777b538SAndroid Build Coastguard Worker   }
531*6777b538SAndroid Build Coastguard Worker   return AccessToken(token);
532*6777b538SAndroid Build Coastguard Worker }
533*6777b538SAndroid Build Coastguard Worker 
CreateRestricted(DWORD flags,const std::vector<Sid> & sids_to_disable,const std::vector<std::wstring> & privileges_to_delete,const std::vector<Sid> & sids_to_restrict,ACCESS_MASK desired_access) const534*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::CreateRestricted(
535*6777b538SAndroid Build Coastguard Worker     DWORD flags,
536*6777b538SAndroid Build Coastguard Worker     const std::vector<Sid>& sids_to_disable,
537*6777b538SAndroid Build Coastguard Worker     const std::vector<std::wstring>& privileges_to_delete,
538*6777b538SAndroid Build Coastguard Worker     const std::vector<Sid>& sids_to_restrict,
539*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) const {
540*6777b538SAndroid Build Coastguard Worker   std::vector<SID_AND_ATTRIBUTES> sids_to_disable_buf =
541*6777b538SAndroid Build Coastguard Worker       ConvertSids(sids_to_disable, 0);
542*6777b538SAndroid Build Coastguard Worker   std::vector<SID_AND_ATTRIBUTES> sids_to_restrict_buf =
543*6777b538SAndroid Build Coastguard Worker       ConvertSids(sids_to_restrict, 0);
544*6777b538SAndroid Build Coastguard Worker   std::vector<LUID_AND_ATTRIBUTES> privileges_to_delete_buf =
545*6777b538SAndroid Build Coastguard Worker       ConvertPrivileges(privileges_to_delete, 0);
546*6777b538SAndroid Build Coastguard Worker   if (privileges_to_delete_buf.size() != privileges_to_delete.size()) {
547*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
548*6777b538SAndroid Build Coastguard Worker   }
549*6777b538SAndroid Build Coastguard Worker 
550*6777b538SAndroid Build Coastguard Worker   HANDLE token;
551*6777b538SAndroid Build Coastguard Worker   if (!::CreateRestrictedToken(
552*6777b538SAndroid Build Coastguard Worker           token_.get(), flags, checked_cast<DWORD>(sids_to_disable_buf.size()),
553*6777b538SAndroid Build Coastguard Worker           GetPointer(sids_to_disable_buf),
554*6777b538SAndroid Build Coastguard Worker           checked_cast<DWORD>(privileges_to_delete_buf.size()),
555*6777b538SAndroid Build Coastguard Worker           GetPointer(privileges_to_delete_buf),
556*6777b538SAndroid Build Coastguard Worker           checked_cast<DWORD>(sids_to_restrict_buf.size()),
557*6777b538SAndroid Build Coastguard Worker           GetPointer(sids_to_restrict_buf), &token)) {
558*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
559*6777b538SAndroid Build Coastguard Worker   }
560*6777b538SAndroid Build Coastguard Worker 
561*6777b538SAndroid Build Coastguard Worker   ScopedHandle token_handle(token);
562*6777b538SAndroid Build Coastguard Worker   return FromToken(token_handle.get(), desired_access);
563*6777b538SAndroid Build Coastguard Worker }
564*6777b538SAndroid Build Coastguard Worker 
CreateAppContainer(const Sid & appcontainer_sid,const std::vector<Sid> & capabilities,ACCESS_MASK desired_access) const565*6777b538SAndroid Build Coastguard Worker std::optional<AccessToken> AccessToken::CreateAppContainer(
566*6777b538SAndroid Build Coastguard Worker     const Sid& appcontainer_sid,
567*6777b538SAndroid Build Coastguard Worker     const std::vector<Sid>& capabilities,
568*6777b538SAndroid Build Coastguard Worker     ACCESS_MASK desired_access) const {
569*6777b538SAndroid Build Coastguard Worker   static const CreateAppContainerTokenFunction CreateAppContainerToken =
570*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<CreateAppContainerTokenFunction>(::GetProcAddress(
571*6777b538SAndroid Build Coastguard Worker           ::GetModuleHandle(L"kernelbase.dll"), "CreateAppContainerToken"));
572*6777b538SAndroid Build Coastguard Worker   if (!CreateAppContainerToken) {
573*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_PROC_NOT_FOUND);
574*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
575*6777b538SAndroid Build Coastguard Worker   }
576*6777b538SAndroid Build Coastguard Worker 
577*6777b538SAndroid Build Coastguard Worker   std::vector<SID_AND_ATTRIBUTES> capabilities_buf =
578*6777b538SAndroid Build Coastguard Worker       ConvertSids(capabilities, SE_GROUP_ENABLED);
579*6777b538SAndroid Build Coastguard Worker   SECURITY_CAPABILITIES security_capabilities = {};
580*6777b538SAndroid Build Coastguard Worker   security_capabilities.AppContainerSid = appcontainer_sid.GetPSID();
581*6777b538SAndroid Build Coastguard Worker   security_capabilities.Capabilities = GetPointer(capabilities_buf);
582*6777b538SAndroid Build Coastguard Worker   security_capabilities.CapabilityCount =
583*6777b538SAndroid Build Coastguard Worker       checked_cast<DWORD>(capabilities_buf.size());
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker   HANDLE token = nullptr;
586*6777b538SAndroid Build Coastguard Worker   if (!CreateAppContainerToken(token_.get(), &security_capabilities, &token)) {
587*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
588*6777b538SAndroid Build Coastguard Worker   }
589*6777b538SAndroid Build Coastguard Worker 
590*6777b538SAndroid Build Coastguard Worker   ScopedHandle token_handle(token);
591*6777b538SAndroid Build Coastguard Worker   return FromToken(token_handle.get(), desired_access);
592*6777b538SAndroid Build Coastguard Worker }
593*6777b538SAndroid Build Coastguard Worker 
SetPrivilege(const std::wstring & name,bool enable)594*6777b538SAndroid Build Coastguard Worker std::optional<bool> AccessToken::SetPrivilege(const std::wstring& name,
595*6777b538SAndroid Build Coastguard Worker                                               bool enable) {
596*6777b538SAndroid Build Coastguard Worker   std::optional<DWORD> attrs =
597*6777b538SAndroid Build Coastguard Worker       AdjustPrivilege(token_, name.c_str(), enable ? SE_PRIVILEGE_ENABLED : 0);
598*6777b538SAndroid Build Coastguard Worker   if (!attrs) {
599*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
600*6777b538SAndroid Build Coastguard Worker   }
601*6777b538SAndroid Build Coastguard Worker   return !!(*attrs & SE_PRIVILEGE_ENABLED);
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker 
RemovePrivilege(const std::wstring & name)604*6777b538SAndroid Build Coastguard Worker bool AccessToken::RemovePrivilege(const std::wstring& name) {
605*6777b538SAndroid Build Coastguard Worker   return AdjustPrivilege(token_, name.c_str(), SE_PRIVILEGE_REMOVED)
606*6777b538SAndroid Build Coastguard Worker       .has_value();
607*6777b538SAndroid Build Coastguard Worker }
608*6777b538SAndroid Build Coastguard Worker 
RemoveAllPrivileges()609*6777b538SAndroid Build Coastguard Worker bool AccessToken::RemoveAllPrivileges() {
610*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<char>> privileges_buffer =
611*6777b538SAndroid Build Coastguard Worker       GetTokenInfo(token_.get(), TokenPrivileges);
612*6777b538SAndroid Build Coastguard Worker   if (!privileges_buffer ||
613*6777b538SAndroid Build Coastguard Worker       (privileges_buffer->size() < sizeof(TOKEN_PRIVILEGES))) {
614*6777b538SAndroid Build Coastguard Worker     return false;
615*6777b538SAndroid Build Coastguard Worker   }
616*6777b538SAndroid Build Coastguard Worker   auto* const token_privileges = GetType<TOKEN_PRIVILEGES>(privileges_buffer);
617*6777b538SAndroid Build Coastguard Worker   if (privileges_buffer->size() <
618*6777b538SAndroid Build Coastguard Worker       (offsetof(TOKEN_PRIVILEGES, Privileges) +
619*6777b538SAndroid Build Coastguard Worker        sizeof(LUID_AND_ATTRIBUTES) * token_privileges->PrivilegeCount)) {
620*6777b538SAndroid Build Coastguard Worker     return false;
621*6777b538SAndroid Build Coastguard Worker   }
622*6777b538SAndroid Build Coastguard Worker 
623*6777b538SAndroid Build Coastguard Worker   for (auto privileges = base::make_span(&token_privileges->Privileges[0],
624*6777b538SAndroid Build Coastguard Worker                                          token_privileges->PrivilegeCount);
625*6777b538SAndroid Build Coastguard Worker        auto& privilege : privileges) {
626*6777b538SAndroid Build Coastguard Worker     privilege.Attributes = SE_PRIVILEGE_REMOVED;
627*6777b538SAndroid Build Coastguard Worker   }
628*6777b538SAndroid Build Coastguard Worker   return ::AdjustTokenPrivileges(
629*6777b538SAndroid Build Coastguard Worker       token_.get(), /*DisableAllPrivileges=*/FALSE, token_privileges,
630*6777b538SAndroid Build Coastguard Worker       static_cast<DWORD>(privileges_buffer->size()),
631*6777b538SAndroid Build Coastguard Worker       /*PreviousState=*/nullptr, /*ReturnLength=*/nullptr);
632*6777b538SAndroid Build Coastguard Worker }
633*6777b538SAndroid Build Coastguard Worker 
is_valid() const634*6777b538SAndroid Build Coastguard Worker bool AccessToken::is_valid() const {
635*6777b538SAndroid Build Coastguard Worker   return token_.is_valid();
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker 
get() const638*6777b538SAndroid Build Coastguard Worker HANDLE AccessToken::get() const {
639*6777b538SAndroid Build Coastguard Worker   return token_.get();
640*6777b538SAndroid Build Coastguard Worker }
641*6777b538SAndroid Build Coastguard Worker 
release()642*6777b538SAndroid Build Coastguard Worker ScopedHandle AccessToken::release() {
643*6777b538SAndroid Build Coastguard Worker   return ScopedHandle(token_.release());
644*6777b538SAndroid Build Coastguard Worker }
645*6777b538SAndroid Build Coastguard Worker 
AccessToken(HANDLE token)646*6777b538SAndroid Build Coastguard Worker AccessToken::AccessToken(HANDLE token) : token_(token) {}
647*6777b538SAndroid Build Coastguard Worker 
648*6777b538SAndroid Build Coastguard Worker }  // namespace base::win
649