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_ACCESS_CONTROL_LIST_H_ 6 #define BASE_WIN_ACCESS_CONTROL_LIST_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <optional> 12 #include <vector> 13 14 #include "base/base_export.h" 15 #include "base/compiler_specific.h" 16 #include "base/containers/heap_array.h" 17 #include "base/win/sid.h" 18 #include "base/win/windows_types.h" 19 20 namespace base::win { 21 22 // Represents the type of access operation to perform on an ACL. 23 enum class SecurityAccessMode { kGrant, kSet, kDeny, kRevoke }; 24 25 // Class to represent an entry to modify the ACL. 26 class BASE_EXPORT ExplicitAccessEntry { 27 public: 28 ExplicitAccessEntry(const Sid& sid, 29 SecurityAccessMode mode, 30 DWORD access_mask, 31 DWORD inheritance); 32 ExplicitAccessEntry(WellKnownSid known_sid, 33 SecurityAccessMode mode, 34 DWORD access_mask, 35 DWORD inheritance); 36 ExplicitAccessEntry(const ExplicitAccessEntry&) = delete; 37 ExplicitAccessEntry& operator=(const ExplicitAccessEntry&) = delete; 38 ExplicitAccessEntry(ExplicitAccessEntry&&); 39 ExplicitAccessEntry& operator=(ExplicitAccessEntry&&); 40 ~ExplicitAccessEntry(); 41 sid()42 const Sid& sid() const LIFETIME_BOUND { return sid_; } mode()43 SecurityAccessMode mode() const { return mode_; } access_mask()44 DWORD access_mask() const { return access_mask_; } inheritance()45 DWORD inheritance() const { return inheritance_; } 46 // Clones the entry. 47 ExplicitAccessEntry Clone() const; 48 49 private: 50 Sid sid_; 51 SecurityAccessMode mode_; 52 DWORD access_mask_; 53 DWORD inheritance_; 54 }; 55 56 // This class is used to hold and modify Windows ACLs. An AccessControlList 57 // object can contain a null ACL which grants everyone access to a resource. A 58 // null ACL is distinct from an empty ACL which grants no-one access. An empty 59 // ACL is the default when constructing a new instance. 60 class BASE_EXPORT AccessControlList { 61 public: 62 // Create from an existing ACL pointer. 63 // |acl| The ACL pointer. Passing nullptr will create a null ACL. 64 static std::optional<AccessControlList> FromPACL(ACL* acl); 65 66 // Create an AccessControlList from a mandatory label. 67 // |integrity_level| is the integrity level for the label. 68 // |inheritance| inheritance flags. 69 // |mandatory_policy| is the policy, e.g. SYSTEM_MANDATORY_LABEL_NO_WRITE_UP. 70 static std::optional<AccessControlList> FromMandatoryLabel( 71 DWORD integrity_level, 72 DWORD inheritance, 73 DWORD mandatory_policy); 74 75 AccessControlList(); 76 AccessControlList(const AccessControlList&) = delete; 77 AccessControlList& operator=(const AccessControlList&) = delete; 78 AccessControlList(AccessControlList&&); 79 AccessControlList& operator=(AccessControlList&&); 80 ~AccessControlList(); 81 82 // Set one or more entry in the ACL. 83 // |entries| the list of entries to set in the ACL. 84 // Returns true if successful, false on error, with the Win32 last error set. 85 bool SetEntries(const std::vector<ExplicitAccessEntry>& entries); 86 87 // Set one entry in the ACL. 88 // |sid| the SID for the entry. 89 // |mode| the operation to perform on the ACL, e.g. grant access. 90 // |access_mask| the entries access mask. 91 // |inheritance| inheritance flags. 92 // Returns true if successful, false on error, with the Win32 last error set. 93 bool SetEntry(const Sid& sid, 94 SecurityAccessMode mode, 95 DWORD access_mask, 96 DWORD inheritance); 97 98 // Make a clone of the current AccessControlList object. 99 AccessControlList Clone() const; 100 101 // Clear all entries in the AccessControlList. 102 void Clear(); 103 104 // Returns the AccessControlList as a ACL*. The AccessControlList object 105 // retains owenership of the pointer. This can return nullptr if the ACL is 106 // null. get()107 ACL* get() { return reinterpret_cast<ACL*>(acl_.data()); } get()108 const ACL* get() const { return reinterpret_cast<const ACL*>(acl_.data()); } 109 110 // Returns whether the AccessControlList is considered a null ACL. is_null()111 bool is_null() const { 112 // Note: there is a distinction between null ACL (ACL that occupies 0 bytes) 113 // and an empty ACL (an ACL that occupies sizeof(ACL) bytes and has no ACEs 114 // following it). If the underlying storage is empty, it means that we're 115 // dealing with a null ACL. 116 return acl_.empty(); 117 } 118 119 private: 120 explicit AccessControlList(const ACL* acl); 121 base::HeapArray<uint8_t> acl_; 122 }; 123 124 } // namespace base::win 125 126 #endif // BASE_WIN_ACCESS_CONTROL_LIST_H_ 127