enrollment_handler_chromeos.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
10d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// Copyright (c) 2012 The Chromium Authors. All rights reserved. 20d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// Use of this source code is governed by a BSD-style license that can be 30d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// found in the LICENSE file. 40d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 50d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h" 60d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 70d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "base/bind.h" 80d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "base/command_line.h" 90d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "base/logging.h" 100d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "base/message_loop/message_loop.h" 110d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/browser_process.h" 120d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" 130d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" 140d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 150d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" 160d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "chromeos/chromeos_switches.h" 170d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "components/policy/core/common/cloud/cloud_policy_constants.h" 180d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "google_apis/gaia/gaia_urls.h" 190d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "net/http/http_status_code.h" 200d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin#include "policy/proto/device_management_backend.pb.h" 210d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 220d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinnamespace em = enterprise_management; 230d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 240d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinnamespace policy { 250d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 260d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinnamespace { 270d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 280d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// Retry for InstallAttrs initialization every 500ms. 290d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinconst int kLockRetryIntervalMs = 500; 300d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// Maximum time to retry InstallAttrs initialization before we give up. 310d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinconst int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes. 320d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 330d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// Testing token used when the enrollment-skip-robot-auth is set to skip talking 340d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// to GAIA for an actual token. This is needed to be able to run against the 350d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin// testing DMServer implementations. 360d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinconst char kTestingRobotToken[] = "test-token"; 370d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 380d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} // namespace 390d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 400d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander GutkinEnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS( 410d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DeviceCloudPolicyStoreChromeOS* store, 420d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin EnterpriseInstallAttributes* install_attributes, 430d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin scoped_ptr<CloudPolicyClient> client, 440d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin scoped_refptr<base::SequencedTaskRunner> background_task_runner, 450d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const std::string& auth_token, 460d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const std::string& client_id, 470d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin bool is_auto_enrollment, 480d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const std::string& requisition, 490d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const std::string& current_state_key, 500d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const AllowedDeviceModes& allowed_device_modes, 510d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const EnrollmentCallback& completion_callback) 520d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin : store_(store), 530d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin install_attributes_(install_attributes), 540d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_(client.Pass()), 550d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin background_task_runner_(background_task_runner), 560d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin auth_token_(auth_token), 570d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_id_(client_id), 580d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin is_auto_enrollment_(is_auto_enrollment), 590d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin requisition_(requisition), 600d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin current_state_key_(current_state_key), 610d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin allowed_device_modes_(allowed_device_modes), 620d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin completion_callback_(completion_callback), 630d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin device_mode_(DEVICE_MODE_NOT_SET), 640d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_(STEP_PENDING), 650d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin lockbox_init_duration_(0), 660d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin weak_ptr_factory_(this) { 670d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK(!client_->is_registered()); 680d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(DM_STATUS_SUCCESS, client_->status()); 690d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin store_->AddObserver(this); 700d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_->AddObserver(this); 710d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_->AddNamespaceToFetch(PolicyNamespaceKey( 720d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin dm_protocol::kChromeDevicePolicyType, std::string())); 730d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 740d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 750d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander GutkinEnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() { 760d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin Stop(); 770d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin store_->RemoveObserver(this); 780d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 790d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 800d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::StartEnrollment() { 810d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(STEP_PENDING, enrollment_step_); 820d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_LOADING_STORE; 830d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin AttemptRegistration(); 840d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 850d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 860d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinscoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() { 870d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin Stop(); 880d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin return client_.Pass(); 890d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 900d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 910d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) { 920d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(client_.get(), client); 930d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_); 940d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 950d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_VALIDATION; 960d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 970d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // Validate the policy. 980d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin const em::PolicyFetchResponse* policy = client_->GetPolicyFor( 990d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType, std::string())); 1000d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (!policy) { 1010d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForFetchError( 1020d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DM_STATUS_RESPONSE_DECODING_ERROR)); 1030d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin return; 1040d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1050d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1060d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin scoped_ptr<DeviceCloudPolicyValidator> validator( 1070d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DeviceCloudPolicyValidator::Create( 1080d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin scoped_ptr<em::PolicyFetchResponse>( 1090d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin new em::PolicyFetchResponse(*policy)), 1100d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin background_task_runner_)); 1110d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1120d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(), 1130d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CloudPolicyValidatorBase::TIMESTAMP_REQUIRED); 1140d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1150d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // If this is re-enrollment, make sure that the new policy matches the 1160d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // previously-enrolled domain. 1170d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin std::string domain; 1180d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (install_attributes_->IsEnterpriseDevice()) { 1190d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin domain = install_attributes_->GetDomain(); 1200d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidateDomain(domain); 1210d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1220d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidateDMToken(client->dm_token(), 1230d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); 1240d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType); 1250d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidatePayload(); 1260d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // If |domain| is empty here, the policy validation code will just use the 1270d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // domain from the username field in the policy itself to do key validation. 1280d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // TODO(mnissler): Plumb the enrolling user's username into this object so 1290d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // we can validate the username on the resulting policy, and use the domain 1300d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // from that username to validate the key below (http://crbug.com/343074). 1310d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator->ValidateInitialKey(GetPolicyVerificationKey(), domain); 1320d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin validator.release()->StartValidation( 1330d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin base::Bind(&EnrollmentHandlerChromeOS::PolicyValidated, 1340d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin weak_ptr_factory_.GetWeakPtr())); 1350d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 1360d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1370d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnRegistrationStateChanged( 1380d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CloudPolicyClient* client) { 1390d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(client_.get(), client); 1400d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1410d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) { 1420d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_POLICY_FETCH, 1430d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin device_mode_ = client_->device_mode(); 1440d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (device_mode_ == DEVICE_MODE_NOT_SET) 1450d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin device_mode_ = DEVICE_MODE_ENTERPRISE; 1460d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (!allowed_device_modes_.test(device_mode_)) { 1470d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin LOG(ERROR) << "Bad device mode " << device_mode_; 1480d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForStatus( 1490d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE)); 1500d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin return; 1510d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1520d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_->FetchPolicy(); 1530d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } else { 1540d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin LOG(FATAL) << "Registration state changed to " << client_->is_registered() 1550d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin << " in step " << enrollment_step_; 1560d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1570d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 1580d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1590d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) { 1600d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(client_.get(), client); 1610d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1620d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (enrollment_step_ == STEP_ROBOT_AUTH_FETCH) { 1630d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin LOG(ERROR) << "API authentication code fetch failed: " 1640d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin << client_->status(); 1650d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForRobotAuthFetchError(client_->status())); 1660d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } else if (enrollment_step_ < STEP_POLICY_FETCH) { 1670d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForRegistrationError(client_->status())); 1680d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } else { 1690d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForFetchError(client_->status())); 1700d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1710d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 1720d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1730d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) { 1740d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(store_, store); 1750d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1760d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (enrollment_step_ == STEP_LOADING_STORE) { 1770d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // If the |store_| wasn't initialized when StartEnrollment() was 1780d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // called, then AttemptRegistration() bails silently. This gets 1790d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // registration rolling again after the store finishes loading. 1800d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin AttemptRegistration(); 1810d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } else if (enrollment_step_ == STEP_STORE_POLICY) { 1820d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS)); 1830d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 1840d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 1850d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1860d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) { 1870d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(store_, store); 1880d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForStoreError(store_->status(), 1890d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin store_->validation_status())); 1900d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 1910d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 1920d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::AttemptRegistration() { 1930d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(STEP_LOADING_STORE, enrollment_step_); 1940d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (store_->is_initialized()) { 1950d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_REGISTRATION; 1960d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_->Register(em::DeviceRegisterRequest::DEVICE, 1970d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin auth_token_, client_id_, is_auto_enrollment_, 1980d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin requisition_, current_state_key_); 1990d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 2000d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 2010d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2020d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::PolicyValidated( 2030d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DeviceCloudPolicyValidator* validator) { 2040d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(STEP_VALIDATION, enrollment_step_); 2050d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (validator->success()) { 2060d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin policy_ = validator->policy().Pass(); 2070d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin username_ = validator->policy_data()->username(); 2080d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin device_id_ = validator->policy_data()->device_id(); 2090d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2100d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin if (CommandLine::ForCurrentProcess()->HasSwitch( 2110d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin chromeos::switches::kEnterpriseEnrollmentSkipRobotAuth)) { 2120d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // For test purposes we allow enrollment to succeed without proper robot 2130d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // account and use the provided value as a token. 2140d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin refresh_token_ = kTestingRobotToken; 2150d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_LOCK_DEVICE, 2160d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin StartLockDevice(username_, device_mode_, device_id_); 2170d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin return; 2180d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 2190d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2200d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_ROBOT_AUTH_FETCH; 2210d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_->FetchRobotAuthCodes(auth_token_); 2220d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } else { 2230d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin ReportResult(EnrollmentStatus::ForValidationError(validator->status())); 2240d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin } 2250d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin} 2260d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2270d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkinvoid EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched( 2280d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CloudPolicyClient* client) { 2290d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin DCHECK_EQ(client_.get(), client); 2300d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_); 2310d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2320d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin enrollment_step_ = STEP_ROBOT_AUTH_REFRESH; 2330d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2340d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin gaia::OAuthClientInfo client_info; 2350d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_info.client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); 2360d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_info.client_secret = 2370d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin GaiaUrls::GetInstance()->oauth2_chrome_client_secret(); 2380d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin client_info.redirect_uri = "oob"; 2390d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin 2400d4c52358a1af421705c54bd8a9fdd8a30558a2eAlexander Gutkin // Use the system request context to avoid sending user cookies. 241 gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( 242 g_browser_process->system_request_context())); 243 gaia_oauth_client_->GetTokensFromAuthCode(client_info, 244 client->robot_api_auth_code(), 245 0 /* max_retries */, 246 this); 247} 248 249// GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched. 250void EnrollmentHandlerChromeOS::OnGetTokensResponse( 251 const std::string& refresh_token, 252 const std::string& access_token, 253 int expires_in_seconds) { 254 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 255 256 refresh_token_ = refresh_token; 257 258 enrollment_step_ = STEP_LOCK_DEVICE, 259 StartLockDevice(username_, device_mode_, device_id_); 260} 261 262// GaiaOAuthClient::Delegate 263void EnrollmentHandlerChromeOS::OnRefreshTokenResponse( 264 const std::string& access_token, 265 int expires_in_seconds) { 266 // We never use the code that should trigger this callback. 267 LOG(FATAL) << "Unexpected callback invoked"; 268} 269 270// GaiaOAuthClient::Delegate OAuth2 error when fetching refresh token request. 271void EnrollmentHandlerChromeOS::OnOAuthError() { 272 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 273 // OnOAuthError is only called if the request is bad (malformed) or the 274 // response is bad (empty access token returned). 275 LOG(ERROR) << "OAuth protocol error while fetching API refresh token."; 276 ReportResult( 277 EnrollmentStatus::ForRobotRefreshFetchError(net::HTTP_BAD_REQUEST)); 278} 279 280// GaiaOAuthClient::Delegate network error when fetching refresh token. 281void EnrollmentHandlerChromeOS::OnNetworkError(int response_code) { 282 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_); 283 LOG(ERROR) << "Network error while fetching API refresh token: " 284 << response_code; 285 ReportResult( 286 EnrollmentStatus::ForRobotRefreshFetchError(response_code)); 287} 288 289void EnrollmentHandlerChromeOS::StartLockDevice( 290 const std::string& user, 291 DeviceMode device_mode, 292 const std::string& device_id) { 293 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_); 294 // Since this method is also called directly. 295 weak_ptr_factory_.InvalidateWeakPtrs(); 296 297 install_attributes_->LockDevice( 298 user, device_mode, device_id, 299 base::Bind(&EnrollmentHandlerChromeOS::HandleLockDeviceResult, 300 weak_ptr_factory_.GetWeakPtr(), 301 user, 302 device_mode, 303 device_id)); 304} 305 306void EnrollmentHandlerChromeOS::HandleLockDeviceResult( 307 const std::string& user, 308 DeviceMode device_mode, 309 const std::string& device_id, 310 EnterpriseInstallAttributes::LockResult lock_result) { 311 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_); 312 switch (lock_result) { 313 case EnterpriseInstallAttributes::LOCK_SUCCESS: 314 // Get the token service so we can store our robot refresh token. 315 enrollment_step_ = STEP_STORE_ROBOT_AUTH; 316 chromeos::DeviceOAuth2TokenServiceFactory::Get()->SetAndSaveRefreshToken( 317 refresh_token_, 318 base::Bind(&EnrollmentHandlerChromeOS::HandleRobotAuthTokenStored, 319 weak_ptr_factory_.GetWeakPtr())); 320 return; 321 case EnterpriseInstallAttributes::LOCK_NOT_READY: 322 // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't 323 // succeeded by then show an error to the user and stop the enrollment. 324 if (lockbox_init_duration_ < kLockRetryTimeoutMs) { 325 // InstallAttributes not ready yet, retry later. 326 LOG(WARNING) << "Install Attributes not ready yet will retry in " 327 << kLockRetryIntervalMs << "ms."; 328 base::MessageLoop::current()->PostDelayedTask( 329 FROM_HERE, 330 base::Bind(&EnrollmentHandlerChromeOS::StartLockDevice, 331 weak_ptr_factory_.GetWeakPtr(), 332 user, device_mode, device_id), 333 base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs)); 334 lockbox_init_duration_ += kLockRetryIntervalMs; 335 } else { 336 ReportResult(EnrollmentStatus::ForStatus( 337 EnrollmentStatus::STATUS_LOCK_TIMEOUT)); 338 } 339 return; 340 case EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: 341 ReportResult(EnrollmentStatus::ForStatus( 342 EnrollmentStatus::STATUS_LOCK_ERROR)); 343 return; 344 case EnterpriseInstallAttributes::LOCK_WRONG_USER: 345 LOG(ERROR) << "Enrollment cannot proceed because the InstallAttrs " 346 << "has been locked already!"; 347 ReportResult(EnrollmentStatus::ForStatus( 348 EnrollmentStatus::STATUS_LOCK_WRONG_USER)); 349 return; 350 } 351 352 NOTREACHED() << "Invalid lock result " << lock_result; 353 ReportResult(EnrollmentStatus::ForStatus( 354 EnrollmentStatus::STATUS_LOCK_ERROR)); 355} 356 357void EnrollmentHandlerChromeOS::HandleRobotAuthTokenStored(bool result) { 358 CHECK_EQ(STEP_STORE_ROBOT_AUTH, enrollment_step_); 359 360 if (!result) { 361 LOG(ERROR) << "Failed to store API refresh token."; 362 ReportResult(EnrollmentStatus::ForStatus( 363 EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED)); 364 return; 365 } 366 367 enrollment_step_ = STEP_STORE_POLICY; 368 store_->InstallInitialPolicy(*policy_); 369} 370 371void EnrollmentHandlerChromeOS::Stop() { 372 if (client_.get()) 373 client_->RemoveObserver(this); 374 enrollment_step_ = STEP_FINISHED; 375 weak_ptr_factory_.InvalidateWeakPtrs(); 376 completion_callback_.Reset(); 377} 378 379void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) { 380 EnrollmentCallback callback = completion_callback_; 381 Stop(); 382 383 if (status.status() != EnrollmentStatus::STATUS_SUCCESS) { 384 LOG(WARNING) << "Enrollment failed: " << status.status() 385 << " " << status.client_status() 386 << " " << status.validation_status() 387 << " " << status.store_status(); 388 } 389 390 if (!callback.is_null()) 391 callback.Run(status); 392} 393 394} // namespace policy 395