1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
base / win / security_descriptor.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_WIN_SECURITY_DESCRIPTOR_H_
#define BASE_WIN_SECURITY_DESCRIPTOR_H_
#include <stdint.h>
#include <optional>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/files/file_path.h"
#include "base/win/access_control_list.h"
#include "base/win/access_token.h"
#include "base/win/sid.h"
#include "base/win/windows_types.h"
namespace base::win {
// Represents the type of Windows kernel object for reading/writing the security
// descriptor.
enum class SecurityObjectType {
kFile,
kRegistry,
kWindowStation,
kDesktop,
kKernel
};
// Results from the access check.
struct AccessCheckResult {
// The granted access from the check.
ACCESS_MASK granted_access;
// The access status. Set to true if the access check was successful.
bool access_status;
};
// This class is used to hold and modify a Windows security descriptor.
class BASE_EXPORT SecurityDescriptor {
public:
class BASE_EXPORT SelfRelative {
public:
friend SecurityDescriptor;
SelfRelative(const SelfRelative&);
~SelfRelative();
size_t size() const { return sd_.size(); }
PSECURITY_DESCRIPTOR get() const {
return const_cast<uint8_t*>(sd_.data());
}
private:
explicit SelfRelative(std::vector<uint8_t>&& sd);
std::vector<uint8_t> sd_;
};
// Create from an existing security descriptor pointer.
// |security_descriptor| The pointer to a self-relative or absolute security
// descriptor. This method will copy all security descriptor data.
static std::optional<SecurityDescriptor> FromPointer(
PSECURITY_DESCRIPTOR security_descriptor);
// Create from the security descriptor of an existing file.
// |path| the path to the file.
// |security_info| indicates what parts to read.
static std::optional<SecurityDescriptor> FromFile(
const base::FilePath& path,
SECURITY_INFORMATION security_info);
// Create from the security descriptor of a named Windows object.
// |name| the name of the object using the format specified for the
// GetNamedSecurityInfo API.
// |object_type| specifies the type of object the name represents.
// |security_info| indicates what parts to read.
static std::optional<SecurityDescriptor> FromName(
const std::wstring& name,
SecurityObjectType object_type,
SECURITY_INFORMATION security_info);
// Create from the security descriptor of a kernel object.
// |handle| the object handle. It must have READ_CONTROL access.
// |object_type| specifies the type of object the handle represents.
// |security_info| indicates what parts to read.
static std::optional<SecurityDescriptor> FromHandle(
HANDLE handle,
SecurityObjectType object_type,
SECURITY_INFORMATION security_info);
// Create from a string representation of a security descriptor.
// |sddl| the security descriptor in SDDL format.
static std::optional<SecurityDescriptor> FromSddl(const std::wstring& sddl);
SecurityDescriptor();
SecurityDescriptor(const SecurityDescriptor&) = delete;
SecurityDescriptor& operator=(const SecurityDescriptor&) = delete;
SecurityDescriptor(SecurityDescriptor&&);
SecurityDescriptor& operator=(SecurityDescriptor&&);
~SecurityDescriptor();
// Write the security descriptor to a file.
// |path| specifies the path to the file.
// |security_info| indicates what parts to write.
bool WriteToFile(const base::FilePath& path,
SECURITY_INFORMATION security_info) const;
// Write the security descriptor to a named kernel object.
// |name| the name of the object using the format specified for the
// SetNamedSecurityInfo API.
// |object_type| specifies the type of object name represents.
// |security_info| indicates what parts to write.
bool WriteToName(const std::wstring& name,
SecurityObjectType object_type,
SECURITY_INFORMATION security_info) const;
// Write the SecurityDescriptor to a kernel object.
// |handle| the handle to the object. Must have WRITE_DAC and/or WRITE_OWNER
// access depending of the parts specified with |security_info|. |object_type|
// specifies the type of object the handle represents. Use kKernel for
// undefined types. |security_info| indicates what parts to write.
bool WriteToHandle(HANDLE handle,
SecurityObjectType object_type,
SECURITY_INFORMATION security_info) const;
// Convert the SecurityDescriptor to an SDDL string.
// |security_info| determines what parts are included in the string.
std::optional<std::wstring> ToSddl(SECURITY_INFORMATION security_info) const;
// Create an reference to the absolute security descriptor of this instance.
// |sd| the SECURITY_DESCRIPTOR structure to populate. This is is only valid
// as long as this object is in scope and not modified.
void ToAbsolute(SECURITY_DESCRIPTOR& sd);
// Create a self-relative security descriptor in a single buffer.
std::optional<SelfRelative> ToSelfRelative() const;
// Make a clone of the current security descriptor object.
SecurityDescriptor Clone() const;
// Set the mandatory label in the security descriptor. Note that calling
// this will completely replace the SACL.
// |integrity_level| is the integrity level for the label.
// |inheritance| specify the flags for inheritance.
// |mandatory_policy| is the policy, e.g. SYSTEM_MANDATORY_LABEL_NO_WRITE_UP.
bool SetMandatoryLabel(DWORD integrity_level,
DWORD inheritance,
DWORD mandatory_policy);
// Set one or more entry in the DACL.
// |entries| the list of entries to set in the ACL.
// Returns true if successful, false on error, with the Win32 last error set.
// If DACL is not present a NULL ACL will be added first.
bool SetDaclEntries(const std::vector<ExplicitAccessEntry>& entries);
// Set one entry in the DACL.
// |sid| the SID for the entry.
// |mode| the operation to perform on the ACL, e.g. grant access.
// |access_mask| the entries access mask.
// |inheritance| inheritance flags.
// Returns true if successful, false on
// error, with the Win32 last error set.
// If DACL is not present a NULL ACL will be added first.
bool SetDaclEntry(const Sid& sid,
SecurityAccessMode mode,
DWORD access_mask,
DWORD inheritance);
// Set one entry in the DACL.
// |known_sid| the known SID for the entry.
// |mode| the operation to perform on the ACL, e.g. grant access.
// |access_mask| the entries access mask.
// |inheritance| inheritance flags.
// Returns true if successful, false on
// error, with the Win32 last error set.
// If DACL is not present a NULL ACL will be added first.
bool SetDaclEntry(WellKnownSid known_sid,
SecurityAccessMode mode,
DWORD access_mask,
DWORD inheritance);
// Perform an access check for this security descriptor.
// |token| specify the impersonation token to check against.
// |desired_access| the access desired for the check.
// |generic_mapping| the generic mapping for the access check.
// Returns the result of the access check. If an empty result is returned the
// call to the AccessCheck API failed.
std::optional<AccessCheckResult> AccessCheck(
const AccessToken& token,
ACCESS_MASK desired_access,
const GENERIC_MAPPING& generic_mapping);
// Perform an access check for this security descriptor.
// |token| specify the impersonation token to check against.
// |desired_access| the access desired for the check.
// |object_type| the object type to determine how to map generic rights. Note
// that you can't use kKernel as that doesn't reflect a specific kernel object
// type, an empty return will be return if this is used. If you need to access
// check an unsupported type use the overload which accepts a manually
// configured GENERIC_MAPPING.
// Returns the result of the access check. If an empty result is returned the
// call to the AccessCheck API failed.
std::optional<AccessCheckResult> AccessCheck(const AccessToken& token,
ACCESS_MASK desired_access,
SecurityObjectType object_type);
// Get, set and clear owner member.
const std::optional<Sid>& owner() const { return owner_; }
std::optional<Sid>& owner() { return owner_; }
void set_owner(const Sid& owner) { owner_ = owner.Clone(); }
void clear_owner() { owner_ = std::nullopt; }
// Get, set and clear group member.
const std::optional<Sid>& group() const { return group_; }
std::optional<Sid>& group() { return group_; }
void set_group(const Sid& group) { group_ = group.Clone(); }
void clear_group() { group_ = std::nullopt; }
// Get, set and clear dacl member.
const std::optional<AccessControlList>& dacl() const { return dacl_; }
std::optional<AccessControlList>& dacl() { return dacl_; }
void set_dacl(const AccessControlList& dacl) { dacl_ = dacl.Clone(); }
void clear_dacl() { dacl_ = std::nullopt; }
// Get and set dacl_protected member.
bool dacl_protected() const { return dacl_protected_; }
void set_dacl_protected(bool dacl_protected) {
dacl_protected_ = dacl_protected;
}
// Get, set and clear sacl member.
const std::optional<AccessControlList>& sacl() const { return sacl_; }
std::optional<AccessControlList>& sacl() { return sacl_; }
void set_sacl(const AccessControlList& sacl) { sacl_ = sacl.Clone(); }
void clear_sacl() { sacl_ = std::nullopt; }
// Get and set sacl_protected member.
bool sacl_protected() const { return sacl_protected_; }
void set_sacl_protected(bool sacl_protected) {
sacl_protected_ = sacl_protected;
}
private:
SecurityDescriptor(std::optional<Sid>&& owner,
std::optional<Sid>&& group,
std::optional<AccessControlList>&& dacl,
bool dacl_protected,
std::optional<AccessControlList>&& sacl,
bool sacl_protected);
std::optional<Sid> owner_;
std::optional<Sid> group_;
std::optional<AccessControlList> dacl_;
bool dacl_protected_ = false;
std::optional<AccessControlList> sacl_;
bool sacl_protected_ = false;
};
} // namespace base::win
#endif // BASE_WIN_SECURITY_DESCRIPTOR_H_