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