1 // Copyright 2021 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/security_util.h"
6
7 #include <windows.h>
8 #include <winternl.h>
9
10 #include "base/check.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/win/access_control_list.h"
14 #include "base/win/scoped_handle.h"
15 #include "base/win/security_descriptor.h"
16 #include "third_party/abseil-cpp/absl/types/optional.h"
17
18 namespace base {
19 namespace win {
20
21 namespace {
22
AddACEToPath(const FilePath & path,const std::vector<Sid> & sids,DWORD access_mask,DWORD inheritance,bool recursive,SecurityAccessMode access_mode)23 bool AddACEToPath(const FilePath& path,
24 const std::vector<Sid>& sids,
25 DWORD access_mask,
26 DWORD inheritance,
27 bool recursive,
28 SecurityAccessMode access_mode) {
29 DCHECK(!path.empty());
30 if (sids.empty()) {
31 return true;
32 }
33
34 absl::optional<SecurityDescriptor> sd =
35 SecurityDescriptor::FromFile(path, DACL_SECURITY_INFORMATION);
36 if (!sd) {
37 return false;
38 }
39
40 std::vector<ExplicitAccessEntry> entries;
41 for (const Sid& sid : sids) {
42 entries.emplace_back(sid, access_mode, access_mask, inheritance);
43 }
44
45 if (!sd->SetDaclEntries(entries)) {
46 return false;
47 }
48
49 if (recursive) {
50 return sd->WriteToFile(path, DACL_SECURITY_INFORMATION);
51 }
52
53 ScopedHandle handle(::CreateFile(path.value().c_str(), WRITE_DAC, 0, nullptr,
54 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
55 nullptr));
56 if (!handle.is_valid()) {
57 DPLOG(ERROR) << "Failed opening path \"" << path.value()
58 << "\" to write DACL";
59 return false;
60 }
61 return sd->WriteToHandle(handle.get(), SecurityObjectType::kKernel,
62 DACL_SECURITY_INFORMATION);
63 }
64
65 } // namespace
66
GrantAccessToPath(const FilePath & path,const std::vector<Sid> & sids,DWORD access_mask,DWORD inheritance,bool recursive)67 bool GrantAccessToPath(const FilePath& path,
68 const std::vector<Sid>& sids,
69 DWORD access_mask,
70 DWORD inheritance,
71 bool recursive) {
72 return AddACEToPath(path, sids, access_mask, inheritance, recursive,
73 SecurityAccessMode::kGrant);
74 }
75
DenyAccessToPath(const FilePath & path,const std::vector<Sid> & sids,DWORD access_mask,DWORD inheritance,bool recursive)76 bool DenyAccessToPath(const FilePath& path,
77 const std::vector<Sid>& sids,
78 DWORD access_mask,
79 DWORD inheritance,
80 bool recursive) {
81 return AddACEToPath(path, sids, access_mask, inheritance, recursive,
82 SecurityAccessMode::kDeny);
83 }
84
CloneSidVector(const std::vector<Sid> & sids)85 std::vector<Sid> CloneSidVector(const std::vector<Sid>& sids) {
86 std::vector<Sid> clone;
87 clone.reserve(sids.size());
88 for (const Sid& sid : sids) {
89 clone.push_back(sid.Clone());
90 }
91 return clone;
92 }
93
AppendSidVector(std::vector<Sid> & base_sids,const std::vector<Sid> & append_sids)94 void AppendSidVector(std::vector<Sid>& base_sids,
95 const std::vector<Sid>& append_sids) {
96 for (const Sid& sid : append_sids) {
97 base_sids.push_back(sid.Clone());
98 }
99 }
100
GetGrantedAccess(HANDLE handle)101 absl::optional<ACCESS_MASK> GetGrantedAccess(HANDLE handle) {
102 PUBLIC_OBJECT_BASIC_INFORMATION basic_info = {};
103 if (!NT_SUCCESS(::NtQueryObject(handle, ObjectBasicInformation, &basic_info,
104 sizeof(basic_info), nullptr))) {
105 return absl::nullopt;
106 }
107 return basic_info.GrantedAccess;
108 }
109
110 } // namespace win
111 } // namespace base
112