xref: /aosp_15_r20/external/cronet/base/win/access_token.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_WIN_ACCESS_TOKEN_H_
6 #define BASE_WIN_ACCESS_TOKEN_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <string>
11 #include <vector>
12 
13 #include "base/base_export.h"
14 #include "base/win/access_control_list.h"
15 #include "base/win/scoped_handle.h"
16 #include "base/win/sid.h"
17 #include "base/win/windows_types.h"
18 
19 namespace base::win {
20 
21 // Impersonation level for the token.
22 enum class SecurityImpersonationLevel {
23   kAnonymous,
24   kIdentification,
25   kImpersonation,
26   kDelegation
27 };
28 
29 // This class is used to access the information for a Windows access token.
30 class BASE_EXPORT AccessToken {
31  public:
32   // This class represents an access token group.
33   class BASE_EXPORT Group {
34    public:
35     // Get the group SID.
GetSid()36     const Sid& GetSid() const { return sid_; }
37     // Get the group attribute flags.
GetAttributes()38     DWORD GetAttributes() const { return attributes_; }
39     // Returns true if the group is an integrity level.
40     bool IsIntegrity() const;
41     // Returns true if the group is enabled.
42     bool IsEnabled() const;
43     // Returns true if the group is deny only.
44     bool IsDenyOnly() const;
45     // Returns true if the group is the logon ID.
46     bool IsLogonId() const;
47 
48     Group(Sid&& sid, DWORD attributes);
49     Group(Group&&);
50     ~Group();
51 
52    private:
53     Sid sid_;
54     DWORD attributes_;
55   };
56 
57   // This class represents an access token privilege.
58   class BASE_EXPORT Privilege {
59    public:
60     // Get the privilege LUID.
GetLuid()61     CHROME_LUID GetLuid() const { return luid_; }
62     // Get the privilege attribute flags.
GetAttributes()63     DWORD GetAttributes() const { return attributes_; }
64     // Get the name of the privilege.
65     std::wstring GetName() const;
66     // Returns true if the privilege is enabled.
67     bool IsEnabled() const;
68 
69     Privilege(CHROME_LUID luid, DWORD attributes);
70 
71    private:
72     CHROME_LUID luid_;
73     DWORD attributes_;
74   };
75 
76   // Creates an AccessToken object from a token handle.
77   // |token| the token handle. This handle will be duplicated for TOKEN_QUERY
78   // access, therefore the caller must be granted that access to the token
79   // object. The AccessToken object owns its own copy of the token handle so
80   // the original can be closed.
81   // |desired_access| specifies additional access for the token handle,
82   // TOKEN_QUERY will always be requested.
83   static std::optional<AccessToken> FromToken(HANDLE token,
84                                               ACCESS_MASK desired_access = 0);
85 
86   // Creates an AccessToken object from an existing token handle.
87   // |token| the token handle. The AccessToken object will take ownership of
88   // this handle without duplicating it. It must have been opened with at least
89   // TOKEN_QUERY access to succeed.
90   static std::optional<AccessToken> FromToken(ScopedHandle&& token);
91 
92   // Creates an AccessToken object from a process handle.
93   // |process| the process handle. The handle needs to have
94   // PROCESS_QUERY_LIMITED_INFORMATION access to the handle and TOKEN_QUERY
95   // access to the token object.
96   // |impersonation| if true then the process token will be duplicated to an
97   // impersonation token. This allows you to call the IsMember API which
98   // requires an impersonation token. To duplicate TOKEN_DUPLICATE access is
99   // required.
100   // |desired_access| specifies additional access for the token handle,
101   // TOKEN_QUERY will always be requested.
102   static std::optional<AccessToken> FromProcess(HANDLE process,
103                                                 bool impersonation = false,
104                                                 ACCESS_MASK desired_access = 0);
105 
106   // Creates an AccessToken object for the current process.
107   // |impersonation| if true then the process token will be duplicated to an
108   // impersonation token. This allows you to call the IsMember API which
109   // requires an impersonation token. To duplicate TOKEN_DUPLICATE access is
110   // required.
111   // |desired_access| specifies additional access for the token handle,
112   // TOKEN_QUERY will always be requested.
113   static std::optional<AccessToken> FromCurrentProcess(
114       bool impersonation = false,
115       ACCESS_MASK desired_access = 0);
116 
117   // Creates an AccessToken object from a thread handle. The thread must be
118   // impersonating a token for this to succeed.
119   // |thread| the thread handle. The handle needs to have
120   // THREAD_QUERY_LIMITED_INFORMATION access and TOKEN_QUERY access to the
121   // token object.
122   // |open_as_self| open the token using the process token rather than the
123   // current thread's impersonated token.
124   // If the thread isn't impersonating it will return an empty value and the
125   // Win32 last error code will be ERROR_NO_TOKEN.
126   // |desired_access| specifies additional access for the token handle,
127   // TOKEN_QUERY will always be requested.
128   static std::optional<AccessToken> FromThread(HANDLE thread,
129                                                bool open_as_self = true,
130                                                ACCESS_MASK desired_access = 0);
131 
132   // Creates an AccessToken object from the current thread. The thread must be
133   // impersonating a token for this to succeed.
134   // |open_as_self| open the thread handle using the process token rather
135   // than the current thread's impersonated token.
136   // If the thread isn't impersonating it will return an empty value and the
137   // Win32 last error code will be ERROR_NO_TOKEN.
138   // |desired_access| specifies additional access for the token handle,
139   // TOKEN_QUERY will always be requested.
140   static std::optional<AccessToken> FromCurrentThread(
141       bool open_as_self = true,
142       ACCESS_MASK desired_access = 0);
143 
144   // Creates an AccessToken object for the current thread's effective token.
145   // If the thread is impersonating then it'll try and open the thread token,
146   // otherwise it'll open the process token.
147   // |desired_access| specifies additional access for the token handle,
148   // TOKEN_QUERY will always be requested.
149   static std::optional<AccessToken> FromEffective(
150       ACCESS_MASK desired_access = 0);
151 
152   AccessToken(const AccessToken&) = delete;
153   AccessToken& operator=(const AccessToken&) = delete;
154   AccessToken(AccessToken&&);
155   AccessToken& operator=(AccessToken&&);
156   ~AccessToken();
157 
158   // Get the token's user SID.
159   Sid User() const;
160 
161   // Get the token's user group.
162   Group UserGroup() const;
163 
164   // Get the token's owner SID. This can be different to the user SID, it's
165   // used as the default owner for new secured objects.
166   Sid Owner() const;
167 
168   // Get the token's primary group SID.
169   Sid PrimaryGroup() const;
170 
171   // Get the token logon SID. Returns an empty value if the token doesn't have
172   // a logon SID. If the logon SID doesn't exist then the Win32 last error code
173   // will be ERROR_NOT_FOUND.
174   std::optional<Sid> LogonId() const;
175 
176   // Get the token's integrity level. Returns MAXDWORD if the token doesn't
177   // have an integrity level.
178   DWORD IntegrityLevel() const;
179 
180   // Set the token's integrity level. Token needs to have been opened with
181   // TOKEN_ADJUST_DEFAULT access.
182   bool SetIntegrityLevel(DWORD integrity_level);
183 
184   // Get the token's session ID. Returns MAXDWORD if the token if the session
185   // ID can't be queried.
186   DWORD SessionId() const;
187 
188   // The token's group list.
189   std::vector<Group> Groups() const;
190 
191   // Get whether the token is a restricted.
192   bool IsRestricted() const;
193 
194   // The token's restricted SIDs list. If not a restricted token this will
195   // return an empty vector.
196   std::vector<Group> RestrictedSids() const;
197 
198   // Get whether the token is an appcontainer.
199   bool IsAppContainer() const;
200 
201   // Get the token's appcontainer SID. If not an appcontainer token this will
202   // return an empty value.
203   std::optional<Sid> AppContainerSid() const;
204 
205   // The token's capabilities. If not an appcontainer token this will return an
206   // empty vector.
207   std::vector<Group> Capabilities() const;
208 
209   // Get the UAC linked token.
210   std::optional<AccessToken> LinkedToken() const;
211 
212   // Get the default DACL for the token. Returns an empty value on error.
213   std::optional<AccessControlList> DefaultDacl() const;
214 
215   // Set the default DACL of the token. Token needs to have been opened with
216   // TOKEN_ADJUST_DEFAULT access.
217   bool SetDefaultDacl(const AccessControlList& default_dacl);
218 
219   // Get the token's ID.
220   CHROME_LUID Id() const;
221 
222   // Get the token's authentication ID.
223   CHROME_LUID AuthenticationId() const;
224 
225   // Get the token's privileges.
226   std::vector<Privilege> Privileges() const;
227 
228   // Get whether the token is elevated.
229   bool IsElevated() const;
230 
231   // Checks if the sid is a member of the token's groups. The token must be
232   // an impersonation token rather than a primary token. If the token is not an
233   // impersonation token then it returns false and the Win32 last error will be
234   // set to ERROR_NO_IMPERSONATION_TOKEN.
235   bool IsMember(const Sid& sid) const;
236 
237   // Checks if the well known sid is a member of the token's groups. The token
238   // must be an impersonation token rather than a primary token. If the token
239   // is not an impersonation token then it returns false and the Win32 last
240   // error will be set to ERROR_NO_IMPERSONATION_TOKEN.
241   bool IsMember(WellKnownSid known_sid) const;
242 
243   // Checks if the token is an impersonation token. If false then it's a primary
244   // token.
245   bool IsImpersonation() const;
246 
247   // Checks if the token can only be used for identification. This is based on
248   // the security impersonation level of the token. If the level is less than
249   // or equal to SecurityIdentification this function returns true. Always
250   // returns false for a primary token.
251   bool IsIdentification() const;
252 
253   // Get the current impersonation level. If the token is a primary token
254   // the function returns kImpersonation.
255   SecurityImpersonationLevel ImpersonationLevel() const;
256 
257   // Duplicate the token to a new primary token.
258   // |desired_access| specifies additional access for the token handle.
259   // TOKEN_QUERY will always be requested.
260   // The original token must have TOKEN_DUPLICATE access to successfully
261   // duplicate the token.
262   std::optional<AccessToken> DuplicatePrimary(
263       ACCESS_MASK desired_access = 0) const;
264 
265   // Duplicate the token to a new impersonation token.
266   // |impersonation_level| specifies the impersonation level for the token.
267   // |desired_access| specifies additional access for the token handle.
268   // TOKEN_QUERY will always be requested.
269   // The original token must have TOKEN_DUPLICATE access to successfully
270   // duplicate the token.
271   std::optional<AccessToken> DuplicateImpersonation(
272       SecurityImpersonationLevel impersonation_level =
273           SecurityImpersonationLevel::kImpersonation,
274       ACCESS_MASK desired_access = 0) const;
275 
276   // Create a new restricted token from this token.
277   // |flags| can be set to a combination of DISABLE_MAX_PRIVILEGE,
278   // SANDBOX_INERT, LUA_TOKEN and WRITE_RESTRICTED.
279   // |sids_to_disable| is the list of SIDs to disable in the token.
280   // |privileges_to_delete| is the names of the privileges to delete.
281   // |sids_to_restrict| is the list of SIDs to add as restricted SIDs.
282   // |desired_access| specifies additional access for the token handle.
283   // The token needs to be opened with TOKEN_DUPLICATE access.
284   std::optional<AccessToken> CreateRestricted(
285       DWORD flags,
286       const std::vector<Sid>& sids_to_disable,
287       const std::vector<std::wstring>& privileges_to_delete,
288       const std::vector<Sid>& sids_to_restrict,
289       ACCESS_MASK desired_access = 0) const;
290 
291   // Create a new AppContainer primary token from this token.
292   // |app_container_sid| the AppContainer package SID.
293   // |capabilities| the list of AppContainer capabilities.
294   // |desired_access| specifies additional access for the token handle.
295   // The token needs to be opened with TOKEN_DUPLICATE access.
296   std::optional<AccessToken> CreateAppContainer(
297       const Sid& appcontainer_sid,
298       const std::vector<Sid>& capabilities,
299       ACCESS_MASK desired_access = 0) const;
300 
301   // Enable or disable a privilege.
302   // |name| the name of the privilege to change.
303   // |enable| specify whether to enable or disable the privilege.
304   // Returns the previous enable state of the privilege, or nullopt if failed.
305   // The token must be opened with TOKEN_ADJUST_PRIVILEGES access.
306   std::optional<bool> SetPrivilege(const std::wstring& name, bool enable);
307 
308   // Remove a privilege permanently from the token.
309   // |name| the name of the privilege to remove.
310   // Returns true if successfully removed the privilege.
311   // The token must be opened with TOKEN_ADJUST_PRIVILEGES access.
312   bool RemovePrivilege(const std::wstring& name);
313 
314   // Permanently remove all privileges from the token.
315   // Returns true if the operation was successful.
316   // The token must be opened with TOKEN_ADJUST_PRIVILEGES access.
317   bool RemoveAllPrivileges();
318 
319   // Indicates if the AccessToken object is valid.
320   bool is_valid() const;
321 
322   // Get the underlying token handle.
323   HANDLE get() const;
324 
325   // Take ownership of the underlying token handle. Once released no other
326   // methods on this object should be called.
327   ScopedHandle release();
328 
329  private:
330   explicit AccessToken(HANDLE token);
331   ScopedHandle token_;
332 };
333 
334 }  // namespace base::win
335 
336 #endif  // BASE_WIN_ACCESS_TOKEN_H_
337