xref: /aosp_15_r20/external/cronet/base/win/security_descriptor.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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