device_cloud_policy_manager_chromeos.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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_cloud_policy_manager_chromeos.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/command_line.h"
10#include "base/port.h"
11#include "base/prefs/pref_registry_simple.h"
12#include "base/prefs/pref_service.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/time/time.h"
15#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h"
16#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
17#include "chrome/browser/chromeos/login/startup_utils.h"
18#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
19#include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
20#include "chrome/common/pref_names.h"
21#include "chromeos/chromeos_constants.h"
22#include "chromeos/chromeos_switches.h"
23#include "chromeos/system/statistics_provider.h"
24#include "components/policy/core/common/cloud/cloud_policy_store.h"
25#include "content/public/browser/browser_thread.h"
26#include "crypto/sha2.h"
27#include "policy/proto/device_management_backend.pb.h"
28#include "url/gurl.h"
29
30using content::BrowserThread;
31
32namespace em = enterprise_management;
33
34namespace policy {
35
36namespace {
37
38const char kNoRequisition[] = "none";
39const char kRemoraRequisition[] = "remora";
40const char kSharkRequisition[] = "shark";
41
42// These are the machine serial number keys that we check in order until we
43// find a non-empty serial number. The VPD spec says the serial number should be
44// in the "serial_number" key for v2+ VPDs. However, legacy devices used a
45// different key to report their serial number, which we fall back to if
46// "serial_number" is not present.
47//
48// Product_S/N is still special-cased due to inconsistencies with serial
49// numbers on Lumpy devices: On these devices, serial_number is identical to
50// Product_S/N with an appended checksum. Unfortunately, the sticker on the
51// packaging doesn't include that checksum either (the sticker on the device
52// does though!). The former sticker is the source of the serial number used by
53// device management service, so we prefer Product_S/N over serial number to
54// match the server.
55//
56// TODO(mnissler): Move serial_number back to the top once the server side uses
57// the correct serial number.
58const char* kMachineInfoSerialNumberKeys[] = {
59  "Product_S/N",    // Lumpy/Alex devices
60  "serial_number",  // VPD v2+ devices
61  "Product_SN",     // Mario
62  "sn",             // old ZGB devices (more recent ones use serial_number)
63};
64
65// Fetches a machine statistic value from StatisticsProvider, returns an empty
66// string on failure.
67std::string GetMachineStatistic(const std::string& key) {
68  std::string value;
69  chromeos::system::StatisticsProvider* provider =
70      chromeos::system::StatisticsProvider::GetInstance();
71  if (!provider->GetMachineStatistic(key, &value))
72    return std::string();
73
74  return value;
75}
76
77// Gets a machine flag from StatisticsProvider, returns the given
78// |default_value| if not present.
79bool GetMachineFlag(const std::string& key, bool default_value) {
80  bool value = default_value;
81  chromeos::system::StatisticsProvider* provider =
82      chromeos::system::StatisticsProvider::GetInstance();
83  if (!provider->GetMachineFlag(key, &value))
84    return default_value;
85
86  return value;
87}
88
89// Checks whether forced re-enrollment is enabled.
90bool ForcedReEnrollmentEnabled() {
91  return chromeos::AutoEnrollmentController::GetMode() ==
92         chromeos::AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT;
93}
94
95}  // namespace
96
97DeviceCloudPolicyManagerChromeOS::DeviceCloudPolicyManagerChromeOS(
98    scoped_ptr<DeviceCloudPolicyStoreChromeOS> store,
99    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
100    ServerBackedStateKeysBroker* state_keys_broker)
101    : CloudPolicyManager(
102          PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType,
103                             std::string()),
104          store.get(),
105          task_runner,
106          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
107          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)),
108      device_store_(store.Pass()),
109      state_keys_broker_(state_keys_broker),
110      local_state_(NULL) {
111}
112
113DeviceCloudPolicyManagerChromeOS::~DeviceCloudPolicyManagerChromeOS() {}
114
115void DeviceCloudPolicyManagerChromeOS::Initialize(PrefService* local_state) {
116  CHECK(local_state);
117
118  local_state_ = local_state;
119
120  state_keys_update_subscription_ = state_keys_broker_->RegisterUpdateCallback(
121      base::Bind(&DeviceCloudPolicyManagerChromeOS::OnStateKeysUpdated,
122                 base::Unretained(this)));
123
124  InitializeRequisition();
125}
126
127std::string DeviceCloudPolicyManagerChromeOS::GetDeviceRequisition() const {
128  std::string requisition;
129  const PrefService::Preference* pref = local_state_->FindPreference(
130      prefs::kDeviceEnrollmentRequisition);
131  if (!pref->IsDefaultValue())
132    pref->GetValue()->GetAsString(&requisition);
133
134  if (requisition == kNoRequisition)
135    requisition.clear();
136
137  return requisition;
138}
139
140void DeviceCloudPolicyManagerChromeOS::SetDeviceRequisition(
141    const std::string& requisition) {
142  VLOG(1) << "SetDeviceRequisition " << requisition;
143  if (local_state_) {
144    if (requisition.empty()) {
145      local_state_->ClearPref(prefs::kDeviceEnrollmentRequisition);
146      local_state_->ClearPref(prefs::kDeviceEnrollmentAutoStart);
147      local_state_->ClearPref(prefs::kDeviceEnrollmentCanExit);
148    } else {
149      local_state_->SetString(prefs::kDeviceEnrollmentRequisition, requisition);
150      if (requisition == kNoRequisition) {
151        local_state_->ClearPref(prefs::kDeviceEnrollmentAutoStart);
152        local_state_->ClearPref(prefs::kDeviceEnrollmentCanExit);
153      } else {
154        local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
155        local_state_->SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
156      }
157    }
158  }
159}
160
161bool DeviceCloudPolicyManagerChromeOS::IsRemoraRequisition() const {
162  return GetDeviceRequisition() == kRemoraRequisition;
163}
164
165bool DeviceCloudPolicyManagerChromeOS::IsSharkRequisition() const {
166  return GetDeviceRequisition() == kSharkRequisition;
167}
168
169void DeviceCloudPolicyManagerChromeOS::Shutdown() {
170  state_keys_update_subscription_.reset();
171  CloudPolicyManager::Shutdown();
172}
173
174// static
175void DeviceCloudPolicyManagerChromeOS::RegisterPrefs(
176    PrefRegistrySimple* registry) {
177  registry->RegisterStringPref(prefs::kDeviceEnrollmentRequisition,
178                               std::string());
179  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentAutoStart, false);
180  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentCanExit, true);
181  registry->RegisterDictionaryPref(prefs::kServerBackedDeviceState);
182}
183
184// static
185std::string DeviceCloudPolicyManagerChromeOS::GetMachineID() {
186  std::string machine_id;
187  chromeos::system::StatisticsProvider* provider =
188      chromeos::system::StatisticsProvider::GetInstance();
189  for (size_t i = 0; i < arraysize(kMachineInfoSerialNumberKeys); i++) {
190    if (provider->GetMachineStatistic(kMachineInfoSerialNumberKeys[i],
191                                      &machine_id) &&
192        !machine_id.empty()) {
193      break;
194    }
195  }
196
197  if (machine_id.empty())
198    LOG(WARNING) << "Failed to get machine id.";
199
200  return machine_id;
201}
202
203// static
204std::string DeviceCloudPolicyManagerChromeOS::GetMachineModel() {
205  return GetMachineStatistic(chromeos::system::kHardwareClassKey);
206}
207
208void DeviceCloudPolicyManagerChromeOS::StartConnection(
209    scoped_ptr<CloudPolicyClient> client_to_connect,
210    scoped_ptr<CloudPolicyClient::StatusProvider> device_status_provider) {
211  CHECK(!service());
212
213  device_status_provider_ = device_status_provider.Pass();
214
215  // Set state keys here so the first policy fetch submits them to the server.
216  if (ForcedReEnrollmentEnabled())
217    client_to_connect->SetStateKeysToUpload(state_keys_broker_->state_keys());
218
219  core()->Connect(client_to_connect.Pass());
220  core()->StartRefreshScheduler();
221  core()->TrackRefreshDelayPref(local_state_,
222                                prefs::kDevicePolicyRefreshRate);
223  attestation_policy_observer_.reset(
224      new chromeos::attestation::AttestationPolicyObserver(client()));
225}
226
227void DeviceCloudPolicyManagerChromeOS::OnStateKeysUpdated() {
228  if (client() && ForcedReEnrollmentEnabled())
229    client()->SetStateKeysToUpload(state_keys_broker_->state_keys());
230}
231
232void DeviceCloudPolicyManagerChromeOS::InitializeRequisition() {
233  // OEM statistics are only loaded when OOBE is not completed.
234  if (chromeos::StartupUtils::IsOobeCompleted())
235    return;
236
237  const PrefService::Preference* pref = local_state_->FindPreference(
238      prefs::kDeviceEnrollmentRequisition);
239  if (pref->IsDefaultValue()) {
240    std::string requisition =
241        GetMachineStatistic(chromeos::system::kOemDeviceRequisitionKey);
242
243    if (!requisition.empty()) {
244      local_state_->SetString(prefs::kDeviceEnrollmentRequisition,
245                              requisition);
246      if (requisition == kRemoraRequisition ||
247          requisition == kSharkRequisition) {
248        local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
249        local_state_->SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
250      } else {
251        local_state_->SetBoolean(
252            prefs::kDeviceEnrollmentAutoStart,
253            GetMachineFlag(chromeos::system::kOemIsEnterpriseManagedKey,
254                           false));
255        local_state_->SetBoolean(
256            prefs::kDeviceEnrollmentCanExit,
257            GetMachineFlag(chromeos::system::kOemCanExitEnterpriseEnrollmentKey,
258                           false));
259      }
260    }
261  }
262}
263
264}  // namespace policy
265