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