| 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/chromeos/login/signed_settings.h" | 5 #include "chrome/browser/chromeos/login/signed_settings.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 return false; | 73 return false; |
| 74 } | 74 } |
| 75 | 75 |
| 76 // static | 76 // static |
| 77 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( | 77 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( |
| 78 OwnerManager::KeyOpCode return_code) { | 78 OwnerManager::KeyOpCode return_code) { |
| 79 return (return_code == OwnerManager::KEY_UNAVAILABLE ? | 79 return (return_code == OwnerManager::KEY_UNAVAILABLE ? |
| 80 KEY_UNAVAILABLE : BAD_SIGNATURE); | 80 KEY_UNAVAILABLE : BAD_SIGNATURE); |
| 81 } | 81 } |
| 82 | 82 |
| 83 // static | |
| 84 bool SignedSettings::EnumerateWhitelist(std::vector<std::string>* whitelisted) { | |
| 85 OwnershipService* service = OwnershipService::GetSharedInstance(); | |
| 86 if (!service->has_cached_policy()) | |
| 87 return false; | |
| 88 em::ChromeDeviceSettingsProto pol; | |
| 89 pol.ParseFromString(service->cached_policy().policy_value()); | |
| 90 if (!pol.has_user_whitelist()) | |
| 91 return false; | |
| 92 | |
| 93 const RepeatedPtrField<std::string>& whitelist = | |
| 94 pol.user_whitelist().user_whitelist(); | |
| 95 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); | |
| 96 it != whitelist.end(); | |
| 97 ++it) { | |
| 98 whitelisted->push_back(*it); | |
| 99 } | |
| 100 return true; | |
| 101 } | |
| 102 | |
| 103 class CheckWhitelistOp : public SignedSettings { | |
| 104 public: | |
| 105 CheckWhitelistOp(const std::string& email, | |
| 106 SignedSettings::Delegate<bool>* d); | |
| 107 virtual ~CheckWhitelistOp(); | |
| 108 void Execute(); | |
| 109 void Fail(SignedSettings::ReturnCode code); | |
| 110 void Succeed(bool value); | |
| 111 // Implementation of OwnerManager::Delegate | |
| 112 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 113 const std::vector<uint8>& payload); | |
| 114 | |
| 115 private: | |
| 116 bool LookUpInPolicy(const std::string& email); | |
| 117 // Always call d_->OnSettingOpCompleted() via this call. | |
| 118 // It guarantees that the callback will not be triggered until _after_ | |
| 119 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
| 120 // in some cases. | |
| 121 void PerformCallback(SignedSettings::ReturnCode code, bool value); | |
| 122 | |
| 123 const std::string email_; | |
| 124 SignedSettings::Delegate<bool>* d_; | |
| 125 }; | |
| 126 | |
| 127 class WhitelistOp : public SignedSettings, | |
| 128 public SignedSettings::Delegate<bool> { | |
| 129 public: | |
| 130 WhitelistOp(const std::string& email, | |
| 131 bool add_to_whitelist, | |
| 132 SignedSettings::Delegate<bool>* d); | |
| 133 virtual ~WhitelistOp(); | |
| 134 void Execute(); | |
| 135 void Fail(SignedSettings::ReturnCode code); | |
| 136 void Succeed(bool value); | |
| 137 // Implementation of OwnerManager::Delegate | |
| 138 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 139 const std::vector<uint8>& payload); | |
| 140 // Implementation of SignedSettings::Delegate | |
| 141 void OnSettingsOpCompleted(ReturnCode code, bool value); | |
| 142 | |
| 143 private: | |
| 144 void ModifyWhitelist(const std::string& email, | |
| 145 bool add_to_whitelist, | |
| 146 em::UserWhitelistProto* whitelist_proto); | |
| 147 // Always call d_->OnSettingOpCompleted() via this call. | |
| 148 // It guarantees that the callback will not be triggered until _after_ | |
| 149 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
| 150 // in some cases. | |
| 151 void PerformCallback(SignedSettings::ReturnCode code, bool value); | |
| 152 | |
| 153 const std::string email_; | |
| 154 const bool add_to_whitelist_; | |
| 155 SignedSettings::Delegate<bool>* d_; | |
| 156 em::PolicyFetchResponse to_store_; | |
| 157 scoped_refptr<SignedSettings> store_op_; | |
| 158 }; | |
| 159 | |
| 160 class StorePropertyOp : public SignedSettings, | 83 class StorePropertyOp : public SignedSettings, |
| 161 public SignedSettings::Delegate<bool> { | 84 public SignedSettings::Delegate<bool> { |
| 162 public: | 85 public: |
| 163 StorePropertyOp(const std::string& name, | 86 StorePropertyOp(const std::string& name, |
| 164 const base::Value& value, | 87 const base::Value& value, |
| 165 SignedSettings::Delegate<bool>* d); | 88 SignedSettings::Delegate<bool>* d); |
| 166 virtual ~StorePropertyOp(); | 89 virtual ~StorePropertyOp(); |
| 167 void Execute(); | 90 void Execute(); |
| 168 void Fail(SignedSettings::ReturnCode code); | 91 void Fail(SignedSettings::ReturnCode code); |
| 169 void Succeed(bool value); | 92 void Succeed(bool value); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 void PerformCallback(SignedSettings::ReturnCode code, | 190 void PerformCallback(SignedSettings::ReturnCode code, |
| 268 const em::PolicyFetchResponse& value); | 191 const em::PolicyFetchResponse& value); |
| 269 | 192 |
| 270 void ProcessPolicy(const char* out, const unsigned int len); | 193 void ProcessPolicy(const char* out, const unsigned int len); |
| 271 | 194 |
| 272 em::PolicyFetchResponse policy_; | 195 em::PolicyFetchResponse policy_; |
| 273 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; | 196 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; |
| 274 }; | 197 }; |
| 275 | 198 |
| 276 // static | 199 // static |
| 277 SignedSettings* SignedSettings::CreateCheckWhitelistOp( | |
| 278 const std::string& email, | |
| 279 SignedSettings::Delegate<bool>* d) { | |
| 280 DCHECK(d != NULL); | |
| 281 return new CheckWhitelistOp(Authenticator::Canonicalize(email), d); | |
| 282 } | |
| 283 | |
| 284 // static | |
| 285 SignedSettings* SignedSettings::CreateWhitelistOp( | |
| 286 const std::string& email, | |
| 287 bool add_to_whitelist, | |
| 288 SignedSettings::Delegate<bool>* d) { | |
| 289 DCHECK(d != NULL); | |
| 290 return new WhitelistOp(Authenticator::Canonicalize(email), | |
| 291 add_to_whitelist, | |
| 292 d); | |
| 293 } | |
| 294 | |
| 295 // static | |
| 296 SignedSettings* SignedSettings::CreateStorePropertyOp( | 200 SignedSettings* SignedSettings::CreateStorePropertyOp( |
| 297 const std::string& name, | 201 const std::string& name, |
| 298 const base::Value& value, | 202 const base::Value& value, |
| 299 SignedSettings::Delegate<bool>* d) { | 203 SignedSettings::Delegate<bool>* d) { |
| 300 DCHECK(d != NULL); | 204 DCHECK(d != NULL); |
| 301 return new StorePropertyOp(name, value, d); | 205 return new StorePropertyOp(name, value, d); |
| 302 } | 206 } |
| 303 | 207 |
| 304 // static | 208 // static |
| 305 SignedSettings* SignedSettings::CreateRetrievePropertyOp( | 209 SignedSettings* SignedSettings::CreateRetrievePropertyOp( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 318 return new StorePolicyOp(policy, d); | 222 return new StorePolicyOp(policy, d); |
| 319 } | 223 } |
| 320 | 224 |
| 321 // static | 225 // static |
| 322 SignedSettings* SignedSettings::CreateRetrievePolicyOp( | 226 SignedSettings* SignedSettings::CreateRetrievePolicyOp( |
| 323 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { | 227 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { |
| 324 DCHECK(d != NULL); | 228 DCHECK(d != NULL); |
| 325 return new RetrievePolicyOp(d); | 229 return new RetrievePolicyOp(d); |
| 326 } | 230 } |
| 327 | 231 |
| 328 CheckWhitelistOp::CheckWhitelistOp(const std::string& email, | |
| 329 SignedSettings::Delegate<bool>* d) | |
| 330 : email_(email), | |
| 331 d_(d) { | |
| 332 } | |
| 333 | |
| 334 CheckWhitelistOp::~CheckWhitelistOp() {} | |
| 335 | |
| 336 void CheckWhitelistOp::Execute() { | |
| 337 CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); | |
| 338 std::vector<uint8> sig; | |
| 339 std::string email_to_check = email_; | |
| 340 if (!service_->has_cached_policy()) { | |
| 341 TryToFetchPolicyAndCallBack(); | |
| 342 return; | |
| 343 } | |
| 344 if (LookUpInPolicy(email_to_check)) { | |
| 345 VLOG(2) << "Whitelist check was successful for " << email_to_check; | |
| 346 Succeed(true); | |
| 347 return; | |
| 348 } | |
| 349 // If the exact match was not found try to match against a wildcard entry | |
| 350 // where the domain only matches (e.g. *@example.com). In theory we should | |
| 351 // always have correctly formated mail address here but a little precaution | |
| 352 // does no harm. | |
| 353 if (email_.find('@') != std::string::npos) { | |
| 354 email_to_check = std::string("*").append(email_.substr(email_.find('@'))); | |
| 355 if (LookUpInPolicy(email_to_check)) { | |
| 356 VLOG(2) << "Whitelist check was successful for " << email_to_check; | |
| 357 Succeed(true); | |
| 358 return; | |
| 359 } | |
| 360 } | |
| 361 Fail(NOT_FOUND); | |
| 362 return; | |
| 363 } | |
| 364 | |
| 365 void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) { | |
| 366 BrowserThread::PostTask( | |
| 367 BrowserThread::UI, FROM_HERE, | |
| 368 NewRunnableMethod(this, &CheckWhitelistOp::PerformCallback, code, false)); | |
| 369 } | |
| 370 | |
| 371 void CheckWhitelistOp::Succeed(bool value) { | |
| 372 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 373 NewRunnableMethod(this, | |
| 374 &CheckWhitelistOp::PerformCallback, | |
| 375 SUCCESS, value)); | |
| 376 } | |
| 377 | |
| 378 void CheckWhitelistOp::OnKeyOpComplete( | |
| 379 const OwnerManager::KeyOpCode return_code, | |
| 380 const std::vector<uint8>& payload) { | |
| 381 NOTREACHED(); | |
| 382 // Ensure we're on the UI thread, due to the need to send DBus traffic. | |
| 383 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 384 BrowserThread::PostTask( | |
| 385 BrowserThread::UI, FROM_HERE, | |
| 386 NewRunnableMethod(this, | |
| 387 &CheckWhitelistOp::OnKeyOpComplete, | |
| 388 return_code, payload)); | |
| 389 return; | |
| 390 } | |
| 391 if (return_code == OwnerManager::SUCCESS) { | |
| 392 VLOG(2) << "Whitelist check was successful."; | |
| 393 Succeed(true); | |
| 394 } else { | |
| 395 VLOG(2) << "Whitelist check failed."; | |
| 396 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
| 397 } | |
| 398 } | |
| 399 | |
| 400 bool CheckWhitelistOp::LookUpInPolicy(const std::string& email) { | |
| 401 em::ChromeDeviceSettingsProto pol; | |
| 402 pol.ParseFromString(service_->cached_policy().policy_value()); | |
| 403 if (!pol.has_user_whitelist()) | |
| 404 return false; | |
| 405 | |
| 406 const RepeatedPtrField<std::string>& whitelist = | |
| 407 pol.user_whitelist().user_whitelist(); | |
| 408 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); | |
| 409 it != whitelist.end(); | |
| 410 ++it) { | |
| 411 if (email == *it) | |
| 412 return true; | |
| 413 } | |
| 414 return false; | |
| 415 } | |
| 416 | |
| 417 void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code, | |
| 418 bool value) { | |
| 419 d_->OnSettingsOpCompleted(code, value); | |
| 420 } | |
| 421 | |
| 422 WhitelistOp::WhitelistOp(const std::string& email, | |
| 423 bool add_to_whitelist, | |
| 424 SignedSettings::Delegate<bool>* d) | |
| 425 : email_(email), | |
| 426 add_to_whitelist_(add_to_whitelist), | |
| 427 d_(d) { | |
| 428 } | |
| 429 | |
| 430 WhitelistOp::~WhitelistOp() {} | |
| 431 | |
| 432 void WhitelistOp::Execute() { | |
| 433 if (!service_->has_cached_policy()) { | |
| 434 TryToFetchPolicyAndCallBack(); | |
| 435 return; | |
| 436 } | |
| 437 em::PolicyData to_sign; | |
| 438 to_sign.CheckTypeAndMergeFrom(service_->cached_policy()); | |
| 439 em::ChromeDeviceSettingsProto pol; | |
| 440 pol.ParseFromString(to_sign.policy_value()); | |
| 441 em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist(); | |
| 442 ModifyWhitelist(email_, add_to_whitelist_, whitelist_proto); | |
| 443 to_sign.set_policy_value(pol.SerializeAsString()); | |
| 444 to_store_.set_policy_data(to_sign.SerializeAsString()); | |
| 445 service_->StartSigningAttempt(to_store_.policy_data(), this); | |
| 446 } | |
| 447 | |
| 448 void WhitelistOp::Fail(SignedSettings::ReturnCode code) { | |
| 449 BrowserThread::PostTask( | |
| 450 BrowserThread::UI, FROM_HERE, | |
| 451 NewRunnableMethod(this, &WhitelistOp::PerformCallback, code, false)); | |
| 452 } | |
| 453 | |
| 454 void WhitelistOp::Succeed(bool value) { | |
| 455 BrowserThread::PostTask( | |
| 456 BrowserThread::UI, FROM_HERE, | |
| 457 NewRunnableMethod(this, &WhitelistOp::PerformCallback, SUCCESS, value)); | |
| 458 } | |
| 459 | |
| 460 void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 461 const std::vector<uint8>& sig) { | |
| 462 // Ensure we're on the UI thread, due to the need to send DBus traffic. | |
| 463 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 464 BrowserThread::PostTask( | |
| 465 BrowserThread::UI, FROM_HERE, | |
| 466 NewRunnableMethod(this, | |
| 467 &WhitelistOp::OnKeyOpComplete, | |
| 468 return_code, sig)); | |
| 469 return; | |
| 470 } | |
| 471 VLOG(2) << "WhitelistOp::OnKeyOpComplete return_code = " << return_code; | |
| 472 // Now, sure we're on the UI thread. | |
| 473 if (return_code == OwnerManager::SUCCESS) { | |
| 474 to_store_.set_policy_data_signature( | |
| 475 std::string(reinterpret_cast<const char*>(&sig[0]), sig.size())); | |
| 476 store_op_ = CreateStorePolicyOp(&to_store_, this); | |
| 477 // d_->OnSettingsOpCompleted() will be called by this call. | |
| 478 store_op_->Execute(); | |
| 479 } else { | |
| 480 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 void WhitelistOp::OnSettingsOpCompleted(ReturnCode code, bool value) { | |
| 485 if (value && to_store_.has_policy_data()) { | |
| 486 em::PolicyData poldata; | |
| 487 poldata.ParseFromString(to_store_.policy_data()); | |
| 488 service_->set_cached_policy(poldata); | |
| 489 Succeed(value); | |
| 490 return; | |
| 491 } | |
| 492 Fail(NOT_FOUND); | |
| 493 } | |
| 494 | |
| 495 void WhitelistOp::ModifyWhitelist(const std::string& email, | |
| 496 bool add_to_whitelist, | |
| 497 em::UserWhitelistProto* whitelist_proto) { | |
| 498 int i = 0; | |
| 499 const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist(); | |
| 500 for (RepeatedPtrField<string>::const_iterator it = whitelist.begin(); | |
| 501 it != whitelist.end(); | |
| 502 ++it, ++i) { | |
| 503 if (email == *it) | |
| 504 break; | |
| 505 } | |
| 506 // |i| contains the index of |email|, if it is in |whitelist|. | |
| 507 if (add_to_whitelist) { | |
| 508 if (i >= whitelist.size()) // |email| was not in |whitelist|, we must add. | |
| 509 whitelist_proto->add_user_whitelist(email); | |
| 510 return; | |
| 511 } else { | |
| 512 if (i < whitelist.size()) { // |email| was in |whitelist|, we must remove. | |
| 513 RepeatedPtrField<string>* change_list = | |
| 514 whitelist_proto->mutable_user_whitelist(); | |
| 515 change_list->SwapElements(i, whitelist.size() - 1); // Move to end. | |
| 516 change_list->RemoveLast(); | |
| 517 } | |
| 518 return; | |
| 519 } | |
| 520 LOG(WARNING) << "Whitelist modification no-op: " << email; | |
| 521 } | |
| 522 | |
| 523 void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) { | |
| 524 d_->OnSettingsOpCompleted(code, value); | |
| 525 } | |
| 526 | |
| 527 StorePropertyOp::StorePropertyOp(const std::string& name, | 232 StorePropertyOp::StorePropertyOp(const std::string& name, |
| 528 const base::Value& value, | 233 const base::Value& value, |
| 529 SignedSettings::Delegate<bool>* d) | 234 SignedSettings::Delegate<bool>* d) |
| 530 : name_(name), | 235 : name_(name), |
| 531 value_(value.DeepCopy()), | 236 value_(value.DeepCopy()), |
| 532 d_(d), | 237 d_(d), |
| 533 store_op_(NULL) { | 238 store_op_(NULL) { |
| 534 } | 239 } |
| 535 | 240 |
| 536 StorePropertyOp::~StorePropertyOp() {} | 241 StorePropertyOp::~StorePropertyOp() {} |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); | 702 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); |
| 998 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); | 703 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); |
| 999 } | 704 } |
| 1000 | 705 |
| 1001 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, | 706 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, |
| 1002 const em::PolicyFetchResponse& value) { | 707 const em::PolicyFetchResponse& value) { |
| 1003 d_->OnSettingsOpCompleted(code, value); | 708 d_->OnSettingsOpCompleted(code, value); |
| 1004 } | 709 } |
| 1005 | 710 |
| 1006 } // namespace chromeos | 711 } // namespace chromeos |
| OLD | NEW |