user_cloud_policy_manager_chromeos.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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/user_cloud_policy_manager_chromeos.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/logging.h" 10#include "base/metrics/histogram.h" 11#include "base/metrics/sparse_histogram.h" 12#include "base/sequenced_task_runner.h" 13#include "base/values.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" 16#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 17#include "chrome/browser/chromeos/policy/wildcard_login_checker.h" 18#include "chrome/browser/chromeos/profiles/profile_helper.h" 19#include "chrome/browser/lifetime/application_lifetime.h" 20#include "chrome/common/chrome_content_client.h" 21#include "components/policy/core/common/cloud/cloud_external_data_manager.h" 22#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" 23#include "components/policy/core/common/cloud/device_management_service.h" 24#include "components/policy/core/common/cloud/system_policy_request_context.h" 25#include "components/policy/core/common/policy_map.h" 26#include "components/policy/core/common/policy_pref_names.h" 27#include "components/policy/core/common/policy_types.h" 28#include "components/user_manager/user_manager.h" 29#include "net/url_request/url_request_context_getter.h" 30#include "policy/policy_constants.h" 31#include "url/gurl.h" 32 33namespace em = enterprise_management; 34 35namespace policy { 36 37namespace { 38 39// UMA histogram names. 40const char kUMADelayInitialization[] = 41 "Enterprise.UserPolicyChromeOS.DelayInitialization"; 42const char kUMAInitialFetchClientError[] = 43 "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError"; 44const char kUMAInitialFetchDelayClientRegister[] = 45 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister"; 46const char kUMAInitialFetchDelayOAuth2Token[] = 47 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token"; 48const char kUMAInitialFetchDelayPolicyFetch[] = 49 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch"; 50const char kUMAInitialFetchDelayTotal[] = 51 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal"; 52const char kUMAInitialFetchOAuth2Error[] = 53 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error"; 54const char kUMAInitialFetchOAuth2NetworkError[] = 55 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError"; 56 57void OnWildcardCheckCompleted(const std::string& username, 58 WildcardLoginChecker::Result result) { 59 if (result == WildcardLoginChecker::RESULT_BLOCKED) { 60 LOG(ERROR) << "Online wildcard login check failed, terminating session."; 61 62 // TODO(mnissler): This only removes the user pod from the login screen, but 63 // the cryptohome remains. This is because deleting the cryptohome for a 64 // logged-in session is not possible. Fix this either by delaying the 65 // cryptohome deletion operation or by getting rid of the in-session 66 // wildcard check. 67 user_manager::UserManager::Get()->RemoveUserFromList(username); 68 chrome::AttemptUserExit(); 69 } 70} 71 72} // namespace 73 74UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS( 75 scoped_ptr<CloudPolicyStore> store, 76 scoped_ptr<CloudExternalDataManager> external_data_manager, 77 const base::FilePath& component_policy_cache_path, 78 bool wait_for_policy_fetch, 79 base::TimeDelta initial_policy_fetch_timeout, 80 const scoped_refptr<base::SequencedTaskRunner>& task_runner, 81 const scoped_refptr<base::SequencedTaskRunner>& file_task_runner, 82 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) 83 : CloudPolicyManager( 84 PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()), 85 store.get(), 86 task_runner, 87 file_task_runner, 88 io_task_runner), 89 store_(store.Pass()), 90 external_data_manager_(external_data_manager.Pass()), 91 component_policy_cache_path_(component_policy_cache_path), 92 wait_for_policy_fetch_(wait_for_policy_fetch), 93 policy_fetch_timeout_(false, false) { 94 time_init_started_ = base::Time::Now(); 95 if (wait_for_policy_fetch_ && !initial_policy_fetch_timeout.is_max()) { 96 policy_fetch_timeout_.Start( 97 FROM_HERE, 98 initial_policy_fetch_timeout, 99 base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout, 100 base::Unretained(this))); 101 } 102} 103 104UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {} 105 106void UserCloudPolicyManagerChromeOS::Connect( 107 PrefService* local_state, 108 DeviceManagementService* device_management_service, 109 scoped_refptr<net::URLRequestContextGetter> system_request_context, 110 UserAffiliation user_affiliation) { 111 DCHECK(device_management_service); 112 DCHECK(local_state); 113 local_state_ = local_state; 114 scoped_refptr<net::URLRequestContextGetter> request_context; 115 if (system_request_context.get()) { 116 // |system_request_context| can be null for tests. 117 // Use the system request context here instead of a context derived 118 // from the Profile because Connect() is called before the profile is 119 // fully initialized (required so we can perform the initial policy load). 120 // TODO(atwilson): Change this to use a UserPolicyRequestContext once 121 // Connect() is called after profile initialization. http://crbug.com/323591 122 request_context = new SystemPolicyRequestContext( 123 system_request_context, GetUserAgent()); 124 } 125 scoped_ptr<CloudPolicyClient> cloud_policy_client( 126 new CloudPolicyClient(std::string(), std::string(), 127 kPolicyVerificationKeyHash, user_affiliation, 128 NULL, device_management_service, 129 request_context)); 130 core()->Connect(cloud_policy_client.Pass()); 131 client()->AddObserver(this); 132 133 external_data_manager_->Connect(request_context); 134 135 CreateComponentCloudPolicyService(component_policy_cache_path_, 136 request_context); 137 138 // Determine the next step after the CloudPolicyService initializes. 139 if (service()->IsInitializationComplete()) { 140 OnInitializationCompleted(service()); 141 } else { 142 service()->AddObserver(this); 143 } 144} 145 146void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable( 147 const std::string& access_token) { 148 access_token_ = access_token; 149 150 if (!wildcard_username_.empty()) { 151 wildcard_login_checker_.reset(new WildcardLoginChecker()); 152 wildcard_login_checker_->StartWithAccessToken( 153 access_token, 154 base::Bind(&OnWildcardCheckCompleted, wildcard_username_)); 155 } 156 157 if (service() && service()->IsInitializationComplete() && 158 client() && !client()->is_registered()) { 159 OnOAuth2PolicyTokenFetched( 160 access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 161 } 162} 163 164bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const { 165 return client() && client()->is_registered(); 166} 167 168void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck( 169 const std::string& username) { 170 DCHECK(access_token_.empty()); 171 wildcard_username_ = username; 172} 173 174void UserCloudPolicyManagerChromeOS::Shutdown() { 175 if (client()) 176 client()->RemoveObserver(this); 177 if (service()) 178 service()->RemoveObserver(this); 179 token_fetcher_.reset(); 180 external_data_manager_->Disconnect(); 181 CloudPolicyManager::Shutdown(); 182} 183 184bool UserCloudPolicyManagerChromeOS::IsInitializationComplete( 185 PolicyDomain domain) const { 186 if (!CloudPolicyManager::IsInitializationComplete(domain)) 187 return false; 188 if (domain == POLICY_DOMAIN_CHROME) 189 return !wait_for_policy_fetch_; 190 return true; 191} 192 193void UserCloudPolicyManagerChromeOS::OnInitializationCompleted( 194 CloudPolicyService* cloud_policy_service) { 195 DCHECK_EQ(service(), cloud_policy_service); 196 cloud_policy_service->RemoveObserver(this); 197 198 time_init_completed_ = base::Time::Now(); 199 UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization, 200 time_init_completed_ - time_init_started_); 201 202 // If the CloudPolicyClient isn't registered at this stage then it needs an 203 // OAuth token for the initial registration. 204 // 205 // If |wait_for_policy_fetch_| is true then Profile initialization is blocking 206 // on the initial policy fetch, so the token must be fetched immediately. 207 // In that case, the signin Profile is used to authenticate a Gaia request to 208 // fetch a refresh token, and then the policy token is fetched. 209 // 210 // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder 211 // service will eventually call OnAccessTokenAvailable() once an access token 212 // is available. That call may have already happened while waiting for 213 // initialization of the CloudPolicyService, so in that case check if an 214 // access token is already available. 215 if (!client()->is_registered()) { 216 if (wait_for_policy_fetch_) { 217 FetchPolicyOAuthTokenUsingSigninProfile(); 218 } else if (!access_token_.empty()) { 219 OnAccessTokenAvailable(access_token_); 220 } 221 } 222 223 if (!wait_for_policy_fetch_) { 224 // If this isn't blocking on a policy fetch then 225 // CloudPolicyManager::OnStoreLoaded() already published the cached policy. 226 // Start the refresh scheduler now, which will eventually refresh the 227 // cached policy or make the first fetch once the OAuth2 token is 228 // available. 229 StartRefreshSchedulerIfReady(); 230 } 231} 232 233void UserCloudPolicyManagerChromeOS::OnPolicyFetched( 234 CloudPolicyClient* client) { 235 // No action required. If we're blocked on a policy fetch, we'll learn about 236 // completion of it through OnInitialPolicyFetchComplete(). 237} 238 239void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged( 240 CloudPolicyClient* cloud_policy_client) { 241 DCHECK_EQ(client(), cloud_policy_client); 242 243 if (wait_for_policy_fetch_) { 244 time_client_registered_ = base::Time::Now(); 245 if (!time_token_available_.is_null()) { 246 UMA_HISTOGRAM_MEDIUM_TIMES( 247 kUMAInitialFetchDelayClientRegister, 248 time_client_registered_ - time_token_available_); 249 } 250 251 // If we're blocked on the policy fetch, now is a good time to issue it. 252 if (client()->is_registered()) { 253 service()->RefreshPolicy( 254 base::Bind( 255 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete, 256 base::Unretained(this))); 257 } else { 258 // If the client has switched to not registered, we bail out as this 259 // indicates the cloud policy setup flow has been aborted. 260 CancelWaitForPolicyFetch(); 261 } 262 } 263} 264 265void UserCloudPolicyManagerChromeOS::OnClientError( 266 CloudPolicyClient* cloud_policy_client) { 267 DCHECK_EQ(client(), cloud_policy_client); 268 if (wait_for_policy_fetch_) { 269 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError, 270 cloud_policy_client->status()); 271 } 272 CancelWaitForPolicyFetch(); 273} 274 275void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() { 276 CloudPolicyManager::OnComponentCloudPolicyUpdated(); 277 StartRefreshSchedulerIfReady(); 278} 279 280void UserCloudPolicyManagerChromeOS::GetChromePolicy(PolicyMap* policy_map) { 281 CloudPolicyManager::GetChromePolicy(policy_map); 282 283 // If the store has a verified policy blob received from the server then apply 284 // the defaults for policies that haven't been configured by the administrator 285 // given that this is an enterprise user. 286 if (!store()->has_policy()) 287 return; 288 SetEnterpriseUsersDefaults(policy_map); 289} 290 291void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() { 292 scoped_refptr<net::URLRequestContextGetter> signin_context; 293 Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile(); 294 if (signin_profile) 295 signin_context = signin_profile->GetRequestContext(); 296 if (!signin_context.get()) { 297 LOG(ERROR) << "No signin Profile for policy oauth token fetch!"; 298 OnOAuth2PolicyTokenFetched( 299 std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 300 return; 301 } 302 303 token_fetcher_.reset(new PolicyOAuth2TokenFetcher( 304 signin_context.get(), 305 g_browser_process->system_request_context(), 306 base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched, 307 base::Unretained(this)))); 308 token_fetcher_->Start(); 309} 310 311void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched( 312 const std::string& policy_token, 313 const GoogleServiceAuthError& error) { 314 DCHECK(!client()->is_registered()); 315 time_token_available_ = base::Time::Now(); 316 if (wait_for_policy_fetch_) { 317 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token, 318 time_token_available_ - time_init_completed_); 319 } 320 321 if (error.state() == GoogleServiceAuthError::NONE) { 322 // Start client registration. Either OnRegistrationStateChanged() or 323 // OnClientError() will be called back. 324 client()->Register(em::DeviceRegisterRequest::USER, policy_token, 325 std::string(), false, std::string(), std::string()); 326 } else { 327 // Failed to get a token, stop waiting and use an empty policy. 328 CancelWaitForPolicyFetch(); 329 330 UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error, 331 error.state(), 332 GoogleServiceAuthError::NUM_STATES); 333 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { 334 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError, 335 error.network_error()); 336 } 337 } 338 339 token_fetcher_.reset(); 340} 341 342void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete( 343 bool success) { 344 const base::Time now = base::Time::Now(); 345 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayPolicyFetch, 346 now - time_client_registered_); 347 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayTotal, 348 now - time_init_started_); 349 CancelWaitForPolicyFetch(); 350} 351 352void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() { 353 if (!wait_for_policy_fetch_) 354 return; 355 LOG(WARNING) << "Timed out while waiting for the initial policy fetch. " 356 << "The first session will start without policy."; 357 CancelWaitForPolicyFetch(); 358} 359 360void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() { 361 if (!wait_for_policy_fetch_) 362 return; 363 364 wait_for_policy_fetch_ = false; 365 policy_fetch_timeout_.Stop(); 366 CheckAndPublishPolicy(); 367 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler 368 // can be started. 369 StartRefreshSchedulerIfReady(); 370} 371 372void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() { 373 if (core()->refresh_scheduler()) 374 return; // Already started. 375 376 if (wait_for_policy_fetch_) 377 return; // Still waiting for the initial, blocking fetch. 378 379 if (!service() || !local_state_) 380 return; // Not connected. 381 382 if (component_policy_service() && 383 !component_policy_service()->is_initialized()) { 384 // If the client doesn't have the list of components to fetch yet then don't 385 // start the scheduler. The |component_policy_service_| will call back into 386 // OnComponentCloudPolicyUpdated() once it's ready. 387 return; 388 } 389 390 core()->StartRefreshScheduler(); 391 core()->TrackRefreshDelayPref(local_state_, 392 policy_prefs::kUserPolicyRefreshRate); 393} 394 395} // namespace policy 396