tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

access_control_list.cc (5614B)


      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 #include "base/win/access_control_list.h"
      6 
      7 #include <aclapi.h>
      8 #include <windows.h>
      9 
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "base/check.h"
     14 #include "base/logging.h"
     15 #include "base/notreached.h"
     16 #include "base/numerics/checked_math.h"
     17 #include "base/win/scoped_localalloc.h"
     18 
     19 namespace base::win {
     20 
     21 namespace {
     22 
     23 std::unique_ptr<uint8_t[]> AclToBuffer(const ACL* acl) {
     24  if (!acl) {
     25    return nullptr;
     26  }
     27  size_t size = acl->AclSize;
     28  DCHECK(size >= sizeof(*acl));
     29  std::unique_ptr<uint8_t[]> ptr = std::make_unique<uint8_t[]>(size);
     30  memcpy(ptr.get(), acl, size);
     31  return ptr;
     32 }
     33 
     34 std::unique_ptr<uint8_t[]> EmptyAclToBuffer() {
     35  ACL acl = {};
     36  acl.AclRevision = ACL_REVISION;
     37  acl.AclSize = static_cast<WORD>(sizeof(acl));
     38  return AclToBuffer(&acl);
     39 }
     40 
     41 ACCESS_MODE ConvertAccessMode(SecurityAccessMode access_mode) {
     42  switch (access_mode) {
     43    case SecurityAccessMode::kGrant:
     44      return GRANT_ACCESS;
     45    case SecurityAccessMode::kSet:
     46      return SET_ACCESS;
     47    case SecurityAccessMode::kDeny:
     48      return DENY_ACCESS;
     49    case SecurityAccessMode::kRevoke:
     50      return REVOKE_ACCESS;
     51  }
     52 }
     53 
     54 std::unique_ptr<uint8_t[]> AddACEToAcl(
     55    ACL* old_acl,
     56    const std::vector<ExplicitAccessEntry>& entries) {
     57  std::vector<EXPLICIT_ACCESS> access_entries(entries.size());
     58  auto entries_interator = access_entries.begin();
     59  for (const ExplicitAccessEntry& entry : entries) {
     60    EXPLICIT_ACCESS& new_access = *entries_interator++;
     61    new_access.grfAccessMode = ConvertAccessMode(entry.mode());
     62    new_access.grfAccessPermissions = entry.access_mask();
     63    new_access.grfInheritance = entry.inheritance();
     64    ::BuildTrusteeWithSid(&new_access.Trustee, entry.sid().GetPSID());
     65  }
     66 
     67  PACL new_acl = nullptr;
     68  DWORD error = ::SetEntriesInAcl(checked_cast<ULONG>(access_entries.size()),
     69                                  access_entries.data(), old_acl, &new_acl);
     70  if (error != ERROR_SUCCESS) {
     71    ::SetLastError(error);
     72    DPLOG(ERROR) << "Failed adding ACEs to ACL";
     73    return nullptr;
     74  }
     75  auto new_acl_ptr = TakeLocalAlloc(new_acl);
     76  return AclToBuffer(new_acl_ptr.get());
     77 }
     78 
     79 }  // namespace
     80 
     81 ExplicitAccessEntry ExplicitAccessEntry::Clone() const {
     82  return ExplicitAccessEntry{sid_, mode_, access_mask_, inheritance_};
     83 }
     84 
     85 ExplicitAccessEntry::ExplicitAccessEntry(const Sid& sid,
     86                                         SecurityAccessMode mode,
     87                                         DWORD access_mask,
     88                                         DWORD inheritance)
     89    : sid_(sid.Clone()),
     90      mode_(mode),
     91      access_mask_(access_mask),
     92      inheritance_(inheritance) {}
     93 
     94 ExplicitAccessEntry::ExplicitAccessEntry(WellKnownSid known_sid,
     95                                         SecurityAccessMode mode,
     96                                         DWORD access_mask,
     97                                         DWORD inheritance)
     98    : ExplicitAccessEntry(Sid(known_sid), mode, access_mask, inheritance) {}
     99 
    100 ExplicitAccessEntry::ExplicitAccessEntry(ExplicitAccessEntry&&) = default;
    101 ExplicitAccessEntry& ExplicitAccessEntry::operator=(ExplicitAccessEntry&&) =
    102    default;
    103 ExplicitAccessEntry::~ExplicitAccessEntry() = default;
    104 
    105 absl::optional<AccessControlList> AccessControlList::FromPACL(ACL* acl) {
    106  if (acl && !::IsValidAcl(acl)) {
    107    ::SetLastError(ERROR_INVALID_ACL);
    108    return absl::nullopt;
    109  }
    110  return AccessControlList{acl};
    111 }
    112 
    113 absl::optional<AccessControlList> AccessControlList::FromMandatoryLabel(
    114    DWORD integrity_level,
    115    DWORD inheritance,
    116    DWORD mandatory_policy) {
    117  Sid sid = Sid::FromIntegrityLevel(integrity_level);
    118  // Get total ACL length. SYSTEM_MANDATORY_LABEL_ACE contains the first DWORD
    119  // of the SID so remove it from total.
    120  DWORD length = sizeof(ACL) + sizeof(SYSTEM_MANDATORY_LABEL_ACE) +
    121                 ::GetLengthSid(sid.GetPSID()) - sizeof(DWORD);
    122  std::unique_ptr<uint8_t[]> sacl_ptr = std::make_unique<uint8_t[]>(length);
    123  PACL sacl = reinterpret_cast<PACL>(sacl_ptr.get());
    124 
    125  if (!::InitializeAcl(sacl, length, ACL_REVISION)) {
    126    return absl::nullopt;
    127  }
    128 
    129  if (!::AddMandatoryAce(sacl, ACL_REVISION, inheritance, mandatory_policy,
    130                         sid.GetPSID())) {
    131    return absl::nullopt;
    132  }
    133 
    134  DCHECK(::IsValidAcl(sacl));
    135  AccessControlList ret;
    136  ret.acl_ = std::move(sacl_ptr);
    137  return ret;
    138 }
    139 
    140 AccessControlList::AccessControlList() : acl_(EmptyAclToBuffer()) {}
    141 AccessControlList::AccessControlList(AccessControlList&&) = default;
    142 AccessControlList& AccessControlList::operator=(AccessControlList&&) = default;
    143 AccessControlList::~AccessControlList() = default;
    144 
    145 bool AccessControlList::SetEntries(
    146    const std::vector<ExplicitAccessEntry>& entries) {
    147  if (entries.empty())
    148    return true;
    149 
    150  std::unique_ptr<uint8_t[]> acl = AddACEToAcl(get(), entries);
    151  if (!acl)
    152    return false;
    153 
    154  acl_ = std::move(acl);
    155  return true;
    156 }
    157 
    158 bool AccessControlList::SetEntry(const Sid& sid,
    159                                 SecurityAccessMode mode,
    160                                 DWORD access_mask,
    161                                 DWORD inheritance) {
    162  std::vector<ExplicitAccessEntry> ace_list;
    163  ace_list.emplace_back(sid, mode, access_mask, inheritance);
    164  return SetEntries(ace_list);
    165 }
    166 
    167 AccessControlList AccessControlList::Clone() const {
    168  return AccessControlList{get()};
    169 }
    170 
    171 void AccessControlList::Clear() {
    172  acl_ = EmptyAclToBuffer();
    173 }
    174 
    175 AccessControlList::AccessControlList(const ACL* acl) : acl_(AclToBuffer(acl)) {}
    176 
    177 }  // namespace base::win