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