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