| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/policy/cloud_policy_controller.h" | 5 #include "chrome/browser/policy/cloud_policy_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | |
| 11 #include "base/logging.h" | 10 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | |
| 13 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 14 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 15 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 16 #include "chrome/browser/policy/cloud_policy_cache_base.h" | 14 #include "chrome/browser/policy/cloud_policy_cache_base.h" |
| 17 #include "chrome/browser/policy/cloud_policy_subsystem.h" | 15 #include "chrome/browser/policy/cloud_policy_subsystem.h" |
| 18 #include "chrome/browser/policy/device_management_backend.h" | |
| 19 #include "chrome/browser/policy/device_management_service.h" | 16 #include "chrome/browser/policy/device_management_service.h" |
| 20 #include "chrome/browser/policy/enterprise_metrics.h" | 17 #include "chrome/browser/policy/enterprise_metrics.h" |
| 21 #include "chrome/browser/policy/proto/device_management_constants.h" | 18 #include "chrome/browser/policy/proto/device_management_constants.h" |
| 19 #include "chrome/common/guid.h" |
| 20 |
| 21 namespace { |
| 22 | 22 |
| 23 // Domain names that are known not to be managed. | 23 // Domain names that are known not to be managed. |
| 24 // We don't register the device when such a user logs in. | 24 // We don't register the device when such a user logs in. |
| 25 static const char* kNonManagedDomains[] = { | 25 const char* kNonManagedDomains[] = { |
| 26 "@googlemail.com", | 26 "@googlemail.com", |
| 27 "@gmail.com" | 27 "@gmail.com" |
| 28 }; | 28 }; |
| 29 | 29 |
| 30 // Checks the domain part of the given username against the list of known | 30 // Checks the domain part of the given username against the list of known |
| 31 // non-managed domain names. Returns false if |username| is empty or | 31 // non-managed domain names. Returns false if |username| is empty or |
| 32 // in a domain known not to be managed. | 32 // in a domain known not to be managed. |
| 33 static bool CanBeInManagedDomain(const std::string& username) { | 33 bool CanBeInManagedDomain(const std::string& username) { |
| 34 if (username.empty()) { | 34 if (username.empty()) { |
| 35 // This means incognito user in case of ChromiumOS and | 35 // This means incognito user in case of ChromiumOS and |
| 36 // no logged-in user in case of Chromium (SigninService). | 36 // no logged-in user in case of Chromium (SigninService). |
| 37 return false; | 37 return false; |
| 38 } | 38 } |
| 39 for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) { | 39 for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) { |
| 40 if (EndsWith(username, kNonManagedDomains[i], true)) { | 40 if (EndsWith(username, kNonManagedDomains[i], true)) { |
| 41 return false; | 41 return false; |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 return true; | 44 return true; |
| 45 } | 45 } |
| 46 | 46 |
| 47 } |
| 48 |
| 47 namespace policy { | 49 namespace policy { |
| 48 | 50 |
| 49 namespace em = enterprise_management; | 51 namespace em = enterprise_management; |
| 50 | 52 |
| 51 // The maximum ratio in percent of the policy refresh rate we use for adjusting | 53 // The maximum ratio in percent of the policy refresh rate we use for adjusting |
| 52 // the policy refresh time instant. The rationale is to avoid load spikes from | 54 // the policy refresh time instant. The rationale is to avoid load spikes from |
| 53 // many devices that were set up in sync for some reason. | 55 // many devices that were set up in sync for some reason. |
| 54 static const int kPolicyRefreshDeviationFactorPercent = 10; | 56 static const int kPolicyRefreshDeviationFactorPercent = 10; |
| 55 // Maximum deviation we are willing to accept. | 57 // Maximum deviation we are willing to accept. |
| 56 static const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; | 58 static const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; |
| 57 | 59 |
| 58 // These are the base values for delays before retrying after an error. They | 60 // These are the base values for delays before retrying after an error. They |
| 59 // will be doubled each time they are used. | 61 // will be doubled each time they are used. |
| 60 static const int64 kPolicyRefreshErrorDelayInMilliseconds = | 62 static const int64 kPolicyRefreshErrorDelayInMilliseconds = |
| 61 5 * 60 * 1000; // 5 minutes | 63 5 * 60 * 1000; // 5 minutes |
| 62 | 64 |
| 63 // Default value for the policy refresh rate. | 65 // Default value for the policy refresh rate. |
| 64 static const int kPolicyRefreshRateInMilliseconds = | 66 static const int kPolicyRefreshRateInMilliseconds = |
| 65 3 * 60 * 60 * 1000; // 3 hours. | 67 3 * 60 * 60 * 1000; // 3 hours. |
| 66 | 68 |
| 67 CloudPolicyController::CloudPolicyController( | 69 CloudPolicyController::CloudPolicyController( |
| 68 DeviceManagementService* service, | 70 DeviceManagementService* service, |
| 69 CloudPolicyCacheBase* cache, | 71 CloudPolicyCacheBase* cache, |
| 70 DeviceTokenFetcher* token_fetcher, | 72 DeviceTokenFetcher* token_fetcher, |
| 71 CloudPolicyIdentityStrategy* identity_strategy, | 73 CloudPolicyDataStore* data_store, |
| 72 PolicyNotifier* notifier) { | 74 PolicyNotifier* notifier) { |
| 73 Initialize(service, | 75 Initialize(service, |
| 74 cache, | 76 cache, |
| 75 token_fetcher, | 77 token_fetcher, |
| 76 identity_strategy, | 78 data_store, |
| 77 notifier, | 79 notifier, |
| 78 new DelayedWorkScheduler); | 80 new DelayedWorkScheduler); |
| 79 } | 81 } |
| 80 | 82 |
| 81 CloudPolicyController::~CloudPolicyController() { | 83 CloudPolicyController::~CloudPolicyController() { |
| 82 token_fetcher_->RemoveObserver(this); | 84 data_store_->RemoveObserver(this); |
| 83 identity_strategy_->RemoveObserver(this); | |
| 84 scheduler_->CancelDelayedWork(); | 85 scheduler_->CancelDelayedWork(); |
| 85 } | 86 } |
| 86 | 87 |
| 87 void CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) { | 88 void CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) { |
| 88 policy_refresh_rate_ms_ = refresh_rate_milliseconds; | 89 policy_refresh_rate_ms_ = refresh_rate_milliseconds; |
| 89 | 90 |
| 90 // Reschedule the refresh task if necessary. | 91 // Reschedule the refresh task if necessary. |
| 91 if (state_ == STATE_POLICY_VALID) | 92 if (state_ == STATE_POLICY_VALID) |
| 92 SetState(STATE_POLICY_VALID); | 93 SetState(STATE_POLICY_VALID); |
| 93 } | 94 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 case DeviceManagementBackend::kErrorRequestFailed: | 154 case DeviceManagementBackend::kErrorRequestFailed: |
| 154 case DeviceManagementBackend::kErrorTemporaryUnavailable: { | 155 case DeviceManagementBackend::kErrorTemporaryUnavailable: { |
| 155 VLOG(1) << "A temporary error in the communication with the policy server" | 156 VLOG(1) << "A temporary error in the communication with the policy server" |
| 156 << " occurred."; | 157 << " occurred."; |
| 157 // Will retry last operation but gracefully backing off. | 158 // Will retry last operation but gracefully backing off. |
| 158 SetState(STATE_POLICY_ERROR); | 159 SetState(STATE_POLICY_ERROR); |
| 159 } | 160 } |
| 160 } | 161 } |
| 161 } | 162 } |
| 162 | 163 |
| 163 void CloudPolicyController::OnDeviceTokenAvailable() { | |
| 164 identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken()); | |
| 165 } | |
| 166 | |
| 167 void CloudPolicyController::OnDeviceTokenChanged() { | 164 void CloudPolicyController::OnDeviceTokenChanged() { |
| 168 if (identity_strategy_->GetDeviceToken().empty()) | 165 if (data_store_->device_token().empty()) |
| 169 SetState(STATE_TOKEN_UNAVAILABLE); | 166 SetState(STATE_TOKEN_UNAVAILABLE); |
| 170 else | 167 else |
| 171 SetState(STATE_TOKEN_VALID); | 168 SetState(STATE_TOKEN_VALID); |
| 172 } | 169 } |
| 173 | 170 |
| 174 void CloudPolicyController::OnCredentialsChanged() { | 171 void CloudPolicyController::OnCredentialsChanged() { |
| 175 notifier_->Inform(CloudPolicySubsystem::UNENROLLED, | 172 // This notification is only interesting if we don't have a device token. |
| 176 CloudPolicySubsystem::NO_DETAILS, | 173 // If we already have a device token, that must be matching the current |
| 177 PolicyNotifier::POLICY_CONTROLLER); | 174 // user, because (1) we always recreate the policy subsystem after user |
| 178 effective_policy_refresh_error_delay_ms_ = | 175 // login (2) tokens are cached per user. |
| 179 kPolicyRefreshErrorDelayInMilliseconds; | 176 if (data_store_->device_token().empty()) { |
| 180 SetState(STATE_TOKEN_UNAVAILABLE); | 177 notifier_->Inform(CloudPolicySubsystem::UNENROLLED, |
| 178 CloudPolicySubsystem::NO_DETAILS, |
| 179 PolicyNotifier::POLICY_CONTROLLER); |
| 180 effective_policy_refresh_error_delay_ms_ = |
| 181 kPolicyRefreshErrorDelayInMilliseconds; |
| 182 SetState(STATE_TOKEN_UNAVAILABLE); |
| 183 } |
| 184 } |
| 185 |
| 186 void CloudPolicyController::OnDataStoreGoingAway() { |
| 187 NOTREACHED(); |
| 181 } | 188 } |
| 182 | 189 |
| 183 CloudPolicyController::CloudPolicyController( | 190 CloudPolicyController::CloudPolicyController( |
| 184 DeviceManagementService* service, | 191 DeviceManagementService* service, |
| 185 CloudPolicyCacheBase* cache, | 192 CloudPolicyCacheBase* cache, |
| 186 DeviceTokenFetcher* token_fetcher, | 193 DeviceTokenFetcher* token_fetcher, |
| 187 CloudPolicyIdentityStrategy* identity_strategy, | 194 CloudPolicyDataStore* data_store, |
| 188 PolicyNotifier* notifier, | 195 PolicyNotifier* notifier, |
| 189 DelayedWorkScheduler* scheduler) { | 196 DelayedWorkScheduler* scheduler) { |
| 190 Initialize(service, | 197 Initialize(service, |
| 191 cache, | 198 cache, |
| 192 token_fetcher, | 199 token_fetcher, |
| 193 identity_strategy, | 200 data_store, |
| 194 notifier, | 201 notifier, |
| 195 scheduler); | 202 scheduler); |
| 196 } | 203 } |
| 197 | 204 |
| 198 void CloudPolicyController::Initialize( | 205 void CloudPolicyController::Initialize( |
| 199 DeviceManagementService* service, | 206 DeviceManagementService* service, |
| 200 CloudPolicyCacheBase* cache, | 207 CloudPolicyCacheBase* cache, |
| 201 DeviceTokenFetcher* token_fetcher, | 208 DeviceTokenFetcher* token_fetcher, |
| 202 CloudPolicyIdentityStrategy* identity_strategy, | 209 CloudPolicyDataStore* data_store, |
| 203 PolicyNotifier* notifier, | 210 PolicyNotifier* notifier, |
| 204 DelayedWorkScheduler* scheduler) { | 211 DelayedWorkScheduler* scheduler) { |
| 205 DCHECK(cache); | 212 DCHECK(cache); |
| 206 | 213 |
| 207 service_ = service; | 214 service_ = service; |
| 208 cache_ = cache; | 215 cache_ = cache; |
| 209 token_fetcher_ = token_fetcher; | 216 token_fetcher_ = token_fetcher; |
| 210 identity_strategy_ = identity_strategy; | 217 data_store_ = data_store; |
| 211 notifier_ = notifier; | 218 notifier_ = notifier; |
| 212 state_ = STATE_TOKEN_UNAVAILABLE; | 219 state_ = STATE_TOKEN_UNAVAILABLE; |
| 213 policy_refresh_rate_ms_ = kPolicyRefreshRateInMilliseconds; | 220 policy_refresh_rate_ms_ = kPolicyRefreshRateInMilliseconds; |
| 214 effective_policy_refresh_error_delay_ms_ = | 221 effective_policy_refresh_error_delay_ms_ = |
| 215 kPolicyRefreshErrorDelayInMilliseconds; | 222 kPolicyRefreshErrorDelayInMilliseconds; |
| 216 scheduler_.reset(scheduler); | 223 scheduler_.reset(scheduler); |
| 217 token_fetcher_->AddObserver(this); | 224 data_store_->AddObserver(this); |
| 218 identity_strategy_->AddObserver(this); | 225 if (!data_store_->device_token().empty()) |
| 219 if (!identity_strategy_->GetDeviceToken().empty()) | |
| 220 SetState(STATE_TOKEN_VALID); | 226 SetState(STATE_TOKEN_VALID); |
| 221 else | 227 else |
| 222 SetState(STATE_TOKEN_UNAVAILABLE); | 228 SetState(STATE_TOKEN_UNAVAILABLE); |
| 223 } | 229 } |
| 224 | 230 |
| 225 void CloudPolicyController::FetchToken() { | 231 void CloudPolicyController::FetchToken() { |
| 226 std::string username; | 232 if (data_store_->token_cache_loaded() && |
| 227 std::string auth_token; | 233 !data_store_->user_name().empty() && |
| 228 std::string device_id = identity_strategy_->GetDeviceID(); | 234 !data_store_->gaia_token().empty()) { |
| 229 std::string machine_id = identity_strategy_->GetMachineID(); | 235 if (CanBeInManagedDomain(data_store_->user_name())) { |
| 230 std::string machine_model = identity_strategy_->GetMachineModel(); | 236 // Generate a new random device id. (It'll only be kept if registration |
| 231 em::DeviceRegisterRequest_Type policy_type = | 237 // succeeds.) |
| 232 identity_strategy_->GetPolicyRegisterType(); | 238 data_store_->set_device_id(guid::GenerateGUID()); |
| 233 if (identity_strategy_->GetCredentials(&username, &auth_token)) { | 239 token_fetcher_->FetchToken(); |
| 234 if (CanBeInManagedDomain(username)) { | |
| 235 token_fetcher_->FetchToken(auth_token, device_id, policy_type, | |
| 236 machine_id, machine_model); | |
| 237 } else { | 240 } else { |
| 238 SetState(STATE_TOKEN_UNMANAGED); | 241 SetState(STATE_TOKEN_UNMANAGED); |
| 239 } | 242 } |
| 240 } | 243 } |
| 241 } | 244 } |
| 242 | 245 |
| 243 void CloudPolicyController::SendPolicyRequest() { | 246 void CloudPolicyController::SendPolicyRequest() { |
| 244 backend_.reset(service_->CreateBackend()); | 247 backend_.reset(service_->CreateBackend()); |
| 245 DCHECK(!identity_strategy_->GetDeviceToken().empty()); | 248 DCHECK(!data_store_->device_token().empty()); |
| 246 em::DevicePolicyRequest policy_request; | 249 em::DevicePolicyRequest policy_request; |
| 247 em::PolicyFetchRequest* fetch_request = policy_request.add_request(); | 250 em::PolicyFetchRequest* fetch_request = policy_request.add_request(); |
| 248 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); | 251 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); |
| 249 fetch_request->set_policy_type(identity_strategy_->GetPolicyType()); | 252 fetch_request->set_policy_type(data_store_->policy_type()); |
| 250 if (!cache_->is_unmanaged() && | 253 if (!cache_->is_unmanaged() && |
| 251 !cache_->last_policy_refresh_time().is_null()) { | 254 !cache_->last_policy_refresh_time().is_null()) { |
| 252 base::TimeDelta timestamp = | 255 base::TimeDelta timestamp = |
| 253 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); | 256 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); |
| 254 fetch_request->set_timestamp(timestamp.InMilliseconds()); | 257 fetch_request->set_timestamp(timestamp.InMilliseconds()); |
| 255 } | 258 } |
| 256 int key_version = 0; | 259 int key_version = 0; |
| 257 if (cache_->GetPublicKeyVersion(&key_version)) | 260 if (cache_->GetPublicKeyVersion(&key_version)) |
| 258 fetch_request->set_public_key_version(key_version); | 261 fetch_request->set_public_key_version(key_version); |
| 259 | 262 |
| 260 backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(), | 263 backend_->ProcessPolicyRequest(data_store_->device_token(), |
| 261 identity_strategy_->GetDeviceID(), | 264 data_store_->device_id(), |
| 262 policy_request, this); | 265 policy_request, this); |
| 263 } | 266 } |
| 264 | 267 |
| 265 void CloudPolicyController::DoWork() { | 268 void CloudPolicyController::DoWork() { |
| 266 switch (state_) { | 269 switch (state_) { |
| 267 case STATE_TOKEN_UNAVAILABLE: | 270 case STATE_TOKEN_UNAVAILABLE: |
| 268 case STATE_TOKEN_ERROR: | 271 case STATE_TOKEN_ERROR: |
| 269 FetchToken(); | 272 FetchToken(); |
| 270 return; | 273 return; |
| 271 case STATE_TOKEN_VALID: | 274 case STATE_TOKEN_VALID: |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 363 } |
| 361 | 364 |
| 362 int64 CloudPolicyController::GetRefreshDelay() { | 365 int64 CloudPolicyController::GetRefreshDelay() { |
| 363 int64 deviation = (kPolicyRefreshDeviationFactorPercent * | 366 int64 deviation = (kPolicyRefreshDeviationFactorPercent * |
| 364 policy_refresh_rate_ms_) / 100; | 367 policy_refresh_rate_ms_) / 100; |
| 365 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); | 368 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); |
| 366 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); | 369 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); |
| 367 } | 370 } |
| 368 | 371 |
| 369 } // namespace policy | 372 } // namespace policy |
| OLD | NEW |