device_local_account_policy_store.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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