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 "chrome/browser/browser_process.h"
10#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
11#include "chromeos/dbus/session_manager_client.h"
12#include "components/ownership/owner_key_util.h"
13#include "components/policy/core/common/cloud/device_management_service.h"
14#include "components/policy/core/common/external_data_fetcher.h"
15#include "components/policy/core/common/policy_map.h"
16#include "components/policy/core/common/policy_types.h"
17#include "policy/proto/cloud_policy.pb.h"
18#include "policy/proto/device_management_backend.pb.h"
19
20namespace em = enterprise_management;
21
22namespace policy {
23
24DeviceLocalAccountPolicyStore::DeviceLocalAccountPolicyStore(
25    const std::string& account_id,
26    chromeos::SessionManagerClient* session_manager_client,
27    chromeos::DeviceSettingsService* device_settings_service,
28    scoped_refptr<base::SequencedTaskRunner> background_task_runner)
29    : UserCloudPolicyStoreBase(background_task_runner),
30      account_id_(account_id),
31      session_manager_client_(session_manager_client),
32      device_settings_service_(device_settings_service),
33      weak_factory_(this) {}
34
35DeviceLocalAccountPolicyStore::~DeviceLocalAccountPolicyStore() {}
36
37void DeviceLocalAccountPolicyStore::Load() {
38  weak_factory_.InvalidateWeakPtrs();
39  session_manager_client_->RetrieveDeviceLocalAccountPolicy(
40      account_id_,
41      base::Bind(&DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob,
42                 weak_factory_.GetWeakPtr()));
43}
44
45void DeviceLocalAccountPolicyStore::Store(
46    const em::PolicyFetchResponse& policy) {
47  weak_factory_.InvalidateWeakPtrs();
48  CheckKeyAndValidate(
49      true,
50      make_scoped_ptr(new em::PolicyFetchResponse(policy)),
51      base::Bind(&DeviceLocalAccountPolicyStore::StoreValidatedPolicy,
52                 weak_factory_.GetWeakPtr()));
53}
54
55void DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob(
56    const std::string& policy_blob) {
57  if (policy_blob.empty()) {
58    status_ = CloudPolicyStore::STATUS_LOAD_ERROR;
59    NotifyStoreError();
60  } else {
61    scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
62    if (policy->ParseFromString(policy_blob)) {
63      CheckKeyAndValidate(
64          false,
65          policy.Pass(),
66          base::Bind(&DeviceLocalAccountPolicyStore::UpdatePolicy,
67                     weak_factory_.GetWeakPtr()));
68    } else {
69      status_ = CloudPolicyStore::STATUS_PARSE_ERROR;
70      NotifyStoreError();
71    }
72  }
73}
74
75void DeviceLocalAccountPolicyStore::UpdatePolicy(
76    UserCloudPolicyValidator* validator) {
77  validation_status_ = validator->status();
78  if (!validator->success()) {
79    status_ = STATUS_VALIDATION_ERROR;
80    NotifyStoreError();
81    return;
82  }
83
84  InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
85  status_ = STATUS_OK;
86  NotifyStoreLoaded();
87}
88
89void DeviceLocalAccountPolicyStore::StoreValidatedPolicy(
90    UserCloudPolicyValidator* validator) {
91  if (!validator->success()) {
92    status_ = CloudPolicyStore::STATUS_VALIDATION_ERROR;
93    validation_status_ = validator->status();
94    NotifyStoreError();
95    return;
96  }
97
98  std::string policy_blob;
99  if (!validator->policy()->SerializeToString(&policy_blob)) {
100    status_ = CloudPolicyStore::STATUS_SERIALIZE_ERROR;
101    NotifyStoreError();
102    return;
103  }
104
105  session_manager_client_->StoreDeviceLocalAccountPolicy(
106      account_id_,
107      policy_blob,
108      base::Bind(&DeviceLocalAccountPolicyStore::HandleStoreResult,
109                 weak_factory_.GetWeakPtr()));
110}
111
112void DeviceLocalAccountPolicyStore::HandleStoreResult(bool success) {
113  if (!success) {
114    status_ = CloudPolicyStore::STATUS_STORE_ERROR;
115    NotifyStoreError();
116  } else {
117    Load();
118  }
119}
120
121void DeviceLocalAccountPolicyStore::CheckKeyAndValidate(
122    bool valid_timestamp_required,
123    scoped_ptr<em::PolicyFetchResponse> policy,
124    const UserCloudPolicyValidator::CompletionCallback& callback) {
125  device_settings_service_->GetOwnershipStatusAsync(
126      base::Bind(&DeviceLocalAccountPolicyStore::Validate,
127                 weak_factory_.GetWeakPtr(),
128                 valid_timestamp_required,
129                 base::Passed(&policy),
130                 callback));
131}
132
133void DeviceLocalAccountPolicyStore::Validate(
134    bool valid_timestamp_required,
135    scoped_ptr<em::PolicyFetchResponse> policy_response,
136    const UserCloudPolicyValidator::CompletionCallback& callback,
137    chromeos::DeviceSettingsService::OwnershipStatus ownership_status) {
138  DCHECK_NE(chromeos::DeviceSettingsService::OWNERSHIP_UNKNOWN,
139            ownership_status);
140  const em::PolicyData* device_policy_data =
141      device_settings_service_->policy_data();
142  scoped_refptr<ownership::PublicKey> key =
143      device_settings_service_->GetPublicKey();
144  if (!key.get() || !key->is_loaded() || !device_policy_data) {
145    status_ = CloudPolicyStore::STATUS_BAD_STATE;
146    NotifyStoreLoaded();
147    return;
148  }
149
150  scoped_ptr<UserCloudPolicyValidator> validator(
151      UserCloudPolicyValidator::Create(policy_response.Pass(),
152                                       background_task_runner()));
153  validator->ValidateUsername(account_id_, false);
154  validator->ValidatePolicyType(dm_protocol::kChromePublicAccountPolicyType);
155  // The timestamp is verified when storing a new policy downloaded from the
156  // server but not when loading a cached policy from disk.
157  // See SessionManagerOperation::ValidateDeviceSettings for the rationale.
158  validator->ValidateAgainstCurrentPolicy(
159      policy(),
160      valid_timestamp_required
161          ? CloudPolicyValidatorBase::TIMESTAMP_REQUIRED
162          : CloudPolicyValidatorBase::TIMESTAMP_NOT_REQUIRED,
163      CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED);
164
165  // Validate the DMToken to match what device policy has.
166  validator->ValidateDMToken(device_policy_data->request_token(),
167                             CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
168
169  validator->ValidatePayload();
170  policy::BrowserPolicyConnectorChromeOS* connector =
171      g_browser_process->platform_part()->browser_policy_connector_chromeos();
172  validator->ValidateSignature(key->as_string(),
173                               GetPolicyVerificationKey(),
174                               connector->GetEnterpriseDomain(),
175                               false);
176  validator.release()->StartValidation(callback);
177}
178
179}  // namespace policy
180