blob: 1ba00440ba95f5d2369f0eebc8cf40f1819a52f7 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS 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 "login_manager/user_policy_service.h"
#include <stdint.h>
#include <sys/stat.h>
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/logging.h>
#include "bindings/device_management_backend.pb.h"
#include "login_manager/dbus_error_types.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_store.h"
#include "login_manager/system_utils.h"
namespace em = enterprise_management;
namespace login_manager {
UserPolicyService::UserPolicyService(
scoped_ptr<PolicyStore> policy_store,
scoped_ptr<PolicyKey> policy_key,
const base::FilePath& key_copy_path,
SystemUtils* system_utils)
: PolicyService(std::move(policy_store), policy_key.get()),
scoped_policy_key_(std::move(policy_key)),
key_copy_path_(key_copy_path),
system_utils_(system_utils) {
}
UserPolicyService::~UserPolicyService() {
}
void UserPolicyService::PersistKeyCopy() {
// Create a copy at |key_copy_path_| that is readable by chronos.
if (key_copy_path_.empty())
return;
if (scoped_policy_key_->IsPopulated()) {
base::FilePath dir(key_copy_path_.DirName());
base::CreateDirectory(dir);
mode_t mode = S_IRWXU | S_IXGRP | S_IXOTH;
chmod(dir.value().c_str(), mode);
const std::vector<uint8_t>& key = scoped_policy_key_->public_key_der();
system_utils_->AtomicFileWrite(key_copy_path_,
std::string(key.begin(), key.end()));
mode = S_IRUSR | S_IRGRP | S_IROTH;
chmod(key_copy_path_.value().c_str(), mode);
} else {
// Remove the key if it has been cleared.
system_utils_->RemoveFile(key_copy_path_);
}
}
bool UserPolicyService::Store(const uint8_t* policy_blob,
uint32_t len,
const Completion& completion,
int flags) {
em::PolicyFetchResponse policy;
em::PolicyData policy_data;
if (!policy.ParseFromArray(policy_blob, len) || !policy.has_policy_data() ||
!policy_data.ParseFromString(policy.policy_data())) {
static const char msg[] = "Unable to parse policy protobuf.";
LOG(ERROR) << msg;
Error error(dbus_error::kSigDecodeFail, msg);
completion.Run(error);
return false;
}
// Allow to switch to unmanaged state even if no signature is present.
if (policy_data.state() == em::PolicyData::UNMANAGED &&
!policy.has_policy_data_signature()) {
// Also clear the key.
if (key()->IsPopulated()) {
key()->ClobberCompromisedKey(std::vector<uint8_t>());
PersistKey();
}
store()->Set(policy);
PersistPolicyWithCompletion(completion);
return true;
}
return PolicyService::StorePolicy(policy, completion, flags);
}
void UserPolicyService::OnKeyPersisted(bool status) {
if (status)
PersistKeyCopy();
// Only notify the delegate after writing the copy, so that chrome can find
// the file after being notified that the key is ready.
PolicyService::OnKeyPersisted(status);
}
} // namespace login_manager