1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "base/values.h" 10#include "chrome/browser/policy/cloud/device_management_service.h" 11#include "chrome/browser/policy/external_data_fetcher.h" 12#include "chrome/browser/policy/policy_types.h" 13#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 14#include "chromeos/dbus/power_policy_controller.h" 15#include "chromeos/dbus/session_manager_client.h" 16#include "policy/policy_constants.h" 17#include "policy/proto/cloud_policy.pb.h" 18 19namespace em = enterprise_management; 20 21namespace policy { 22 23DeviceLocalAccountPolicyStore::DeviceLocalAccountPolicyStore( 24 const std::string& account_id, 25 chromeos::SessionManagerClient* session_manager_client, 26 chromeos::DeviceSettingsService* device_settings_service) 27 : account_id_(account_id), 28 session_manager_client_(session_manager_client), 29 device_settings_service_(device_settings_service), 30 weak_factory_(this) {} 31 32DeviceLocalAccountPolicyStore::~DeviceLocalAccountPolicyStore() {} 33 34void DeviceLocalAccountPolicyStore::Load() { 35 weak_factory_.InvalidateWeakPtrs(); 36 session_manager_client_->RetrieveDeviceLocalAccountPolicy( 37 account_id_, 38 base::Bind(&DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob, 39 weak_factory_.GetWeakPtr())); 40} 41 42void DeviceLocalAccountPolicyStore::Store( 43 const em::PolicyFetchResponse& policy) { 44 weak_factory_.InvalidateWeakPtrs(); 45 CheckKeyAndValidate( 46 make_scoped_ptr(new em::PolicyFetchResponse(policy)), 47 base::Bind(&DeviceLocalAccountPolicyStore::StoreValidatedPolicy, 48 weak_factory_.GetWeakPtr())); 49} 50 51void DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob( 52 const std::string& policy_blob) { 53 if (policy_blob.empty()) { 54 status_ = CloudPolicyStore::STATUS_LOAD_ERROR; 55 NotifyStoreError(); 56 } else { 57 scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse()); 58 if (policy->ParseFromString(policy_blob)) { 59 CheckKeyAndValidate( 60 policy.Pass(), 61 base::Bind(&DeviceLocalAccountPolicyStore::UpdatePolicy, 62 weak_factory_.GetWeakPtr())); 63 } else { 64 status_ = CloudPolicyStore::STATUS_PARSE_ERROR; 65 NotifyStoreError(); 66 } 67 } 68} 69 70void DeviceLocalAccountPolicyStore::UpdatePolicy( 71 UserCloudPolicyValidator* validator) { 72 validation_status_ = validator->status(); 73 if (!validator->success()) { 74 status_ = STATUS_VALIDATION_ERROR; 75 NotifyStoreError(); 76 return; 77 } 78 79 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); 80 // Exit the session when the lid is closed. The default behavior is to 81 // suspend while leaving the session running, which is not desirable for 82 // public sessions. 83 policy_map_.Set(key::kLidCloseAction, 84 POLICY_LEVEL_MANDATORY, 85 POLICY_SCOPE_USER, 86 base::Value::CreateIntegerValue( 87 chromeos::PowerPolicyController::ACTION_STOP_SESSION), 88 NULL); 89 90 // Force the |ShelfAutoHideBehavior| policy to |Never|, ensuring that the ash 91 // shelf does not auto-hide. 92 policy_map_.Set(key::kShelfAutoHideBehavior, 93 POLICY_LEVEL_MANDATORY, 94 POLICY_SCOPE_USER, 95 Value::CreateStringValue("Never"), 96 NULL); 97 // Force the |ShowLogoutButtonInTray| policy to |true|, ensuring that a big, 98 // red logout button is shown in the ash system tray. 99 policy_map_.Set(key::kShowLogoutButtonInTray, 100 POLICY_LEVEL_MANDATORY, 101 POLICY_SCOPE_USER, 102 Value::CreateBooleanValue(true), 103 NULL); 104 // Restrict device-local accounts to hosted apps for now (i.e. no extensions, 105 // packaged apps etc.) for security/privacy reasons (i.e. we'd like to 106 // prevent the admin from stealing private information from random people). 107 scoped_ptr<base::ListValue> allowed_extension_types(new base::ListValue()); 108 allowed_extension_types->AppendString("hosted_app"); 109 policy_map_.Set(key::kExtensionAllowedTypes, 110 POLICY_LEVEL_MANDATORY, 111 POLICY_SCOPE_USER, 112 allowed_extension_types.release(), 113 NULL); 114 115 status_ = STATUS_OK; 116 NotifyStoreLoaded(); 117} 118 119void DeviceLocalAccountPolicyStore::StoreValidatedPolicy( 120 UserCloudPolicyValidator* validator) { 121 if (!validator->success()) { 122 status_ = CloudPolicyStore::STATUS_VALIDATION_ERROR; 123 validation_status_ = validator->status(); 124 NotifyStoreError(); 125 return; 126 } 127 128 std::string policy_blob; 129 if (!validator->policy()->SerializeToString(&policy_blob)) { 130 status_ = CloudPolicyStore::STATUS_SERIALIZE_ERROR; 131 NotifyStoreError(); 132 return; 133 } 134 135 session_manager_client_->StoreDeviceLocalAccountPolicy( 136 account_id_, 137 policy_blob, 138 base::Bind(&DeviceLocalAccountPolicyStore::HandleStoreResult, 139 weak_factory_.GetWeakPtr())); 140} 141 142void DeviceLocalAccountPolicyStore::HandleStoreResult(bool success) { 143 if (!success) { 144 status_ = CloudPolicyStore::STATUS_STORE_ERROR; 145 NotifyStoreError(); 146 } else { 147 Load(); 148 } 149} 150 151void DeviceLocalAccountPolicyStore::CheckKeyAndValidate( 152 scoped_ptr<em::PolicyFetchResponse> policy, 153 const UserCloudPolicyValidator::CompletionCallback& callback) { 154 device_settings_service_->GetOwnershipStatusAsync( 155 base::Bind(&DeviceLocalAccountPolicyStore::Validate, 156 weak_factory_.GetWeakPtr(), 157 base::Passed(&policy), 158 callback)); 159} 160 161void DeviceLocalAccountPolicyStore::Validate( 162 scoped_ptr<em::PolicyFetchResponse> policy_response, 163 const UserCloudPolicyValidator::CompletionCallback& callback, 164 chromeos::DeviceSettingsService::OwnershipStatus ownership_status, 165 bool is_owner) { 166 DCHECK_NE(chromeos::DeviceSettingsService::OWNERSHIP_UNKNOWN, 167 ownership_status); 168 scoped_refptr<chromeos::OwnerKey> key = 169 device_settings_service_->GetOwnerKey(); 170 if (!key.get() || !key->public_key()) { 171 status_ = CloudPolicyStore::STATUS_BAD_STATE; 172 NotifyStoreLoaded(); 173 return; 174 } 175 176 scoped_ptr<UserCloudPolicyValidator> validator( 177 UserCloudPolicyValidator::Create(policy_response.Pass())); 178 validator->ValidateUsername(account_id_); 179 validator->ValidatePolicyType(dm_protocol::kChromePublicAccountPolicyType); 180 validator->ValidateAgainstCurrentPolicy( 181 policy(), 182 CloudPolicyValidatorBase::TIMESTAMP_REQUIRED, 183 CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); 184 validator->ValidatePayload(); 185 validator->ValidateSignature(*key->public_key(), false); 186 validator.release()->StartValidation(callback); 187} 188 189} // namespace policy 190