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/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 
     33 namespace em = enterprise_management;
     34 
     35 namespace policy {
     36 
     37 namespace {
     38 
     39 // UMA histogram names.
     40 const char kUMADelayInitialization[] =
     41     "Enterprise.UserPolicyChromeOS.DelayInitialization";
     42 const char kUMAInitialFetchClientError[] =
     43     "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
     44 const char kUMAInitialFetchDelayClientRegister[] =
     45     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
     46 const char kUMAInitialFetchDelayOAuth2Token[] =
     47     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
     48 const char kUMAInitialFetchDelayPolicyFetch[] =
     49     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
     50 const char kUMAInitialFetchDelayTotal[] =
     51     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
     52 const char kUMAInitialFetchOAuth2Error[] =
     53     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
     54 const char kUMAInitialFetchOAuth2NetworkError[] =
     55     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
     56 
     57 void 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 
     74 UserCloudPolicyManagerChromeOS::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 
    104 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
    105 
    106 void 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 
    146 void 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 
    164 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
    165   return client() && client()->is_registered();
    166 }
    167 
    168 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
    169     const std::string& username) {
    170   DCHECK(access_token_.empty());
    171   wildcard_username_ = username;
    172 }
    173 
    174 void 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 
    184 bool 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 
    193 void 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 
    233 void 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 
    239 void 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 
    265 void 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 
    275 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
    276   CloudPolicyManager::OnComponentCloudPolicyUpdated();
    277   StartRefreshSchedulerIfReady();
    278 }
    279 
    280 void 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 
    291 void 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 
    311 void 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 
    342 void 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 
    352 void 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 
    360 void 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 
    372 void 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