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 "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