1 // Copyright 2014 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 "components/policy/core/browser/browser_policy_connector.h"
6
7 #include <stddef.h>
8 #include <algorithm>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h"
20 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
21 #include "components/policy/core/common/cloud/device_management_service.h"
22 #include "components/policy/core/common/configuration_policy_provider.h"
23 #include "components/policy/core/common/policy_namespace.h"
24 #include "components/policy/core/common/policy_pref_names.h"
25 #include "components/policy/core/common/policy_statistics_collector.h"
26 #include "components/policy/core/common/policy_switches.h"
27 #include "components/policy/policy_constants.h"
28 #include "components/prefs/pref_registry_simple.h"
29 #include "google_apis/gaia/gaia_auth_util.h"
30 #include "third_party/icu/source/i18n/unicode/regex.h"
31
32 namespace policy {
33
34 namespace {
35
36 // The URL for the device management server.
37 const char kDefaultDeviceManagementServerUrl[] =
38 "https://m.google.com/devicemanagement/data/api";
39
40 const char kDefaultEncryptedReportingServerUrl[] =
41 "https://chromereporting-pa.googleapis.com/v1/record";
42
43 // The URL for the realtime reporting server.
44 const char kDefaultRealtimeReportingServerUrl[] =
45 "https://chromereporting-pa.googleapis.com/v1/events";
46
47 // Regexes that match many of the larger public email providers as we know
48 // these users are not from hosted enterprise domains.
49 const wchar_t* const kNonManagedDomainPatterns[] = {
50 L"aol\\.com",
51 L"comcast\\.net",
52 L"googlemail\\.com",
53 L"gmail\\.com",
54 L"gmx\\.de",
55 L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
56 L"live\\.com",
57 L"mail\\.ru",
58 L"msn\\.com",
59 L"naver\\.com",
60 L"orange\\.fr",
61 L"outlook\\.com",
62 L"qq\\.com",
63 L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
64 L"yandex\\.ru",
65 L"web\\.de",
66 L"wp\\.pl",
67 L"consumer\\.example\\.com",
68 };
69
70 const char* non_managed_domain_for_testing = nullptr;
71
72 // Returns true if |domain| matches the regex |pattern|.
MatchDomain(const base::string16 & domain,const base::string16 & pattern,size_t index)73 bool MatchDomain(const base::string16& domain, const base::string16& pattern,
74 size_t index) {
75 UErrorCode status = U_ZERO_ERROR;
76 const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
77 icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
78 if (!U_SUCCESS(status)) {
79 // http://crbug.com/365351 - if for some reason the matcher creation fails
80 // just return that the pattern doesn't match the domain. This is safe
81 // because the calling method (IsNonEnterpriseUser()) is just used to enable
82 // an optimization for non-enterprise users - better to skip the
83 // optimization than crash.
84 DLOG(ERROR) << "Possible invalid domain pattern: " << pattern
85 << " - Error: " << status;
86 return false;
87 }
88 icu::UnicodeString icu_input(domain.data(), domain.length());
89 matcher.reset(icu_input);
90 status = U_ZERO_ERROR;
91 UBool match = matcher.matches(status);
92 DCHECK(U_SUCCESS(status));
93 return !!match; // !! == convert from UBool to bool.
94 }
95
96 } // namespace
97
BrowserPolicyConnector(const HandlerListFactory & handler_list_factory)98 BrowserPolicyConnector::BrowserPolicyConnector(
99 const HandlerListFactory& handler_list_factory)
100 : BrowserPolicyConnectorBase(handler_list_factory) {
101 }
102
~BrowserPolicyConnector()103 BrowserPolicyConnector::~BrowserPolicyConnector() {
104 }
105
InitInternal(PrefService * local_state,std::unique_ptr<DeviceManagementService> device_management_service)106 void BrowserPolicyConnector::InitInternal(
107 PrefService* local_state,
108 std::unique_ptr<DeviceManagementService> device_management_service) {
109 device_management_service_ = std::move(device_management_service);
110
111 policy_statistics_collector_.reset(new policy::PolicyStatisticsCollector(
112 base::BindRepeating(&GetChromePolicyDetails), GetChromeSchema(),
113 GetPolicyService(), local_state, base::ThreadTaskRunnerHandle::Get()));
114 policy_statistics_collector_->Initialize();
115 }
116
Shutdown()117 void BrowserPolicyConnector::Shutdown() {
118 BrowserPolicyConnectorBase::Shutdown();
119 device_management_service_.reset();
120 }
121
ScheduleServiceInitialization(int64_t delay_milliseconds)122 void BrowserPolicyConnector::ScheduleServiceInitialization(
123 int64_t delay_milliseconds) {
124 // Skip device initialization if the BrowserPolicyConnector was never
125 // initialized (unit tests).
126 if (device_management_service_)
127 device_management_service_->ScheduleInitialization(delay_milliseconds);
128 }
129
ProviderHasPolicies(const ConfigurationPolicyProvider * provider) const130 bool BrowserPolicyConnector::ProviderHasPolicies(
131 const ConfigurationPolicyProvider* provider) const {
132 if (!provider)
133 return false;
134 for (const auto& pair : provider->policies()) {
135 if (!pair.second->empty())
136 return true;
137 }
138 return false;
139 }
140
GetDeviceManagementUrl() const141 std::string BrowserPolicyConnector::GetDeviceManagementUrl() const {
142 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
143 if (command_line->HasSwitch(switches::kDeviceManagementUrl) &&
144 IsCommandLineSwitchSupported())
145 return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl);
146 else
147 return kDefaultDeviceManagementServerUrl;
148 }
149
GetRealtimeReportingUrl() const150 std::string BrowserPolicyConnector::GetRealtimeReportingUrl() const {
151 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
152 if (command_line->HasSwitch(switches::kRealtimeReportingUrl) &&
153 IsCommandLineSwitchSupported())
154 return command_line->GetSwitchValueASCII(switches::kRealtimeReportingUrl);
155 else
156 return kDefaultRealtimeReportingServerUrl;
157 }
158
GetEncryptedReportingUrl() const159 std::string BrowserPolicyConnector::GetEncryptedReportingUrl() const {
160 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
161 if (command_line->HasSwitch(switches::kEncryptedReportingUrl) &&
162 IsCommandLineSwitchSupported())
163 return command_line->GetSwitchValueASCII(switches::kEncryptedReportingUrl);
164 else
165 return kDefaultEncryptedReportingServerUrl;
166 }
167
168 // static
IsNonEnterpriseUser(const std::string & username)169 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) {
170 TRACE_EVENT0("browser", "BrowserPolicyConnector::IsNonEnterpriseUser");
171 if (username.empty() || username.find('@') == std::string::npos) {
172 // An empty username means incognito user in case of ChromiumOS and
173 // no logged-in user in case of Chromium (SigninService). Many tests use
174 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
175 // users.
176 return true;
177 }
178 const base::string16 domain = base::UTF8ToUTF16(
179 gaia::ExtractDomainName(gaia::CanonicalizeEmail(username)));
180 for (size_t i = 0; i < base::size(kNonManagedDomainPatterns); i++) {
181 base::string16 pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]);
182 if (MatchDomain(domain, pattern, i))
183 return true;
184 }
185 if (non_managed_domain_for_testing &&
186 domain == base::UTF8ToUTF16(non_managed_domain_for_testing)) {
187 return true;
188 }
189 return false;
190 }
191
192 // static
SetNonEnterpriseDomainForTesting(const char * domain)193 void BrowserPolicyConnector::SetNonEnterpriseDomainForTesting(
194 const char* domain) {
195 non_managed_domain_for_testing = domain;
196 }
197
198 // static
RegisterPrefs(PrefRegistrySimple * registry)199 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) {
200 registry->RegisterIntegerPref(
201 policy_prefs::kUserPolicyRefreshRate,
202 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
203 registry->RegisterBooleanPref(
204 policy_prefs::kCloudManagementEnrollmentMandatory, false);
205 registry->RegisterBooleanPref(
206 policy_prefs::kCloudPolicyOverridesPlatformPolicy, false);
207 }
208
209 } // namespace policy
210