112 lines
3.2 KiB
C++
112 lines
3.2 KiB
C++
// Copyright 2021 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/win/security_util.h"
|
|
|
|
#include <windows.h>
|
|
#include <winternl.h>
|
|
|
|
#include "base/check.h"
|
|
#include "base/files/file_path.h"
|
|
#include "base/logging.h"
|
|
#include "base/win/access_control_list.h"
|
|
#include "base/win/scoped_handle.h"
|
|
#include "base/win/security_descriptor.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
|
|
namespace base {
|
|
namespace win {
|
|
|
|
namespace {
|
|
|
|
bool AddACEToPath(const FilePath& path,
|
|
const std::vector<Sid>& sids,
|
|
DWORD access_mask,
|
|
DWORD inheritance,
|
|
bool recursive,
|
|
SecurityAccessMode access_mode) {
|
|
DCHECK(!path.empty());
|
|
if (sids.empty()) {
|
|
return true;
|
|
}
|
|
|
|
absl::optional<SecurityDescriptor> sd =
|
|
SecurityDescriptor::FromFile(path, DACL_SECURITY_INFORMATION);
|
|
if (!sd) {
|
|
return false;
|
|
}
|
|
|
|
std::vector<ExplicitAccessEntry> entries;
|
|
for (const Sid& sid : sids) {
|
|
entries.emplace_back(sid, access_mode, access_mask, inheritance);
|
|
}
|
|
|
|
if (!sd->SetDaclEntries(entries)) {
|
|
return false;
|
|
}
|
|
|
|
if (recursive) {
|
|
return sd->WriteToFile(path, DACL_SECURITY_INFORMATION);
|
|
}
|
|
|
|
ScopedHandle handle(::CreateFile(path.value().c_str(), WRITE_DAC, 0, nullptr,
|
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
|
|
nullptr));
|
|
if (!handle.is_valid()) {
|
|
DPLOG(ERROR) << "Failed opening path \"" << path.value()
|
|
<< "\" to write DACL";
|
|
return false;
|
|
}
|
|
return sd->WriteToHandle(handle.get(), SecurityObjectType::kKernel,
|
|
DACL_SECURITY_INFORMATION);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool GrantAccessToPath(const FilePath& path,
|
|
const std::vector<Sid>& sids,
|
|
DWORD access_mask,
|
|
DWORD inheritance,
|
|
bool recursive) {
|
|
return AddACEToPath(path, sids, access_mask, inheritance, recursive,
|
|
SecurityAccessMode::kGrant);
|
|
}
|
|
|
|
bool DenyAccessToPath(const FilePath& path,
|
|
const std::vector<Sid>& sids,
|
|
DWORD access_mask,
|
|
DWORD inheritance,
|
|
bool recursive) {
|
|
return AddACEToPath(path, sids, access_mask, inheritance, recursive,
|
|
SecurityAccessMode::kDeny);
|
|
}
|
|
|
|
std::vector<Sid> CloneSidVector(const std::vector<Sid>& sids) {
|
|
std::vector<Sid> clone;
|
|
clone.reserve(sids.size());
|
|
for (const Sid& sid : sids) {
|
|
clone.push_back(sid.Clone());
|
|
}
|
|
return clone;
|
|
}
|
|
|
|
void AppendSidVector(std::vector<Sid>& base_sids,
|
|
const std::vector<Sid>& append_sids) {
|
|
for (const Sid& sid : append_sids) {
|
|
base_sids.push_back(sid.Clone());
|
|
}
|
|
}
|
|
|
|
absl::optional<ACCESS_MASK> GetGrantedAccess(HANDLE handle) {
|
|
PUBLIC_OBJECT_BASIC_INFORMATION basic_info = {};
|
|
if (!NT_SUCCESS(::NtQueryObject(handle, ObjectBasicInformation, &basic_info,
|
|
sizeof(basic_info), nullptr))) {
|
|
return absl::nullopt;
|
|
}
|
|
return basic_info.GrantedAccess;
|
|
}
|
|
|
|
} // namespace win
|
|
} // namespace base
|