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