blob: d75d3555d993e69dcc08a6e0443a0dd5f8278dab [file] [log] [blame]
// 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 <aclapi.h>
#include <windows.h>
#include <string>
#include "base/check.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_localalloc.h"
#include "base/win/win_util.h"
namespace base {
namespace win {
bool GrantAccessToPath(const FilePath& path,
const std::vector<Sid>& sids,
DWORD access_mask,
DWORD inheritance,
bool recursive) {
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<EXPLICIT_ACCESS> access_entries(sids.size());
auto entries_interator = access_entries.begin();
for (const Sid& sid : sids) {
EXPLICIT_ACCESS& new_access = *entries_interator++;
new_access.grfAccessMode = GRANT_ACCESS;
new_access.grfAccessPermissions = access_mask;
new_access.grfInheritance = inheritance;
::BuildTrusteeWithSid(&new_access.Trustee, sid.GetPSID());
}
PACL new_dacl = nullptr;
error = ::SetEntriesInAcl(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.IsValid()) {
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 win
} // namespace base