blob: 1a134c671e29288bc7844183926a18677af4e620 [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 <sys/stat.h>
#include <string>
#include <vector>
#include <base/file_util.h>
#include <base/logging.h>
#include <base/message_loop/message_loop_proxy.h>
#include "login_manager/dbus_error_types.h"
#include "login_manager/device_management_backend.pb.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,
const scoped_refptr<base::MessageLoopProxy>& main_loop,
SystemUtils* system_utils)
: PolicyService(policy_store.Pass(), policy_key.get(), main_loop),
scoped_policy_key_(policy_key.Pass()),
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>& 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* policy_blob,
uint32 len,
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())) {
const char msg[] = "Unable to parse policy protobuf.";
LOG(ERROR) << msg;
Error error(dbus_error::kSigDecodeFail, msg);
completion->ReportFailure(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>());
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