blob: bad9a11c011fcf3d11e26c145e378bcbd27a601e [file] [log] [blame]
// Copyright 2016 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 "chromeos/dbus/fake_auth_policy_client.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/md5.h"
#include "base/path_service.h"
#include "base/strings/string_split.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "components/policy/proto/cloud_policy.pb.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "components/signin/core/account_id/account_id.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace em = enterprise_management;
namespace {
const size_t kMaxMachineNameLength = 15;
const char kInvalidMachineNameCharacters[] = "\\/:*?\"<>|";
// Delay operations to be more realistic.
constexpr int kOperationDelaySeconds = 3;
// Drop stub policy file of |policy_type| at |policy_path| containing
// |serialized_payload|.
bool WritePolicyFile(const base::FilePath& policy_path,
const std::string& serialized_payload,
const std::string& policy_type) {
base::PlatformThread::Sleep(
base::TimeDelta::FromSeconds(kOperationDelaySeconds));
em::PolicyData data;
data.set_policy_value(serialized_payload);
data.set_policy_type(policy_type);
em::PolicyFetchResponse response;
CHECK(data.SerializeToString(response.mutable_policy_data()));
std::string serialized_response;
CHECK(response.SerializeToString(&serialized_response));
if (!base::CreateDirectory(policy_path.DirName()))
return false;
// Note that in theory there could be a short time window in which a
// concurrent reader sees a partial (and thus invalid) file, but given the
// small file size that seems very unlikely in practice.
const int bytes_written = base::WriteFile(
policy_path, serialized_response.c_str(), serialized_response.size());
if (bytes_written < 0)
return false;
return bytes_written == static_cast<int>(serialized_response.size());
}
void PostDelayedClosure(base::OnceClosure closure) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, std::move(closure),
base::TimeDelta::FromSeconds(kOperationDelaySeconds));
}
} // namespace
namespace chromeos {
FakeAuthPolicyClient::FakeAuthPolicyClient() {}
FakeAuthPolicyClient::~FakeAuthPolicyClient() {}
void FakeAuthPolicyClient::Init(dbus::Bus* bus) {}
void FakeAuthPolicyClient::JoinAdDomain(const std::string& machine_name,
const std::string& user_principal_name,
int password_fd,
JoinCallback callback) {
authpolicy::ErrorType error = authpolicy::ERROR_NONE;
if (!started_) {
LOG(ERROR) << "authpolicyd not started";
error = authpolicy::ERROR_DBUS_FAILURE;
} else if (machine_name.size() > kMaxMachineNameLength) {
error = authpolicy::ERROR_MACHINE_NAME_TOO_LONG;
} else if (machine_name.empty() ||
machine_name.find_first_of(kInvalidMachineNameCharacters) !=
std::string::npos) {
error = authpolicy::ERROR_BAD_MACHINE_NAME;
} else {
std::vector<std::string> parts = base::SplitString(
user_principal_name, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (parts.size() != 2 || parts[0].empty() || parts[1].empty()) {
error = authpolicy::ERROR_PARSE_UPN_FAILED;
}
}
PostDelayedClosure(base::BindOnce(std::move(callback), error));
}
void FakeAuthPolicyClient::AuthenticateUser(
const std::string& user_principal_name,
const std::string& object_guid,
int password_fd,
AuthCallback callback) {
authpolicy::ErrorType error = authpolicy::ERROR_NONE;
authpolicy::ActiveDirectoryAccountData account_data;
if (!started_) {
LOG(ERROR) << "authpolicyd not started";
error = authpolicy::ERROR_DBUS_FAILURE;
} else {
if (auth_error_ == authpolicy::ERROR_NONE) {
if (object_guid.empty())
account_data.set_account_id(base::MD5String(user_principal_name));
else
account_data.set_account_id(object_guid);
}
error = auth_error_;
}
PostDelayedClosure(base::BindOnce(std::move(callback), error, account_data));
}
void FakeAuthPolicyClient::RefreshDevicePolicy(RefreshPolicyCallback callback) {
if (!started_) {
LOG(ERROR) << "authpolicyd not started";
std::move(callback).Run(false);
return;
}
base::FilePath policy_path;
if (!PathService::Get(chromeos::FILE_OWNER_KEY, &policy_path)) {
std::move(callback).Run(false);
return;
}
policy_path = policy_path.DirName().AppendASCII("stub_device_policy");
em::ChromeDeviceSettingsProto policy;
std::string payload;
CHECK(policy.SerializeToString(&payload));
// Drop file for SessionManagerClientStubImpl to read.
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
base::TaskTraits()
.WithShutdownBehavior(
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
.WithPriority(base::TaskPriority::BACKGROUND)
.MayBlock(),
base::BindOnce(&WritePolicyFile, policy_path, payload,
"google/chromeos/device"),
std::move(callback));
}
void FakeAuthPolicyClient::RefreshUserPolicy(const AccountId& account_id,
RefreshPolicyCallback callback) {
if (!started_) {
LOG(ERROR) << "authpolicyd not started";
std::move(callback).Run(false);
return;
}
base::FilePath policy_path;
if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &policy_path)) {
std::move(callback).Run(false);
return;
}
const cryptohome::Identification cryptohome_identification(account_id);
const std::string sanitized_username =
chromeos::CryptohomeClient::GetStubSanitizedUsername(
cryptohome_identification);
policy_path = policy_path.AppendASCII(sanitized_username);
policy_path = policy_path.AppendASCII("stub_policy");
em::CloudPolicySettings policy;
std::string payload;
CHECK(policy.SerializeToString(&payload));
// Drop file for SessionManagerClientStubImpl to read.
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
base::TaskTraits()
.WithShutdownBehavior(
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
.WithPriority(base::TaskPriority::BACKGROUND)
.MayBlock(),
base::BindOnce(&WritePolicyFile, policy_path, payload,
"google/chromeos/user"),
std::move(callback));
}
} // namespace chromeos