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/policy/browser_policy_connector.h"
      6 
      7 #include <algorithm>
      8 #include <iterator>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/command_line.h"
     13 #include "base/files/file_path.h"
     14 #include "base/logging.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/path_service.h"
     17 #include "base/prefs/pref_registry_simple.h"
     18 #include "base/prefs/pref_service.h"
     19 #include "base/strings/string_util.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "chrome/browser/browser_process.h"
     22 #include "chrome/browser/policy/async_policy_provider.h"
     23 #include "chrome/browser/policy/cloud/cloud_policy_client.h"
     24 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
     25 #include "chrome/browser/policy/cloud/cloud_policy_service.h"
     26 #include "chrome/browser/policy/cloud/device_management_service.h"
     27 #include "chrome/browser/policy/configuration_policy_provider.h"
     28 #include "chrome/browser/policy/managed_mode_policy_provider.h"
     29 #include "chrome/browser/policy/policy_domain_descriptor.h"
     30 #include "chrome/browser/policy/policy_service_impl.h"
     31 #include "chrome/browser/policy/policy_statistics_collector.h"
     32 #include "chrome/common/chrome_paths.h"
     33 #include "chrome/common/chrome_switches.h"
     34 #include "chrome/common/pref_names.h"
     35 #include "content/public/browser/browser_thread.h"
     36 #include "google_apis/gaia/gaia_auth_util.h"
     37 #include "google_apis/gaia/gaia_constants.h"
     38 #include "grit/generated_resources.h"
     39 #include "net/url_request/url_request_context_getter.h"
     40 #include "policy/policy_constants.h"
     41 #include "third_party/icu/source/i18n/unicode/regex.h"
     42 
     43 #if defined(OS_WIN)
     44 #include "chrome/browser/policy/policy_loader_win.h"
     45 #elif defined(OS_MACOSX)
     46 #include "chrome/browser/policy/policy_loader_mac.h"
     47 #include "chrome/browser/policy/preferences_mac.h"
     48 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
     49 #include "chrome/browser/policy/config_dir_policy_loader.h"
     50 #endif
     51 
     52 #if defined(OS_CHROMEOS)
     53 #include "chrome/browser/chromeos/cros/network_library.h"
     54 #include "chrome/browser/chromeos/login/user_manager.h"
     55 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
     56 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
     57 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
     58 #include "chrome/browser/chromeos/policy/device_local_account.h"
     59 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
     60 #include "chrome/browser/chromeos/policy/device_status_collector.h"
     61 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
     62 #include "chrome/browser/chromeos/policy/network_configuration_updater.h"
     63 #include "chrome/browser/chromeos/policy/network_configuration_updater_impl.h"
     64 #include "chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.h"
     65 #include "chrome/browser/chromeos/settings/cros_settings.h"
     66 #include "chrome/browser/chromeos/settings/cros_settings_provider.h"
     67 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     68 #include "chrome/browser/chromeos/system/statistics_provider.h"
     69 #include "chrome/browser/chromeos/system/timezone_settings.h"
     70 #include "chromeos/chromeos_paths.h"
     71 #include "chromeos/chromeos_switches.h"
     72 #include "chromeos/cryptohome/cryptohome_library.h"
     73 #include "chromeos/dbus/cryptohome_client.h"
     74 #include "chromeos/dbus/dbus_thread_manager.h"
     75 #include "chromeos/network/managed_network_configuration_handler.h"
     76 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
     77 #endif
     78 
     79 using content::BrowserThread;
     80 
     81 namespace policy {
     82 
     83 namespace {
     84 
     85 // The following constants define delays applied before the initial policy fetch
     86 // on startup. (So that displaying Chrome's GUI does not get delayed.)
     87 // Delay in milliseconds from startup.
     88 const int64 kServiceInitializationStartupDelay = 5000;
     89 
     90 // The URL for the device management server.
     91 const char kDefaultDeviceManagementServerUrl[] =
     92     "https://m.google.com/devicemanagement/data/api";
     93 
     94 // Used in BrowserPolicyConnector::SetPolicyProviderForTesting.
     95 ConfigurationPolicyProvider* g_testing_provider = NULL;
     96 
     97 }  // namespace
     98 
     99 BrowserPolicyConnector::BrowserPolicyConnector()
    100     : is_initialized_(false),
    101       local_state_(NULL),
    102       weak_ptr_factory_(this) {
    103   // GetPolicyService() must be ready after the constructor is done.
    104   // The connector is created very early during startup, when the browser
    105   // threads aren't running yet; initialize components that need local_state,
    106   // the system request context or other threads (e.g. FILE) at Init().
    107 
    108   platform_provider_.reset(CreatePlatformProvider());
    109 
    110   device_management_service_.reset(
    111       new DeviceManagementService(GetDeviceManagementUrl()));
    112 
    113 #if defined(OS_CHROMEOS)
    114   // CryptohomeLibrary or DBusThreadManager may be uninitialized on unit tests.
    115   if (chromeos::CryptohomeLibrary::IsInitialized() &&
    116       chromeos::DBusThreadManager::IsInitialized()) {
    117     chromeos::CryptohomeLibrary* cryptohome =
    118         chromeos::CryptohomeLibrary::Get();
    119     chromeos::CryptohomeClient* cryptohome_client =
    120         chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
    121     install_attributes_.reset(
    122         new EnterpriseInstallAttributes(cryptohome, cryptohome_client));
    123     base::FilePath install_attrs_file;
    124     CHECK(PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES,
    125                            &install_attrs_file));
    126     install_attributes_->ReadCacheFile(install_attrs_file);
    127 
    128     scoped_ptr<DeviceCloudPolicyStoreChromeOS> device_cloud_policy_store(
    129         new DeviceCloudPolicyStoreChromeOS(
    130             chromeos::DeviceSettingsService::Get(),
    131             install_attributes_.get()));
    132     device_cloud_policy_manager_.reset(
    133         new DeviceCloudPolicyManagerChromeOS(
    134             device_cloud_policy_store.Pass(),
    135             install_attributes_.get()));
    136   }
    137 #endif
    138 }
    139 
    140 BrowserPolicyConnector::~BrowserPolicyConnector() {
    141   if (is_initialized()) {
    142     // Shutdown() wasn't invoked by our owner after having called Init().
    143     // This usually means it's an early shutdown and
    144     // BrowserProcessImpl::StartTearDown() wasn't invoked.
    145     // Cleanup properly in those cases and avoid crashing the ToastCrasher test.
    146     Shutdown();
    147   }
    148 }
    149 
    150 void BrowserPolicyConnector::Init(
    151     PrefService* local_state,
    152     scoped_refptr<net::URLRequestContextGetter> request_context) {
    153   // Initialization of some of the providers requires the FILE thread; make
    154   // sure that threading is ready at this point.
    155   DCHECK(BrowserThread::IsThreadInitialized(BrowserThread::FILE));
    156   DCHECK(!is_initialized()) << "BrowserPolicyConnector::Init() called twice.";
    157 
    158   local_state_ = local_state;
    159   request_context_ = request_context;
    160 
    161   device_management_service_->ScheduleInitialization(
    162       kServiceInitializationStartupDelay);
    163 
    164   if (g_testing_provider)
    165     g_testing_provider->Init();
    166   if (platform_provider_)
    167     platform_provider_->Init();
    168 
    169 #if defined(OS_CHROMEOS)
    170   global_user_cloud_policy_provider_.Init();
    171 
    172   if (device_cloud_policy_manager_) {
    173     device_cloud_policy_manager_->Init();
    174     scoped_ptr<CloudPolicyClient::StatusProvider> status_provider(
    175         new DeviceStatusCollector(
    176             local_state_,
    177             chromeos::system::StatisticsProvider::GetInstance(),
    178             NULL));
    179     device_cloud_policy_manager_->Connect(
    180         local_state_,
    181         device_management_service_.get(),
    182         status_provider.Pass());
    183   }
    184 
    185   CommandLine* command_line = CommandLine::ForCurrentProcess();
    186   if (!command_line->HasSwitch(chromeos::switches::kDisableLocalAccounts)) {
    187     device_local_account_policy_service_.reset(
    188         new DeviceLocalAccountPolicyService(
    189             chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
    190             chromeos::DeviceSettingsService::Get(),
    191             chromeos::CrosSettings::Get()));
    192     device_local_account_policy_service_->Connect(
    193         device_management_service_.get());
    194   }
    195 
    196   GetAppPackUpdater();
    197 
    198   SetTimezoneIfPolicyAvailable();
    199 #endif
    200 
    201   policy_statistics_collector_.reset(
    202       new policy::PolicyStatisticsCollector(
    203           GetPolicyService(),
    204           local_state_,
    205           base::MessageLoop::current()->message_loop_proxy()));
    206   policy_statistics_collector_->Initialize();
    207 
    208 #if defined(OS_CHROMEOS)
    209 
    210   network_configuration_updater_.reset(new NetworkConfigurationUpdaterImpl(
    211       GetPolicyService(),
    212       scoped_ptr<chromeos::onc::CertificateImporter>(
    213           new chromeos::onc::CertificateImporterImpl)));
    214 #endif
    215 
    216   is_initialized_ = true;
    217 }
    218 
    219 void BrowserPolicyConnector::Shutdown() {
    220   is_initialized_ = false;
    221 
    222   if (g_testing_provider)
    223     g_testing_provider->Shutdown();
    224   // Drop g_testing_provider so that tests executed with --single_process can
    225   // call SetPolicyProviderForTesting() again. It is still owned by the test.
    226   g_testing_provider = NULL;
    227   if (platform_provider_)
    228     platform_provider_->Shutdown();
    229 
    230 #if defined(OS_CHROMEOS)
    231   // The AppPackUpdater may be observing the |device_cloud_policy_subsystem_|.
    232   // Delete it first.
    233   app_pack_updater_.reset();
    234 
    235   network_configuration_updater_.reset();
    236 
    237   if (device_cloud_policy_manager_)
    238     device_cloud_policy_manager_->Shutdown();
    239   if (device_local_account_policy_service_)
    240     device_local_account_policy_service_->Disconnect();
    241   global_user_cloud_policy_provider_.Shutdown();
    242 #endif
    243 
    244   device_management_service_.reset();
    245 
    246   request_context_ = NULL;
    247 }
    248 
    249 PolicyService* BrowserPolicyConnector::GetPolicyService() {
    250   if (!policy_service_) {
    251     std::vector<ConfigurationPolicyProvider*> providers;
    252 #if defined(OS_CHROMEOS)
    253     providers.push_back(&global_user_cloud_policy_provider_);
    254 #endif
    255     policy_service_ = CreatePolicyService(providers);
    256   }
    257   return policy_service_.get();
    258 }
    259 
    260 #if defined(OS_CHROMEOS)
    261 bool BrowserPolicyConnector::IsEnterpriseManaged() {
    262   return install_attributes_ && install_attributes_->IsEnterpriseDevice();
    263 }
    264 
    265 std::string BrowserPolicyConnector::GetEnterpriseDomain() {
    266   return install_attributes_ ? install_attributes_->GetDomain() : std::string();
    267 }
    268 
    269 DeviceMode BrowserPolicyConnector::GetDeviceMode() {
    270   return install_attributes_ ? install_attributes_->GetMode()
    271                              : DEVICE_MODE_NOT_SET;
    272 }
    273 #endif
    274 
    275 void BrowserPolicyConnector::ScheduleServiceInitialization(
    276     int64 delay_milliseconds) {
    277   // Skip device initialization if the BrowserPolicyConnector was never
    278   // initialized (unit tests).
    279   if (device_management_service_)
    280     device_management_service_->ScheduleInitialization(delay_milliseconds);
    281 }
    282 
    283 scoped_ptr<PolicyService> BrowserPolicyConnector::CreatePolicyService(
    284     const std::vector<ConfigurationPolicyProvider*>& additional_providers) {
    285   std::vector<ConfigurationPolicyProvider*> providers;
    286   if (g_testing_provider) {
    287     providers.push_back(g_testing_provider);
    288   } else {
    289     // |providers| in decreasing order of priority.
    290     if (platform_provider_)
    291       providers.push_back(platform_provider_.get());
    292 #if defined(OS_CHROMEOS)
    293     if (device_cloud_policy_manager_)
    294       providers.push_back(device_cloud_policy_manager_.get());
    295 #endif
    296     std::copy(additional_providers.begin(), additional_providers.end(),
    297               std::back_inserter(providers));
    298   }
    299   scoped_ptr<PolicyService> service(new PolicyServiceImpl(providers));
    300   scoped_refptr<PolicyDomainDescriptor> descriptor = new PolicyDomainDescriptor(
    301       POLICY_DOMAIN_CHROME);
    302   service->RegisterPolicyDomain(descriptor);
    303   return service.Pass();
    304 }
    305 
    306 const ConfigurationPolicyHandlerList*
    307     BrowserPolicyConnector::GetHandlerList() const {
    308   return &handler_list_;
    309 }
    310 
    311 UserAffiliation BrowserPolicyConnector::GetUserAffiliation(
    312     const std::string& user_name) {
    313 #if defined(OS_CHROMEOS)
    314   // An empty username means incognito user in case of ChromiumOS and
    315   // no logged-in user in case of Chromium (SigninService). Many tests use
    316   // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
    317   // users.
    318   if (user_name.empty() || user_name.find('@') == std::string::npos)
    319     return USER_AFFILIATION_NONE;
    320   if (install_attributes_ &&
    321       (gaia::ExtractDomainName(gaia::CanonicalizeEmail(user_name)) ==
    322            install_attributes_->GetDomain() ||
    323        policy::IsDeviceLocalAccountUser(user_name))) {
    324     return USER_AFFILIATION_MANAGED;
    325   }
    326 #endif
    327 
    328   return USER_AFFILIATION_NONE;
    329 }
    330 
    331 #if defined(OS_CHROMEOS)
    332 AppPackUpdater* BrowserPolicyConnector::GetAppPackUpdater() {
    333   // request_context_ is NULL in unit tests.
    334   if (!app_pack_updater_ && request_context_.get()) {
    335     app_pack_updater_.reset(
    336         new AppPackUpdater(request_context_.get(), install_attributes_.get()));
    337   }
    338   return app_pack_updater_.get();
    339 }
    340 
    341 net::CertTrustAnchorProvider*
    342 BrowserPolicyConnector::GetCertTrustAnchorProvider() {
    343   return network_configuration_updater()->GetCertTrustAnchorProvider();
    344 }
    345 
    346 void BrowserPolicyConnector::SetUserPolicyDelegate(
    347     ConfigurationPolicyProvider* user_policy_provider) {
    348   global_user_cloud_policy_provider_.SetDelegate(user_policy_provider);
    349 }
    350 #endif
    351 
    352 void BrowserPolicyConnector::SetDeviceManagementServiceForTesting(
    353     scoped_ptr<DeviceManagementService> service) {
    354   device_management_service_ = service.Pass();
    355 }
    356 
    357 // static
    358 void BrowserPolicyConnector::SetPolicyProviderForTesting(
    359     ConfigurationPolicyProvider* provider) {
    360   CHECK(!g_browser_process) << "Must be invoked before the browser is created";
    361   DCHECK(!g_testing_provider);
    362   g_testing_provider = provider;
    363 }
    364 
    365 // static
    366 std::string BrowserPolicyConnector::GetDeviceManagementUrl() {
    367   CommandLine* command_line = CommandLine::ForCurrentProcess();
    368   if (command_line->HasSwitch(switches::kDeviceManagementUrl))
    369     return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl);
    370   else
    371     return kDefaultDeviceManagementServerUrl;
    372 }
    373 
    374 namespace {
    375 
    376 // Returns true if |domain| matches the regex |pattern|.
    377 bool MatchDomain(const string16& domain, const string16& pattern) {
    378   UErrorCode status = U_ZERO_ERROR;
    379   const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
    380   icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
    381   DCHECK(U_SUCCESS(status)) << "Invalid domain pattern: " << pattern;
    382   icu::UnicodeString icu_input(domain.data(), domain.length());
    383   matcher.reset(icu_input);
    384   status = U_ZERO_ERROR;
    385   UBool match = matcher.matches(status);
    386   DCHECK(U_SUCCESS(status));
    387   return !!match;  // !! == convert from UBool to bool
    388 }
    389 
    390 }  // namespace
    391 
    392 // static
    393 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) {
    394   if (username.empty() || username.find('@') == std::string::npos) {
    395     // An empty username means incognito user in case of ChromiumOS and
    396     // no logged-in user in case of Chromium (SigninService). Many tests use
    397     // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
    398     // users.
    399     return true;
    400   }
    401 
    402   // Exclude many of the larger public email providers as we know these users
    403   // are not from hosted enterprise domains.
    404   static const wchar_t* kNonManagedDomainPatterns[] = {
    405     L"aol\\.com",
    406     L"googlemail\\.com",
    407     L"gmail\\.com",
    408     L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
    409     L"live\\.com",
    410     L"mail\\.ru",
    411     L"msn\\.com",
    412     L"qq\\.com",
    413     L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
    414     L"yandex\\.ru",
    415   };
    416   const string16 domain =
    417       UTF8ToUTF16(gaia::ExtractDomainName(gaia::CanonicalizeEmail(username)));
    418   for (size_t i = 0; i < arraysize(kNonManagedDomainPatterns); i++) {
    419     string16 pattern = WideToUTF16(kNonManagedDomainPatterns[i]);
    420     if (MatchDomain(domain, pattern))
    421       return true;
    422   }
    423   return false;
    424 }
    425 
    426 // static
    427 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) {
    428   registry->RegisterIntegerPref(
    429       prefs::kUserPolicyRefreshRate,
    430       CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
    431 #if defined(OS_CHROMEOS)
    432   registry->RegisterIntegerPref(
    433       prefs::kDevicePolicyRefreshRate,
    434       CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
    435 #endif
    436 }
    437 
    438 void BrowserPolicyConnector::SetTimezoneIfPolicyAvailable() {
    439 #if defined(OS_CHROMEOS)
    440   typedef chromeos::CrosSettingsProvider Provider;
    441   Provider::TrustedStatus result =
    442       chromeos::CrosSettings::Get()->PrepareTrustedValues(
    443           base::Bind(&BrowserPolicyConnector::SetTimezoneIfPolicyAvailable,
    444                      weak_ptr_factory_.GetWeakPtr()));
    445 
    446   if (result != Provider::TRUSTED)
    447     return;
    448 
    449   std::string timezone;
    450   if (chromeos::CrosSettings::Get()->GetString(chromeos::kSystemTimezonePolicy,
    451                                                &timezone) &&
    452       !timezone.empty()) {
    453     chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
    454         UTF8ToUTF16(timezone));
    455   }
    456 #endif
    457 }
    458 
    459 // static
    460 ConfigurationPolicyProvider* BrowserPolicyConnector::CreatePlatformProvider() {
    461 #if defined(OS_WIN)
    462   const PolicyDefinitionList* policy_list = GetChromePolicyDefinitionList();
    463   scoped_ptr<AsyncPolicyLoader> loader(PolicyLoaderWin::Create(policy_list));
    464   return new AsyncPolicyProvider(loader.Pass());
    465 #elif defined(OS_MACOSX)
    466   const PolicyDefinitionList* policy_list = GetChromePolicyDefinitionList();
    467   scoped_ptr<AsyncPolicyLoader> loader(
    468       new PolicyLoaderMac(policy_list, new MacPreferences()));
    469   return new AsyncPolicyProvider(loader.Pass());
    470 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
    471   base::FilePath config_dir_path;
    472   if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
    473     scoped_ptr<AsyncPolicyLoader> loader(
    474         new ConfigDirPolicyLoader(config_dir_path, POLICY_SCOPE_MACHINE));
    475     return new AsyncPolicyProvider(loader.Pass());
    476   } else {
    477     return NULL;
    478   }
    479 #else
    480   return NULL;
    481 #endif
    482 }
    483 
    484 }  // namespace policy
    485