// Copyright 2021 The Chromium Authors. All rights reserved. // 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 #include #include #include "base/check.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/numerics/checked_math.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_localalloc.h" #include "base/win/win_util.h" namespace base { namespace win { namespace { bool AddACEToPath(const FilePath& path, const std::vector& sids, DWORD access_mask, DWORD inheritance, bool recursive, ACCESS_MODE access_mode) { DCHECK(!path.empty()); if (sids.empty()) return true; std::wstring object_name = path.value(); PSECURITY_DESCRIPTOR sd = nullptr; PACL dacl = nullptr; // Get the existing DACL. DWORD error = ::GetNamedSecurityInfo(object_name.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, &dacl, nullptr, &sd); if (error != ERROR_SUCCESS) { ::SetLastError(error); DPLOG(ERROR) << "Failed getting DACL for path \"" << path.value() << "\""; return false; } auto sd_ptr = TakeLocalAlloc(sd); std::vector access_entries(sids.size()); auto entries_interator = access_entries.begin(); for (const Sid& sid : sids) { EXPLICIT_ACCESS& new_access = *entries_interator++; new_access.grfAccessMode = access_mode; new_access.grfAccessPermissions = access_mask; new_access.grfInheritance = inheritance; ::BuildTrusteeWithSid(&new_access.Trustee, sid.GetPSID()); } PACL new_dacl = nullptr; error = ::SetEntriesInAcl(checked_cast(access_entries.size()), access_entries.data(), dacl, &new_dacl); if (error != ERROR_SUCCESS) { ::SetLastError(error); DPLOG(ERROR) << "Failed adding ACEs to DACL for path \"" << path.value() << "\""; return false; } auto new_dacl_ptr = TakeLocalAlloc(new_dacl); if (recursive) { error = ::SetNamedSecurityInfo(&object_name[0], SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, new_dacl_ptr.get(), nullptr); } else { 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; } error = ::SetSecurityInfo(handle.get(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, new_dacl_ptr.get(), nullptr); } if (error != ERROR_SUCCESS) { ::SetLastError(error); DPLOG(ERROR) << "Failed setting DACL for path \"" << path.value() << "\""; return false; } return true; } } // namespace bool GrantAccessToPath(const FilePath& path, const std::vector& sids, DWORD access_mask, DWORD inheritance, bool recursive) { return AddACEToPath(path, sids, access_mask, inheritance, recursive, GRANT_ACCESS); } bool DenyAccessToPath(const FilePath& path, const std::vector& sids, DWORD access_mask, DWORD inheritance, bool recursive) { return AddACEToPath(path, sids, access_mask, inheritance, recursive, DENY_ACCESS); } std::vector CloneSidVector(const std::vector& sids) { std::vector clone; clone.reserve(sids.size()); for (const Sid& sid : sids) { clone.push_back(sid.Clone()); } return clone; } void AppendSidVector(std::vector& base_sids, const std::vector& append_sids) { for (const Sid& sid : append_sids) { base_sids.push_back(sid.Clone()); } } } // namespace win } // namespace base