device_cloud_policy_manager_chromeos.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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/browser_process.h"
16#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h"
17#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
18#include "chrome/browser/chromeos/login/startup_utils.h"
19#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
20#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h"
21#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
22#include "chrome/browser/chromeos/policy/server_backed_device_state.h"
23#include "chrome/common/chrome_content_client.h"
24#include "chrome/common/pref_names.h"
25#include "chromeos/chromeos_constants.h"
26#include "chromeos/chromeos_switches.h"
27#include "chromeos/system/statistics_provider.h"
28#include "components/policy/core/common/cloud/cloud_policy_constants.h"
29#include "components/policy/core/common/cloud/cloud_policy_store.h"
30#include "components/policy/core/common/cloud/device_management_service.h"
31#include "components/policy/core/common/cloud/system_policy_request_context.h"
32#include "content/public/browser/browser_thread.h"
33#include "crypto/sha2.h"
34#include "policy/proto/device_management_backend.pb.h"
35#include "url/gurl.h"
36
37using content::BrowserThread;
38
39namespace em = enterprise_management;
40
41namespace policy {
42
43namespace {
44
45// Overridden no requisition value.
46const char kNoRequisition[] = "none";
47
48// Overridden no requisition value.
49const char kRemoraRequisition[] = "remora";
50
51// These are the machine serial number keys that we check in order until we
52// find a non-empty serial number. The VPD spec says the serial number should be
53// in the "serial_number" key for v2+ VPDs. However, legacy devices used a
54// different key to report their serial number, which we fall back to if
55// "serial_number" is not present.
56//
57// Product_S/N is still special-cased due to inconsistencies with serial
58// numbers on Lumpy devices: On these devices, serial_number is identical to
59// Product_S/N with an appended checksum. Unfortunately, the sticker on the
60// packaging doesn't include that checksum either (the sticker on the device
61// does though!). The former sticker is the source of the serial number used by
62// device management service, so we prefer Product_S/N over serial number to
63// match the server.
64//
65// TODO(mnissler): Move serial_number back to the top once the server side uses
66// the correct serial number.
67const char* kMachineInfoSerialNumberKeys[] = {
68  "Product_S/N",    // Lumpy/Alex devices
69  "serial_number",  // VPD v2+ devices
70  "Product_SN",     // Mario
71  "sn",             // old ZGB devices (more recent ones use serial_number)
72};
73
74// Fetches a machine statistic value from StatisticsProvider, returns an empty
75// string on failure.
76std::string GetMachineStatistic(const std::string& key) {
77  std::string value;
78  chromeos::system::StatisticsProvider* provider =
79      chromeos::system::StatisticsProvider::GetInstance();
80  if (!provider->GetMachineStatistic(key, &value))
81    return std::string();
82
83  return value;
84}
85
86// Gets a machine flag from StatisticsProvider, returns the given
87// |default_value| if not present.
88bool GetMachineFlag(const std::string& key, bool default_value) {
89  bool value = default_value;
90  chromeos::system::StatisticsProvider* provider =
91      chromeos::system::StatisticsProvider::GetInstance();
92  if (!provider->GetMachineFlag(key, &value))
93    return default_value;
94
95  return value;
96}
97
98}  // namespace
99
100const int
101DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyTimeQuantumPower;
102
103const int
104DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyFutureQuanta;
105
106DeviceCloudPolicyManagerChromeOS::DeviceCloudPolicyManagerChromeOS(
107    scoped_ptr<DeviceCloudPolicyStoreChromeOS> store,
108    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
109    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
110    EnterpriseInstallAttributes* install_attributes)
111    : CloudPolicyManager(
112          PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType,
113                             std::string()),
114          store.get(),
115          task_runner,
116          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
117          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)),
118      device_store_(store.Pass()),
119      background_task_runner_(background_task_runner),
120      install_attributes_(install_attributes),
121      device_management_service_(NULL),
122      local_state_(NULL) {}
123
124DeviceCloudPolicyManagerChromeOS::~DeviceCloudPolicyManagerChromeOS() {}
125
126void DeviceCloudPolicyManagerChromeOS::Connect(
127    PrefService* local_state,
128    DeviceManagementService* device_management_service,
129    scoped_ptr<CloudPolicyClient::StatusProvider> device_status_provider) {
130  CHECK(!device_management_service_);
131  CHECK(device_management_service);
132  CHECK(local_state);
133
134  local_state_ = local_state;
135  device_management_service_ = device_management_service;
136  device_status_provider_ = device_status_provider.Pass();
137
138  InitalizeRequisition();
139  StartIfManaged();
140}
141
142void DeviceCloudPolicyManagerChromeOS::StartEnrollment(
143    const std::string& auth_token,
144    bool is_auto_enrollment,
145    const AllowedDeviceModes& allowed_device_modes,
146    const EnrollmentCallback& callback) {
147  CHECK(device_management_service_);
148  core()->Disconnect();
149
150  enrollment_handler_.reset(
151      new EnrollmentHandlerChromeOS(
152          device_store_.get(), install_attributes_, CreateClient(),
153          background_task_runner_, auth_token,
154          install_attributes_->GetDeviceId(), is_auto_enrollment,
155          GetDeviceRequisition(), GetCurrentDeviceStateKey(),
156          allowed_device_modes,
157          base::Bind(&DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted,
158                     base::Unretained(this), callback)));
159  enrollment_handler_->StartEnrollment();
160}
161
162void DeviceCloudPolicyManagerChromeOS::CancelEnrollment() {
163  if (enrollment_handler_.get()) {
164    enrollment_handler_.reset();
165    StartIfManaged();
166  }
167}
168
169std::string DeviceCloudPolicyManagerChromeOS::GetDeviceRequisition() const {
170  std::string requisition;
171  const PrefService::Preference* pref = local_state_->FindPreference(
172      prefs::kDeviceEnrollmentRequisition);
173  if (!pref->IsDefaultValue())
174    pref->GetValue()->GetAsString(&requisition);
175
176  if (requisition == kNoRequisition)
177    requisition.clear();
178
179  return requisition;
180}
181
182void DeviceCloudPolicyManagerChromeOS::SetDeviceRequisition(
183    const std::string& requisition) {
184  if (local_state_) {
185    if (requisition.empty()) {
186      local_state_->ClearPref(prefs::kDeviceEnrollmentRequisition);
187      local_state_->ClearPref(prefs::kDeviceEnrollmentAutoStart);
188      local_state_->ClearPref(prefs::kDeviceEnrollmentCanExit);
189    } else {
190      local_state_->SetString(prefs::kDeviceEnrollmentRequisition, requisition);
191      if (requisition == kNoRequisition) {
192        local_state_->ClearPref(prefs::kDeviceEnrollmentAutoStart);
193        local_state_->ClearPref(prefs::kDeviceEnrollmentCanExit);
194      } else {
195        local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
196        local_state_->SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
197      }
198    }
199  }
200}
201
202bool DeviceCloudPolicyManagerChromeOS::ShouldAutoStartEnrollment() const {
203  std::string restore_mode = GetRestoreMode();
204  if (restore_mode == kDeviceStateRestoreModeReEnrollmentRequested ||
205      restore_mode == kDeviceStateRestoreModeReEnrollmentEnforced) {
206    return true;
207  }
208
209  if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentAutoStart))
210    return local_state_->GetBoolean(prefs::kDeviceEnrollmentAutoStart);
211
212  return GetMachineFlag(chromeos::system::kOemIsEnterpriseManagedKey, false);
213}
214
215bool DeviceCloudPolicyManagerChromeOS::CanExitEnrollment() const {
216  if (GetRestoreMode() == kDeviceStateRestoreModeReEnrollmentEnforced)
217    return false;
218
219  if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentCanExit))
220    return local_state_->GetBoolean(prefs::kDeviceEnrollmentCanExit);
221
222  return GetMachineFlag(chromeos::system::kOemCanExitEnterpriseEnrollmentKey,
223                        true);
224}
225
226std::string
227DeviceCloudPolicyManagerChromeOS::GetForcedEnrollmentDomain() const {
228  const base::DictionaryValue* device_state_dict =
229      local_state_->GetDictionary(prefs::kServerBackedDeviceState);
230  std::string management_domain;
231  device_state_dict->GetString(kDeviceStateManagementDomain,
232                               &management_domain);
233  return management_domain;
234}
235
236void DeviceCloudPolicyManagerChromeOS::Shutdown() {
237  CloudPolicyManager::Shutdown();
238  device_status_provider_.reset();
239}
240
241void DeviceCloudPolicyManagerChromeOS::OnStoreLoaded(CloudPolicyStore* store) {
242  CloudPolicyManager::OnStoreLoaded(store);
243
244  if (!enrollment_handler_.get())
245    StartIfManaged();
246}
247
248// static
249void DeviceCloudPolicyManagerChromeOS::RegisterPrefs(
250    PrefRegistrySimple* registry) {
251  registry->RegisterStringPref(prefs::kDeviceEnrollmentRequisition,
252                               std::string());
253  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentAutoStart, false);
254  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentCanExit, true);
255  registry->RegisterDictionaryPref(prefs::kServerBackedDeviceState);
256}
257
258// static
259std::string DeviceCloudPolicyManagerChromeOS::GetMachineID() {
260  std::string machine_id;
261  chromeos::system::StatisticsProvider* provider =
262      chromeos::system::StatisticsProvider::GetInstance();
263  for (size_t i = 0; i < arraysize(kMachineInfoSerialNumberKeys); i++) {
264    if (provider->GetMachineStatistic(kMachineInfoSerialNumberKeys[i],
265                                      &machine_id) &&
266        !machine_id.empty()) {
267      break;
268    }
269  }
270
271  if (machine_id.empty())
272    LOG(WARNING) << "Failed to get machine id.";
273
274  return machine_id;
275}
276
277// static
278std::string DeviceCloudPolicyManagerChromeOS::GetMachineModel() {
279  return GetMachineStatistic(chromeos::system::kHardwareClassKey);
280}
281
282// static
283std::string DeviceCloudPolicyManagerChromeOS::GetCurrentDeviceStateKey() {
284  std::vector<std::string> state_keys;
285  if (GetDeviceStateKeys(base::Time::Now(), &state_keys) &&
286      !state_keys.empty()) {
287    // The key for the current time is always the first one.
288    return state_keys[0];
289  }
290
291  return std::string();
292}
293
294scoped_ptr<CloudPolicyClient> DeviceCloudPolicyManagerChromeOS::CreateClient() {
295  scoped_refptr<net::URLRequestContextGetter> request_context =
296      new SystemPolicyRequestContext(
297          g_browser_process->system_request_context(), GetUserAgent());
298
299  scoped_ptr<CloudPolicyClient> client(
300      new CloudPolicyClient(GetMachineID(), GetMachineModel(),
301                            kPolicyVerificationKeyHash,
302                            USER_AFFILIATION_NONE,
303                            device_status_provider_.get(),
304                            device_management_service_,
305                            request_context));
306
307  // Set state keys to upload immediately after creation so the first policy
308  // fetch submits them to the server.
309  if (chromeos::AutoEnrollmentController::GetMode() ==
310      chromeos::AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT) {
311    std::vector<std::string> state_keys;
312    if (GetDeviceStateKeys(base::Time::Now(), &state_keys))
313      client->SetStateKeysToUpload(state_keys);
314  }
315
316  return client.Pass();
317}
318
319void DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted(
320    const EnrollmentCallback& callback,
321    EnrollmentStatus status) {
322  if (status.status() == EnrollmentStatus::STATUS_SUCCESS)
323    StartConnection(enrollment_handler_->ReleaseClient());
324  else
325    StartIfManaged();
326
327  enrollment_handler_.reset();
328  if (!callback.is_null())
329    callback.Run(status);
330}
331
332void DeviceCloudPolicyManagerChromeOS::StartIfManaged() {
333  if (device_management_service_ &&
334      local_state_ &&
335      store()->is_initialized() &&
336      store()->has_policy() &&
337      !service()) {
338    StartConnection(CreateClient());
339  }
340}
341
342void DeviceCloudPolicyManagerChromeOS::StartConnection(
343    scoped_ptr<CloudPolicyClient> client_to_connect) {
344  core()->Connect(client_to_connect.Pass());
345  core()->StartRefreshScheduler();
346  core()->TrackRefreshDelayPref(local_state_,
347                                prefs::kDevicePolicyRefreshRate);
348  attestation_policy_observer_.reset(
349      new chromeos::attestation::AttestationPolicyObserver(client()));
350}
351
352void DeviceCloudPolicyManagerChromeOS::InitalizeRequisition() {
353  // OEM statistics are only loaded when OOBE is not completed.
354  if (chromeos::StartupUtils::IsOobeCompleted())
355    return;
356
357  const PrefService::Preference* pref = local_state_->FindPreference(
358      prefs::kDeviceEnrollmentRequisition);
359  if (pref->IsDefaultValue()) {
360    std::string requisition =
361        GetMachineStatistic(chromeos::system::kOemDeviceRequisitionKey);
362
363    if (!requisition.empty()) {
364      local_state_->SetString(prefs::kDeviceEnrollmentRequisition,
365                              requisition);
366      if (requisition == kRemoraRequisition) {
367        local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
368        local_state_->SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
369      } else {
370        local_state_->SetBoolean(
371            prefs::kDeviceEnrollmentAutoStart,
372            GetMachineFlag(chromeos::system::kOemIsEnterpriseManagedKey,
373                           false));
374        local_state_->SetBoolean(
375            prefs::kDeviceEnrollmentCanExit,
376            GetMachineFlag(chromeos::system::kOemCanExitEnterpriseEnrollmentKey,
377                           false));
378      }
379    }
380  }
381}
382
383std::string DeviceCloudPolicyManagerChromeOS::GetRestoreMode() const {
384  const base::DictionaryValue* device_state_dict =
385      local_state_->GetDictionary(prefs::kServerBackedDeviceState);
386  std::string restore_mode;
387  device_state_dict->GetString(kDeviceStateRestoreMode, &restore_mode);
388  return restore_mode;
389}
390
391// static
392bool DeviceCloudPolicyManagerChromeOS::GetDeviceStateKeys(
393    const base::Time& timestamp,
394    std::vector<std::string>* state_keys) {
395  state_keys->clear();
396
397  std::string disk_serial_number =
398      GetMachineStatistic(chromeos::system::kDiskSerialNumber);
399  if (disk_serial_number.empty()) {
400    LOG(ERROR) << "Missing disk serial number";
401    return false;
402  }
403
404  std::string machine_id = GetMachineID();
405  if (machine_id.empty())
406    return false;
407
408  // Tolerate missing group code keys, some old devices may not have it.
409  std::string group_code_key =
410      GetMachineStatistic(chromeos::system::kOffersGroupCodeKey);
411
412  // Get the current time in quantized form.
413  int64 quantum_size = GG_INT64_C(1) << kDeviceStateKeyTimeQuantumPower;
414  int64 quantized_time =
415      (timestamp - base::Time::UnixEpoch()).InSeconds() & ~(quantum_size - 1);
416  for (int i = 0; i < kDeviceStateKeyFutureQuanta; ++i) {
417    state_keys->push_back(crypto::SHA256HashString(
418        crypto::SHA256HashString(group_code_key) +
419        crypto::SHA256HashString(disk_serial_number) +
420        crypto::SHA256HashString(machine_id) +
421        crypto::SHA256HashString(base::Int64ToString(quantized_time))));
422    quantized_time += quantum_size;
423  }
424
425  return true;
426}
427
428}  // namespace policy
429