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
|
// 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_
|