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