| // Copyright (c) 2011 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/device_policy.h" |
| |
| #include <string> |
| |
| #include <base/basictypes.h> |
| #include <base/file_path.h> |
| #include <base/file_util.h> |
| #include <base/logging.h> |
| |
| #include "login_manager/bindings/chrome_device_policy.pb.h" |
| #include "login_manager/bindings/device_management_backend.pb.h" |
| #include "login_manager/owner_key.h" |
| #include "login_manager/system_utils.h" |
| |
| namespace em = enterprise_management; |
| |
| namespace login_manager { |
| using google::protobuf::RepeatedPtrField; |
| using std::string; |
| |
| // static |
| const char DevicePolicy::kDefaultPath[] = "/var/lib/whitelist/policy"; |
| // static |
| const char DevicePolicy::kDevicePolicyType[] = "google/chromeos/device"; |
| |
| DevicePolicy::DevicePolicy(const FilePath& policy_path) |
| : policy_path_(policy_path) { |
| } |
| |
| DevicePolicy::~DevicePolicy() { |
| } |
| |
| bool DevicePolicy::LoadOrCreate() { |
| if (!file_util::PathExists(policy_path_)) |
| return true; |
| std::string polstr; |
| if (!file_util::ReadFileToString(policy_path_, &polstr) || polstr.empty()) { |
| PLOG(ERROR) << "Could not read policy off disk"; |
| return false; |
| } |
| if (!policy_.ParseFromString(polstr)) { |
| LOG(ERROR) << "Policy on disk could not be parsed!"; |
| return false; |
| } |
| return true; |
| } |
| |
| const enterprise_management::PolicyFetchResponse& DevicePolicy::Get() const { |
| return policy_; |
| } |
| |
| bool DevicePolicy::Persist() { |
| SystemUtils utils; |
| std::string polstr; |
| if (!policy_.SerializeToString(&polstr)) { |
| LOG(ERROR) << "Could not be serialize policy!"; |
| return false; |
| } |
| return utils.AtomicFileWrite(policy_path_, polstr.c_str(), polstr.length()); |
| } |
| |
| bool DevicePolicy::SerializeToString(std::string* output) const { |
| return policy_.SerializeToString(output); |
| } |
| |
| void DevicePolicy::Set( |
| const enterprise_management::PolicyFetchResponse& policy) { |
| policy_.Clear(); |
| // This can only fail if |policy| and |policy_| are different types. |
| policy_.CheckTypeAndMergeFrom(policy); |
| } |
| |
| bool DevicePolicy::StoreOwnerProperties(OwnerKey* key, |
| const std::string& current_user, |
| GError** error) { |
| em::PolicyData poldata; |
| if (policy_.has_policy_data()) |
| poldata.ParseFromString(policy_.policy_data()); |
| em::ChromeDeviceSettingsProto polval; |
| if (poldata.has_policy_type() && |
| poldata.policy_type() == kDevicePolicyType) { |
| if (poldata.has_policy_value()) |
| polval.ParseFromString(poldata.policy_value()); |
| } else { |
| poldata.set_policy_type(kDevicePolicyType); |
| } |
| // If there existed some device policy, we've got it now! |
| // Update the UserWhitelistProto inside the ChromeDeviceSettingsProto we made. |
| em::UserWhitelistProto* whitelist_proto = polval.mutable_user_whitelist(); |
| bool on_list = false; |
| const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist(); |
| for (RepeatedPtrField<string>::const_iterator it = whitelist.begin(); |
| it != whitelist.end(); |
| ++it) { |
| if (on_list = (current_user == *it)) |
| break; |
| } |
| if (poldata.has_username() && poldata.username() == current_user && on_list) |
| return true; // No changes are needed. |
| |
| if (!on_list) { |
| // Add owner to the whitelist and turn off whitelist enforcement if it is |
| // currently not explicitly turned on or off. |
| whitelist_proto->add_user_whitelist(current_user); |
| if (!polval.has_allow_new_users()) |
| polval.mutable_allow_new_users()->set_allow_new_users(true); |
| } |
| poldata.set_username(current_user); |
| |
| // We have now updated the whitelist and owner setting in |polval|. |
| // We need to put it into |poldata|, serialize that, sign it, and |
| // put both into |policy_|. |
| poldata.set_policy_value(polval.SerializeAsString()); |
| std::string new_data = poldata.SerializeAsString(); |
| std::vector<uint8> sig; |
| const uint8* data = reinterpret_cast<const uint8*>(new_data.c_str()); |
| if (!key || !key->Sign(data, new_data.length(), &sig)) { |
| SystemUtils utils; |
| const char err_msg[] = "Could not sign policy containing new owner data."; |
| LOG_IF(ERROR, error) << err_msg; |
| LOG_IF(WARNING, !error) << err_msg; |
| utils.SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg); |
| return false; |
| } |
| |
| em::PolicyFetchResponse new_policy; |
| new_policy.CheckTypeAndMergeFrom(policy_); |
| new_policy.set_policy_data(new_data); |
| new_policy.set_policy_data_signature( |
| std::string(reinterpret_cast<const char*>(&sig[0]), sig.size())); |
| Set(new_policy); |
| return true; |
| } |
| |
| bool DevicePolicy::CurrentUserIsOwner(const std::string& current_user) { |
| em::PolicyData poldata; |
| if (!policy_.has_policy_data()) |
| return false; |
| if (poldata.ParseFromString(policy_.policy_data())) { |
| return (!poldata.has_request_token() && |
| poldata.has_username() && |
| poldata.username() == current_user); |
| } |
| return false; |
| } |
| |
| } // namespace login_manager |