| // 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/file_util.h> |
| #include <base/logging.h> |
| #include <base/message_loop/message_loop_proxy.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, |
| 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_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, |
| 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_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 |