1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/win/security_descriptor.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker // clang-format off
8*6777b538SAndroid Build Coastguard Worker #include <windows.h> // Must be in front of other Windows header files.
9*6777b538SAndroid Build Coastguard Worker // clang-format on
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include <aclapi.h>
12*6777b538SAndroid Build Coastguard Worker #include <sddl.h>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include <utility>
15*6777b538SAndroid Build Coastguard Worker #include <vector>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/numerics/checked_math.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_localalloc.h"
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace base::win {
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker namespace {
26*6777b538SAndroid Build Coastguard Worker template <typename T>
CloneValue(const std::optional<T> & value)27*6777b538SAndroid Build Coastguard Worker std::optional<T> CloneValue(const std::optional<T>& value) {
28*6777b538SAndroid Build Coastguard Worker if (!value)
29*6777b538SAndroid Build Coastguard Worker return std::nullopt;
30*6777b538SAndroid Build Coastguard Worker return value->Clone();
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
UnwrapSid(const std::optional<Sid> & sid)33*6777b538SAndroid Build Coastguard Worker PSID UnwrapSid(const std::optional<Sid>& sid) {
34*6777b538SAndroid Build Coastguard Worker if (!sid)
35*6777b538SAndroid Build Coastguard Worker return nullptr;
36*6777b538SAndroid Build Coastguard Worker return sid->GetPSID();
37*6777b538SAndroid Build Coastguard Worker }
38*6777b538SAndroid Build Coastguard Worker
UnwrapAcl(const std::optional<AccessControlList> & acl)39*6777b538SAndroid Build Coastguard Worker PACL UnwrapAcl(const std::optional<AccessControlList>& acl) {
40*6777b538SAndroid Build Coastguard Worker if (!acl)
41*6777b538SAndroid Build Coastguard Worker return nullptr;
42*6777b538SAndroid Build Coastguard Worker return acl->get();
43*6777b538SAndroid Build Coastguard Worker }
44*6777b538SAndroid Build Coastguard Worker
ConvertObjectType(SecurityObjectType object_type)45*6777b538SAndroid Build Coastguard Worker SE_OBJECT_TYPE ConvertObjectType(SecurityObjectType object_type) {
46*6777b538SAndroid Build Coastguard Worker switch (object_type) {
47*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kFile:
48*6777b538SAndroid Build Coastguard Worker return SE_FILE_OBJECT;
49*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kRegistry:
50*6777b538SAndroid Build Coastguard Worker return SE_REGISTRY_KEY;
51*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kWindowStation:
52*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kDesktop:
53*6777b538SAndroid Build Coastguard Worker return SE_WINDOW_OBJECT;
54*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kKernel:
55*6777b538SAndroid Build Coastguard Worker return SE_KERNEL_OBJECT;
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker return SE_UNKNOWN_OBJECT_TYPE;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
GetGenericMappingForType(SecurityObjectType object_type)60*6777b538SAndroid Build Coastguard Worker GENERIC_MAPPING GetGenericMappingForType(SecurityObjectType object_type) {
61*6777b538SAndroid Build Coastguard Worker GENERIC_MAPPING generic_mapping = {};
62*6777b538SAndroid Build Coastguard Worker switch (object_type) {
63*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kFile:
64*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericRead = FILE_GENERIC_READ;
65*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericWrite = FILE_GENERIC_WRITE;
66*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericExecute = FILE_GENERIC_EXECUTE;
67*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericAll = FILE_ALL_ACCESS;
68*6777b538SAndroid Build Coastguard Worker break;
69*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kRegistry:
70*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericRead = KEY_READ;
71*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericWrite = KEY_WRITE;
72*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericExecute = KEY_EXECUTE;
73*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericAll = KEY_ALL_ACCESS;
74*6777b538SAndroid Build Coastguard Worker break;
75*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kDesktop:
76*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericRead =
77*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_READ | DESKTOP_READOBJECTS | DESKTOP_ENUMERATE;
78*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericWrite =
79*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_WRITE | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU |
80*6777b538SAndroid Build Coastguard Worker DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD |
81*6777b538SAndroid Build Coastguard Worker DESKTOP_JOURNALPLAYBACK | DESKTOP_WRITEOBJECTS;
82*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericExecute =
83*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP;
84*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericAll =
85*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
86*6777b538SAndroid Build Coastguard Worker DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK |
87*6777b538SAndroid Build Coastguard Worker DESKTOP_JOURNALRECORD | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP |
88*6777b538SAndroid Build Coastguard Worker DESKTOP_WRITEOBJECTS;
89*6777b538SAndroid Build Coastguard Worker break;
90*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kWindowStation:
91*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericRead = STANDARD_RIGHTS_READ | WINSTA_ENUMDESKTOPS |
92*6777b538SAndroid Build Coastguard Worker WINSTA_ENUMERATE | WINSTA_READATTRIBUTES |
93*6777b538SAndroid Build Coastguard Worker WINSTA_READSCREEN;
94*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericWrite =
95*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_WRITE | WINSTA_ACCESSCLIPBOARD |
96*6777b538SAndroid Build Coastguard Worker WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES;
97*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericExecute = STANDARD_RIGHTS_EXECUTE |
98*6777b538SAndroid Build Coastguard Worker WINSTA_ACCESSGLOBALATOMS |
99*6777b538SAndroid Build Coastguard Worker WINSTA_EXITWINDOWS;
100*6777b538SAndroid Build Coastguard Worker generic_mapping.GenericAll =
101*6777b538SAndroid Build Coastguard Worker STANDARD_RIGHTS_REQUIRED | WINSTA_ACCESSCLIPBOARD |
102*6777b538SAndroid Build Coastguard Worker WINSTA_ACCESSGLOBALATOMS | WINSTA_CREATEDESKTOP |
103*6777b538SAndroid Build Coastguard Worker WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |
104*6777b538SAndroid Build Coastguard Worker WINSTA_READATTRIBUTES | WINSTA_READSCREEN | WINSTA_WRITEATTRIBUTES;
105*6777b538SAndroid Build Coastguard Worker break;
106*6777b538SAndroid Build Coastguard Worker case SecurityObjectType::kKernel:
107*6777b538SAndroid Build Coastguard Worker NOTREACHED();
108*6777b538SAndroid Build Coastguard Worker break;
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker return generic_mapping;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker template <typename T>
GetSecurityDescriptor(T object,SecurityObjectType object_type,SECURITY_INFORMATION security_info,DWORD (WINAPI * get_sd)(T,SE_OBJECT_TYPE,SECURITY_INFORMATION,PSID *,PSID *,PACL *,PACL *,PSECURITY_DESCRIPTOR *))114*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> GetSecurityDescriptor(
115*6777b538SAndroid Build Coastguard Worker T object,
116*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
117*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info,
118*6777b538SAndroid Build Coastguard Worker DWORD(WINAPI* get_sd)(T,
119*6777b538SAndroid Build Coastguard Worker SE_OBJECT_TYPE,
120*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION,
121*6777b538SAndroid Build Coastguard Worker PSID*,
122*6777b538SAndroid Build Coastguard Worker PSID*,
123*6777b538SAndroid Build Coastguard Worker PACL*,
124*6777b538SAndroid Build Coastguard Worker PACL*,
125*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR*)) {
126*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR sd = nullptr;
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker DWORD error = get_sd(object, ConvertObjectType(object_type), security_info,
129*6777b538SAndroid Build Coastguard Worker nullptr, nullptr, nullptr, nullptr, &sd);
130*6777b538SAndroid Build Coastguard Worker if (error != ERROR_SUCCESS) {
131*6777b538SAndroid Build Coastguard Worker ::SetLastError(error);
132*6777b538SAndroid Build Coastguard Worker DPLOG(ERROR) << "Failed getting security descriptor for object.";
133*6777b538SAndroid Build Coastguard Worker return std::nullopt;
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker auto sd_ptr = TakeLocalAlloc(sd);
136*6777b538SAndroid Build Coastguard Worker return SecurityDescriptor::FromPointer(sd_ptr.get());
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker template <typename T>
SetSecurityDescriptor(const SecurityDescriptor & sd,T object,SecurityObjectType object_type,SECURITY_INFORMATION security_info,DWORD (WINAPI * set_sd)(T,SE_OBJECT_TYPE,SECURITY_INFORMATION,PSID,PSID,PACL,PACL))140*6777b538SAndroid Build Coastguard Worker bool SetSecurityDescriptor(const SecurityDescriptor& sd,
141*6777b538SAndroid Build Coastguard Worker T object,
142*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
143*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info,
144*6777b538SAndroid Build Coastguard Worker DWORD(WINAPI* set_sd)(T,
145*6777b538SAndroid Build Coastguard Worker SE_OBJECT_TYPE,
146*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION,
147*6777b538SAndroid Build Coastguard Worker PSID,
148*6777b538SAndroid Build Coastguard Worker PSID,
149*6777b538SAndroid Build Coastguard Worker PACL,
150*6777b538SAndroid Build Coastguard Worker PACL)) {
151*6777b538SAndroid Build Coastguard Worker security_info &= ~(PROTECTED_DACL_SECURITY_INFORMATION |
152*6777b538SAndroid Build Coastguard Worker UNPROTECTED_DACL_SECURITY_INFORMATION |
153*6777b538SAndroid Build Coastguard Worker PROTECTED_SACL_SECURITY_INFORMATION |
154*6777b538SAndroid Build Coastguard Worker UNPROTECTED_SACL_SECURITY_INFORMATION);
155*6777b538SAndroid Build Coastguard Worker if (security_info & DACL_SECURITY_INFORMATION) {
156*6777b538SAndroid Build Coastguard Worker if (sd.dacl_protected()) {
157*6777b538SAndroid Build Coastguard Worker security_info |= PROTECTED_DACL_SECURITY_INFORMATION;
158*6777b538SAndroid Build Coastguard Worker } else {
159*6777b538SAndroid Build Coastguard Worker security_info |= UNPROTECTED_DACL_SECURITY_INFORMATION;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker }
162*6777b538SAndroid Build Coastguard Worker if (security_info & SACL_SECURITY_INFORMATION) {
163*6777b538SAndroid Build Coastguard Worker if (sd.sacl_protected()) {
164*6777b538SAndroid Build Coastguard Worker security_info |= PROTECTED_SACL_SECURITY_INFORMATION;
165*6777b538SAndroid Build Coastguard Worker } else {
166*6777b538SAndroid Build Coastguard Worker security_info |= UNPROTECTED_SACL_SECURITY_INFORMATION;
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker }
169*6777b538SAndroid Build Coastguard Worker DWORD error = set_sd(object, ConvertObjectType(object_type), security_info,
170*6777b538SAndroid Build Coastguard Worker UnwrapSid(sd.owner()), UnwrapSid(sd.group()),
171*6777b538SAndroid Build Coastguard Worker UnwrapAcl(sd.dacl()), UnwrapAcl(sd.sacl()));
172*6777b538SAndroid Build Coastguard Worker if (error != ERROR_SUCCESS) {
173*6777b538SAndroid Build Coastguard Worker ::SetLastError(error);
174*6777b538SAndroid Build Coastguard Worker DPLOG(ERROR) << "Failed setting DACL for object.";
175*6777b538SAndroid Build Coastguard Worker return false;
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker return true;
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker
GetSecurityDescriptorSid(PSECURITY_DESCRIPTOR sd,BOOL (WINAPI * get_sid)(PSECURITY_DESCRIPTOR,PSID *,LPBOOL))180*6777b538SAndroid Build Coastguard Worker std::optional<Sid> GetSecurityDescriptorSid(
181*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR sd,
182*6777b538SAndroid Build Coastguard Worker BOOL(WINAPI* get_sid)(PSECURITY_DESCRIPTOR, PSID*, LPBOOL)) {
183*6777b538SAndroid Build Coastguard Worker PSID sid;
184*6777b538SAndroid Build Coastguard Worker BOOL defaulted;
185*6777b538SAndroid Build Coastguard Worker if (!get_sid(sd, &sid, &defaulted) || !sid) {
186*6777b538SAndroid Build Coastguard Worker return std::nullopt;
187*6777b538SAndroid Build Coastguard Worker }
188*6777b538SAndroid Build Coastguard Worker return Sid::FromPSID(sid);
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker
GetSecurityDescriptorAcl(PSECURITY_DESCRIPTOR sd,BOOL (WINAPI * get_acl)(PSECURITY_DESCRIPTOR,LPBOOL,PACL *,LPBOOL))191*6777b538SAndroid Build Coastguard Worker std::optional<AccessControlList> GetSecurityDescriptorAcl(
192*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR sd,
193*6777b538SAndroid Build Coastguard Worker BOOL(WINAPI* get_acl)(PSECURITY_DESCRIPTOR, LPBOOL, PACL*, LPBOOL)) {
194*6777b538SAndroid Build Coastguard Worker PACL acl;
195*6777b538SAndroid Build Coastguard Worker BOOL present;
196*6777b538SAndroid Build Coastguard Worker BOOL defaulted;
197*6777b538SAndroid Build Coastguard Worker if (!get_acl(sd, &present, &acl, &defaulted) || !present) {
198*6777b538SAndroid Build Coastguard Worker return std::nullopt;
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker return AccessControlList::FromPACL(acl);
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker } // namespace
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SelfRelative::SelfRelative(const SelfRelative&) = default;
206*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SelfRelative::~SelfRelative() = default;
SelfRelative(std::vector<uint8_t> && sd)207*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SelfRelative::SelfRelative(std::vector<uint8_t>&& sd)
208*6777b538SAndroid Build Coastguard Worker : sd_(sd) {}
209*6777b538SAndroid Build Coastguard Worker
FromPointer(PSECURITY_DESCRIPTOR sd)210*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> SecurityDescriptor::FromPointer(
211*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR sd) {
212*6777b538SAndroid Build Coastguard Worker if (!sd || !::IsValidSecurityDescriptor(sd)) {
213*6777b538SAndroid Build Coastguard Worker ::SetLastError(ERROR_INVALID_SECURITY_DESCR);
214*6777b538SAndroid Build Coastguard Worker return std::nullopt;
215*6777b538SAndroid Build Coastguard Worker }
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR_CONTROL control;
218*6777b538SAndroid Build Coastguard Worker DWORD revision;
219*6777b538SAndroid Build Coastguard Worker if (!::GetSecurityDescriptorControl(sd, &control, &revision)) {
220*6777b538SAndroid Build Coastguard Worker return std::nullopt;
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker return SecurityDescriptor{
224*6777b538SAndroid Build Coastguard Worker GetSecurityDescriptorSid(sd, ::GetSecurityDescriptorOwner),
225*6777b538SAndroid Build Coastguard Worker GetSecurityDescriptorSid(sd, ::GetSecurityDescriptorGroup),
226*6777b538SAndroid Build Coastguard Worker GetSecurityDescriptorAcl(sd, ::GetSecurityDescriptorDacl),
227*6777b538SAndroid Build Coastguard Worker !!(control & SE_DACL_PROTECTED),
228*6777b538SAndroid Build Coastguard Worker GetSecurityDescriptorAcl(sd, ::GetSecurityDescriptorSacl),
229*6777b538SAndroid Build Coastguard Worker !!(control & SE_SACL_PROTECTED)};
230*6777b538SAndroid Build Coastguard Worker }
231*6777b538SAndroid Build Coastguard Worker
FromFile(const base::FilePath & path,SECURITY_INFORMATION security_info)232*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> SecurityDescriptor::FromFile(
233*6777b538SAndroid Build Coastguard Worker const base::FilePath& path,
234*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) {
235*6777b538SAndroid Build Coastguard Worker return FromName(path.value(), SecurityObjectType::kFile, security_info);
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker
FromName(const std::wstring & name,SecurityObjectType object_type,SECURITY_INFORMATION security_info)238*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> SecurityDescriptor::FromName(
239*6777b538SAndroid Build Coastguard Worker const std::wstring& name,
240*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
241*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) {
242*6777b538SAndroid Build Coastguard Worker return GetSecurityDescriptor(name.c_str(), object_type, security_info,
243*6777b538SAndroid Build Coastguard Worker ::GetNamedSecurityInfo);
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker
FromHandle(HANDLE handle,SecurityObjectType object_type,SECURITY_INFORMATION security_info)246*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> SecurityDescriptor::FromHandle(
247*6777b538SAndroid Build Coastguard Worker HANDLE handle,
248*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
249*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) {
250*6777b538SAndroid Build Coastguard Worker return GetSecurityDescriptor<HANDLE>(handle, object_type, security_info,
251*6777b538SAndroid Build Coastguard Worker ::GetSecurityInfo);
252*6777b538SAndroid Build Coastguard Worker }
253*6777b538SAndroid Build Coastguard Worker
FromSddl(const std::wstring & sddl)254*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor> SecurityDescriptor::FromSddl(
255*6777b538SAndroid Build Coastguard Worker const std::wstring& sddl) {
256*6777b538SAndroid Build Coastguard Worker PSECURITY_DESCRIPTOR sd;
257*6777b538SAndroid Build Coastguard Worker if (!::ConvertStringSecurityDescriptorToSecurityDescriptor(
258*6777b538SAndroid Build Coastguard Worker sddl.c_str(), SDDL_REVISION_1, &sd, nullptr)) {
259*6777b538SAndroid Build Coastguard Worker return std::nullopt;
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker auto sd_ptr = TakeLocalAlloc(sd);
262*6777b538SAndroid Build Coastguard Worker return FromPointer(sd_ptr.get());
263*6777b538SAndroid Build Coastguard Worker }
264*6777b538SAndroid Build Coastguard Worker
265*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SecurityDescriptor() = default;
266*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SecurityDescriptor(SecurityDescriptor&&) = default;
267*6777b538SAndroid Build Coastguard Worker SecurityDescriptor& SecurityDescriptor::operator=(SecurityDescriptor&&) =
268*6777b538SAndroid Build Coastguard Worker default;
269*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::~SecurityDescriptor() = default;
270*6777b538SAndroid Build Coastguard Worker
WriteToFile(const base::FilePath & path,SECURITY_INFORMATION security_info) const271*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::WriteToFile(const base::FilePath& path,
272*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) const {
273*6777b538SAndroid Build Coastguard Worker return WriteToName(path.value(), SecurityObjectType::kFile, security_info);
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker
WriteToName(const std::wstring & name,SecurityObjectType object_type,SECURITY_INFORMATION security_info) const276*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::WriteToName(const std::wstring& name,
277*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
278*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) const {
279*6777b538SAndroid Build Coastguard Worker return SetSecurityDescriptor<wchar_t*>(
280*6777b538SAndroid Build Coastguard Worker *this, const_cast<wchar_t*>(name.c_str()), object_type, security_info,
281*6777b538SAndroid Build Coastguard Worker ::SetNamedSecurityInfo);
282*6777b538SAndroid Build Coastguard Worker }
283*6777b538SAndroid Build Coastguard Worker
WriteToHandle(HANDLE handle,SecurityObjectType object_type,SECURITY_INFORMATION security_info) const284*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::WriteToHandle(
285*6777b538SAndroid Build Coastguard Worker HANDLE handle,
286*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type,
287*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) const {
288*6777b538SAndroid Build Coastguard Worker return SetSecurityDescriptor<HANDLE>(*this, handle, object_type,
289*6777b538SAndroid Build Coastguard Worker security_info, ::SetSecurityInfo);
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker
ToSddl(SECURITY_INFORMATION security_info) const292*6777b538SAndroid Build Coastguard Worker std::optional<std::wstring> SecurityDescriptor::ToSddl(
293*6777b538SAndroid Build Coastguard Worker SECURITY_INFORMATION security_info) const {
294*6777b538SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR sd = {};
295*6777b538SAndroid Build Coastguard Worker ToAbsolute(sd);
296*6777b538SAndroid Build Coastguard Worker LPWSTR sddl;
297*6777b538SAndroid Build Coastguard Worker if (!::ConvertSecurityDescriptorToStringSecurityDescriptor(
298*6777b538SAndroid Build Coastguard Worker &sd, SDDL_REVISION_1, security_info, &sddl, nullptr)) {
299*6777b538SAndroid Build Coastguard Worker return std::nullopt;
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker auto sddl_ptr = TakeLocalAlloc(sddl);
302*6777b538SAndroid Build Coastguard Worker return sddl_ptr.get();
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
ToAbsolute(SECURITY_DESCRIPTOR & sd) const305*6777b538SAndroid Build Coastguard Worker void SecurityDescriptor::ToAbsolute(SECURITY_DESCRIPTOR& sd) const {
306*6777b538SAndroid Build Coastguard Worker memset(&sd, 0, sizeof(sd));
307*6777b538SAndroid Build Coastguard Worker sd.Revision = SECURITY_DESCRIPTOR_REVISION;
308*6777b538SAndroid Build Coastguard Worker sd.Owner = owner_ ? owner_->GetPSID() : nullptr;
309*6777b538SAndroid Build Coastguard Worker sd.Group = group_ ? group_->GetPSID() : nullptr;
310*6777b538SAndroid Build Coastguard Worker if (dacl_) {
311*6777b538SAndroid Build Coastguard Worker sd.Dacl = dacl_->get();
312*6777b538SAndroid Build Coastguard Worker sd.Control |= SE_DACL_PRESENT;
313*6777b538SAndroid Build Coastguard Worker if (dacl_protected_) {
314*6777b538SAndroid Build Coastguard Worker sd.Control |= SE_DACL_PROTECTED;
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker if (sacl_) {
318*6777b538SAndroid Build Coastguard Worker sd.Sacl = sacl_->get();
319*6777b538SAndroid Build Coastguard Worker sd.Control |= SE_SACL_PRESENT;
320*6777b538SAndroid Build Coastguard Worker if (sacl_protected_) {
321*6777b538SAndroid Build Coastguard Worker sd.Control |= SE_SACL_PROTECTED;
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker }
324*6777b538SAndroid Build Coastguard Worker DCHECK(::IsValidSecurityDescriptor(&sd));
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker std::optional<SecurityDescriptor::SelfRelative>
ToSelfRelative() const328*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::ToSelfRelative() const {
329*6777b538SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR sd = {};
330*6777b538SAndroid Build Coastguard Worker ToAbsolute(sd);
331*6777b538SAndroid Build Coastguard Worker DWORD size = sizeof(SECURITY_DESCRIPTOR_MIN_LENGTH);
332*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> buffer(SECURITY_DESCRIPTOR_MIN_LENGTH);
333*6777b538SAndroid Build Coastguard Worker if (::MakeSelfRelativeSD(&sd, buffer.data(), &size)) {
334*6777b538SAndroid Build Coastguard Worker return SelfRelative(std::move(buffer));
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
338*6777b538SAndroid Build Coastguard Worker return std::nullopt;
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker buffer.resize(size);
342*6777b538SAndroid Build Coastguard Worker if (!::MakeSelfRelativeSD(&sd, buffer.data(), &size)) {
343*6777b538SAndroid Build Coastguard Worker return std::nullopt;
344*6777b538SAndroid Build Coastguard Worker }
345*6777b538SAndroid Build Coastguard Worker return SelfRelative(std::move(buffer));
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker
Clone() const348*6777b538SAndroid Build Coastguard Worker SecurityDescriptor SecurityDescriptor::Clone() const {
349*6777b538SAndroid Build Coastguard Worker return SecurityDescriptor{CloneValue(owner_), CloneValue(group_),
350*6777b538SAndroid Build Coastguard Worker CloneValue(dacl_), dacl_protected_,
351*6777b538SAndroid Build Coastguard Worker CloneValue(sacl_), sacl_protected_};
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker
SetMandatoryLabel(DWORD integrity_level,DWORD inheritance,DWORD mandatory_policy)354*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::SetMandatoryLabel(DWORD integrity_level,
355*6777b538SAndroid Build Coastguard Worker DWORD inheritance,
356*6777b538SAndroid Build Coastguard Worker DWORD mandatory_policy) {
357*6777b538SAndroid Build Coastguard Worker std::optional<AccessControlList> sacl = AccessControlList::FromMandatoryLabel(
358*6777b538SAndroid Build Coastguard Worker integrity_level, inheritance, mandatory_policy);
359*6777b538SAndroid Build Coastguard Worker if (!sacl) {
360*6777b538SAndroid Build Coastguard Worker return false;
361*6777b538SAndroid Build Coastguard Worker }
362*6777b538SAndroid Build Coastguard Worker sacl_ = std::move(*sacl);
363*6777b538SAndroid Build Coastguard Worker return true;
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker
SetDaclEntries(const std::vector<ExplicitAccessEntry> & entries)366*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::SetDaclEntries(
367*6777b538SAndroid Build Coastguard Worker const std::vector<ExplicitAccessEntry>& entries) {
368*6777b538SAndroid Build Coastguard Worker if (!dacl_) {
369*6777b538SAndroid Build Coastguard Worker dacl_ = AccessControlList{};
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker return dacl_->SetEntries(entries);
372*6777b538SAndroid Build Coastguard Worker }
373*6777b538SAndroid Build Coastguard Worker
SetDaclEntry(const Sid & sid,SecurityAccessMode mode,DWORD access_mask,DWORD inheritance)374*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::SetDaclEntry(const Sid& sid,
375*6777b538SAndroid Build Coastguard Worker SecurityAccessMode mode,
376*6777b538SAndroid Build Coastguard Worker DWORD access_mask,
377*6777b538SAndroid Build Coastguard Worker DWORD inheritance) {
378*6777b538SAndroid Build Coastguard Worker if (!dacl_) {
379*6777b538SAndroid Build Coastguard Worker dacl_ = AccessControlList{};
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker return dacl_->SetEntry(sid, mode, access_mask, inheritance);
382*6777b538SAndroid Build Coastguard Worker }
383*6777b538SAndroid Build Coastguard Worker
SetDaclEntry(WellKnownSid known_sid,SecurityAccessMode mode,DWORD access_mask,DWORD inheritance)384*6777b538SAndroid Build Coastguard Worker bool SecurityDescriptor::SetDaclEntry(WellKnownSid known_sid,
385*6777b538SAndroid Build Coastguard Worker SecurityAccessMode mode,
386*6777b538SAndroid Build Coastguard Worker DWORD access_mask,
387*6777b538SAndroid Build Coastguard Worker DWORD inheritance) {
388*6777b538SAndroid Build Coastguard Worker return SetDaclEntry(Sid(known_sid), mode, access_mask, inheritance);
389*6777b538SAndroid Build Coastguard Worker }
390*6777b538SAndroid Build Coastguard Worker
AccessCheck(const AccessToken & token,ACCESS_MASK desired_access,const GENERIC_MAPPING & generic_mapping)391*6777b538SAndroid Build Coastguard Worker std::optional<AccessCheckResult> SecurityDescriptor::AccessCheck(
392*6777b538SAndroid Build Coastguard Worker const AccessToken& token,
393*6777b538SAndroid Build Coastguard Worker ACCESS_MASK desired_access,
394*6777b538SAndroid Build Coastguard Worker const GENERIC_MAPPING& generic_mapping) {
395*6777b538SAndroid Build Coastguard Worker GENERIC_MAPPING local_mapping = generic_mapping;
396*6777b538SAndroid Build Coastguard Worker ::MapGenericMask(&desired_access, &local_mapping);
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker // Allocate a privilege set which could cover all possible privileges.
399*6777b538SAndroid Build Coastguard Worker DWORD priv_set_length = checked_cast<DWORD>(
400*6777b538SAndroid Build Coastguard Worker sizeof(PRIVILEGE_SET) +
401*6777b538SAndroid Build Coastguard Worker (token.Privileges().size() * sizeof(LUID_AND_ATTRIBUTES)));
402*6777b538SAndroid Build Coastguard Worker std::vector<char> priv_set(priv_set_length);
403*6777b538SAndroid Build Coastguard Worker DWORD granted_access = 0;
404*6777b538SAndroid Build Coastguard Worker BOOL access_status = FALSE;
405*6777b538SAndroid Build Coastguard Worker SECURITY_DESCRIPTOR sd = {};
406*6777b538SAndroid Build Coastguard Worker ToAbsolute(sd);
407*6777b538SAndroid Build Coastguard Worker if (!::AccessCheck(&sd, token.get(), desired_access, &local_mapping,
408*6777b538SAndroid Build Coastguard Worker reinterpret_cast<PPRIVILEGE_SET>(priv_set.data()),
409*6777b538SAndroid Build Coastguard Worker &priv_set_length, &granted_access, &access_status)) {
410*6777b538SAndroid Build Coastguard Worker return std::nullopt;
411*6777b538SAndroid Build Coastguard Worker }
412*6777b538SAndroid Build Coastguard Worker return AccessCheckResult{granted_access, !!access_status};
413*6777b538SAndroid Build Coastguard Worker }
414*6777b538SAndroid Build Coastguard Worker
AccessCheck(const AccessToken & token,ACCESS_MASK desired_access,SecurityObjectType object_type)415*6777b538SAndroid Build Coastguard Worker std::optional<AccessCheckResult> SecurityDescriptor::AccessCheck(
416*6777b538SAndroid Build Coastguard Worker const AccessToken& token,
417*6777b538SAndroid Build Coastguard Worker ACCESS_MASK desired_access,
418*6777b538SAndroid Build Coastguard Worker SecurityObjectType object_type) {
419*6777b538SAndroid Build Coastguard Worker if (object_type == SecurityObjectType::kKernel) {
420*6777b538SAndroid Build Coastguard Worker ::SetLastError(ERROR_INVALID_PARAMETER);
421*6777b538SAndroid Build Coastguard Worker return std::nullopt;
422*6777b538SAndroid Build Coastguard Worker }
423*6777b538SAndroid Build Coastguard Worker return AccessCheck(token, desired_access,
424*6777b538SAndroid Build Coastguard Worker GetGenericMappingForType(object_type));
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker
SecurityDescriptor(std::optional<Sid> && owner,std::optional<Sid> && group,std::optional<AccessControlList> && dacl,bool dacl_protected,std::optional<AccessControlList> && sacl,bool sacl_protected)427*6777b538SAndroid Build Coastguard Worker SecurityDescriptor::SecurityDescriptor(std::optional<Sid>&& owner,
428*6777b538SAndroid Build Coastguard Worker std::optional<Sid>&& group,
429*6777b538SAndroid Build Coastguard Worker std::optional<AccessControlList>&& dacl,
430*6777b538SAndroid Build Coastguard Worker bool dacl_protected,
431*6777b538SAndroid Build Coastguard Worker std::optional<AccessControlList>&& sacl,
432*6777b538SAndroid Build Coastguard Worker bool sacl_protected) {
433*6777b538SAndroid Build Coastguard Worker owner_.swap(owner);
434*6777b538SAndroid Build Coastguard Worker group_.swap(group);
435*6777b538SAndroid Build Coastguard Worker dacl_.swap(dacl);
436*6777b538SAndroid Build Coastguard Worker dacl_protected_ = dacl_protected;
437*6777b538SAndroid Build Coastguard Worker sacl_.swap(sacl);
438*6777b538SAndroid Build Coastguard Worker sacl_protected_ = sacl_protected;
439*6777b538SAndroid Build Coastguard Worker }
440*6777b538SAndroid Build Coastguard Worker
441*6777b538SAndroid Build Coastguard Worker } // namespace base::win
442