blob: 098ec2fe276ce97aeec505c8f4ffd76d31f4edd6 [file] [log] [blame]
// Copyright 2019 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 "chrome/chrome_cleaner/engines/target/engine_requests_proxy.h"
#include <sddl.h>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/win/registry.h"
#include "chrome/chrome_cleaner/strings/string16_embedded_nulls.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace chrome_cleaner {
namespace {
template <typename ResultType>
void SaveBoolAndCopyableDataCallback(bool* out_success,
ResultType* out_result,
base::OnceClosure quit_closure,
bool success,
const ResultType& result) {
*out_success = success;
*out_result = result;
std::move(quit_closure).Run();
}
void SaveOpenReadOnlyRegistryCallback(uint32_t* out_return_code,
HANDLE* result_holder,
base::OnceClosure quit_closure,
uint32_t return_code,
HANDLE handle) {
*out_return_code = return_code;
*result_holder = std::move(handle);
std::move(quit_closure).Run();
}
void SaveBoolAndScheduledTasksCallback(
bool* out_success,
std::vector<TaskScheduler::TaskInfo>* out_tasks,
base::OnceClosure quit_closure,
bool in_success,
std::vector<mojom::ScheduledTaskPtr> in_tasks) {
out_tasks->clear();
out_tasks->reserve(in_tasks.size());
for (mojom::ScheduledTaskPtr& in_task : in_tasks) {
TaskScheduler::TaskInfo out_task;
out_task.name = std::move(in_task->name);
out_task.description = std::move(in_task->description);
out_task.exec_actions.reserve(in_task->actions.size());
for (mojom::ScheduledTaskActionPtr& in_task_action : in_task->actions) {
TaskScheduler::TaskExecAction out_action;
out_action.application_path = std::move(in_task_action->path);
out_action.working_dir = std::move(in_task_action->working_dir);
out_action.arguments = std::move(in_task_action->arguments);
out_task.exec_actions.push_back(std::move(out_action));
}
out_tasks->push_back(std::move(out_task));
}
*out_success = in_success;
std::move(quit_closure).Run();
}
void SaveUserInformationCallback(bool* out_success,
mojom::UserInformation* out_result,
base::OnceClosure quit_closure,
bool in_success,
mojom::UserInformationPtr in_result) {
*out_success = in_success;
out_result->name = std::move(in_result->name);
out_result->domain = std::move(in_result->domain);
out_result->account_type = in_result->account_type;
std::move(quit_closure).Run();
}
} // namespace
EngineRequestsProxy::EngineRequestsProxy(
mojom::EngineRequestsAssociatedPtr engine_requests_ptr,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: engine_requests_ptr_(std::move(engine_requests_ptr)),
task_runner_(task_runner) {}
void EngineRequestsProxy::UnbindRequestsPtr() {
engine_requests_ptr_.reset();
}
bool EngineRequestsProxy::GetKnownFolderPath(mojom::KnownFolder folder_id,
base::FilePath* folder_path) {
if (folder_path == nullptr) {
LOG(ERROR) << "GetKnownFolderPathCallback given a null folder_path";
return false;
}
bool result;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetKnownFolderPath,
base::Unretained(this), folder_id),
base::BindOnce(&SaveBoolAndCopyableDataCallback<base::FilePath>, &result,
folder_path));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
bool EngineRequestsProxy::GetProcesses(
std::vector<base::ProcessId>* processes) {
if (processes == nullptr) {
LOG(ERROR) << "GetProcessesCallback received a null processes";
return false;
}
bool success = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetProcesses,
base::Unretained(this)),
base::BindOnce(
&SaveBoolAndCopyableDataCallback<std::vector<base::ProcessId>>,
&success, processes));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return success;
}
bool EngineRequestsProxy::GetTasks(
std::vector<TaskScheduler::TaskInfo>* task_list) {
if (task_list == nullptr) {
LOG(ERROR) << "GetTasksCallback received a null task_list";
return false;
}
bool result = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetTasks,
base::Unretained(this)),
base::BindOnce(&SaveBoolAndScheduledTasksCallback, &result, task_list));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
bool EngineRequestsProxy::GetProcessImagePath(base::ProcessId pid,
base::FilePath* image_path) {
if (image_path == nullptr) {
LOG(ERROR) << "GetProcessImagePathCallback received a null file_info";
return false;
}
bool result = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetProcessImagePath,
base::Unretained(this), pid),
base::BindOnce(&SaveBoolAndCopyableDataCallback<base::FilePath>, &result,
image_path));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
bool EngineRequestsProxy::GetLoadedModules(
base::ProcessId pid,
std::vector<base::string16>* modules) {
if (modules == nullptr) {
LOG(ERROR) << "GetLoadedModulesCallback received a null modules";
return false;
}
bool result = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetLoadedModules,
base::Unretained(this), pid),
base::BindOnce(
&SaveBoolAndCopyableDataCallback<std::vector<base::string16>>,
&result, modules));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
bool EngineRequestsProxy::GetProcessCommandLine(base::ProcessId pid,
base::string16* command_line) {
if (command_line == nullptr) {
LOG(ERROR) << "GetProcessCommandLineCallback received a null command_line";
return false;
}
bool result = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetProcessCommandLine,
base::Unretained(this), pid),
base::BindOnce(&SaveBoolAndCopyableDataCallback<base::string16>, &result,
command_line));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
bool EngineRequestsProxy::GetUserInfoFromSID(
const SID* const sid,
mojom::UserInformation* user_info) {
if (user_info == nullptr) {
LOG(ERROR) << "GetUserInfoFromSIDCallback given a null buffer";
return false;
}
bool result = false;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxGetUserInfoFromSID,
base::Unretained(this), sid),
base::BindOnce(&SaveUserInformationCallback, &result, user_info));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return false;
}
return result;
}
uint32_t EngineRequestsProxy::OpenReadOnlyRegistry(
HANDLE root_key,
const base::string16& sub_key,
uint32_t dw_access,
HANDLE* registry_handle) {
uint32_t return_code;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxOpenReadOnlyRegistry,
base::Unretained(this), root_key, sub_key, dw_access),
base::BindOnce(&SaveOpenReadOnlyRegistryCallback, &return_code,
registry_handle));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
return call_status.error_code;
}
return return_code;
}
uint32_t EngineRequestsProxy::NtOpenReadOnlyRegistry(
HANDLE root_key,
const String16EmbeddedNulls& sub_key,
uint32_t dw_access,
HANDLE* registry_handle) {
uint32_t return_code;
MojoCallStatus call_status = SyncSandboxRequest(
this,
base::BindOnce(&EngineRequestsProxy::SandboxNtOpenReadOnlyRegistry,
base::Unretained(this), root_key, sub_key, dw_access),
base::BindOnce(&SaveOpenReadOnlyRegistryCallback, &return_code,
registry_handle));
if (call_status.state == MojoCallStatus::MOJO_CALL_ERROR) {
if (registry_handle)
*registry_handle = INVALID_HANDLE_VALUE;
return call_status.error_code;
}
return return_code;
}
EngineRequestsProxy::~EngineRequestsProxy() = default;
MojoCallStatus EngineRequestsProxy::SandboxGetKnownFolderPath(
mojom::KnownFolder folder_id,
mojom::EngineRequests::SandboxGetKnownFolderPathCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetKnownFolderPath called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetKnownFolderPath(folder_id,
std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetProcesses(
mojom::EngineRequests::SandboxGetProcessesCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetProcesses called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetProcesses(std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetTasks(
mojom::EngineRequests::SandboxGetTasksCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetTasks called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetTasks(std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetProcessImagePath(
base::ProcessId pid,
mojom::EngineRequests::SandboxGetProcessImagePathCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetProcessImagePath called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetProcessImagePath(pid,
std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetLoadedModules(
base::ProcessId pid,
mojom::EngineRequests::SandboxGetLoadedModulesCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetLoadedModules called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetLoadedModules(pid,
std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetProcessCommandLine(
base::ProcessId pid,
mojom::EngineRequestsProxy::SandboxGetProcessCommandLineCallback
result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetProcessCommandLine called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxGetProcessCommandLine(
pid, std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxGetUserInfoFromSID(
const SID* const sid,
mojom::EngineRequests::SandboxGetUserInfoFromSIDCallback result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxGetUserInfoFromSID called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
wchar_t* sid_buffer = nullptr;
if (!::ConvertSidToStringSidW(const_cast<SID*>(sid), &sid_buffer)) {
PLOG(ERROR) << "Unable to convert |sid| to a string.";
return MojoCallStatus::Failure(SandboxErrorCode::BAD_SID);
}
auto mojom_string_sid = mojom::StringSid::New(sid_buffer);
LocalFree(sid_buffer);
engine_requests_ptr_->SandboxGetUserInfoFromSID(std::move(mojom_string_sid),
std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxOpenReadOnlyRegistry(
HANDLE root_key,
const base::string16& sub_key,
uint32_t dw_access,
mojom::EngineRequests::SandboxOpenReadOnlyRegistryCallback
result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxOpenReadOnlyRegistry called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxOpenReadOnlyRegistry(
root_key, sub_key, dw_access, std::move(result_callback));
return MojoCallStatus::Success();
}
MojoCallStatus EngineRequestsProxy::SandboxNtOpenReadOnlyRegistry(
HANDLE root_key,
const String16EmbeddedNulls& sub_key,
uint32_t dw_access,
mojom::EngineRequests::SandboxNtOpenReadOnlyRegistryCallback
result_callback) {
if (!engine_requests_ptr_.is_bound()) {
LOG(ERROR) << "SandboxNtOpenReadOnlyRegistry called without bound pointer";
return MojoCallStatus::Failure(SandboxErrorCode::INTERNAL_ERROR);
}
engine_requests_ptr_->SandboxNtOpenReadOnlyRegistry(
root_key, sub_key, dw_access, std::move(result_callback));
return MojoCallStatus::Success();
}
} // namespace chrome_cleaner