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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/login/signed_settings.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/memory/ref_counted.h" 11 #include "base/stringprintf.h" 12 #include "base/threading/thread_restrictions.h" 13 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/chromeos/cros/cros_library.h" 15 #include "chrome/browser/chromeos/cros/login_library.h" 16 #include "chrome/browser/chromeos/cros_settings_names.h" 17 #include "chrome/browser/chromeos/login/authenticator.h" 18 #include "chrome/browser/chromeos/login/ownership_service.h" 19 #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h" 20 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" 21 #include "chrome/browser/policy/proto/device_management_backend.pb.h" 22 #include "content/browser/browser_thread.h" 23 24 namespace chromeos { 25 using google::protobuf::RepeatedPtrField; 26 using std::string; 27 28 // static 29 const char SignedSettings::kDevicePolicyType[] = "google/chromeos/device"; 30 31 SignedSettings::Relay::Relay(SignedSettings* s) : settings_(s) { 32 } 33 34 SignedSettings::Relay::~Relay() {} 35 36 void SignedSettings::Relay::OnSettingsOpCompleted( 37 SignedSettings::ReturnCode code, 38 const em::PolicyFetchResponse& value) { 39 if (code == SignedSettings::SUCCESS) { 40 settings_->Execute(); 41 return; 42 } 43 settings_->Fail(code); 44 } 45 46 SignedSettings::SignedSettings() 47 : service_(OwnershipService::GetSharedInstance()), 48 relay_(NULL), 49 polfetcher_(NULL) { 50 } 51 52 SignedSettings::~SignedSettings() {} 53 54 void SignedSettings::TryToFetchPolicyAndCallBack() { 55 relay_.reset(new Relay(this)); 56 polfetcher_ = SignedSettings::CreateRetrievePolicyOp(relay_.get()); 57 polfetcher_->set_service(service_); 58 polfetcher_->Execute(); 59 } 60 61 // static 62 bool SignedSettings::PolicyIsSane(const em::PolicyFetchResponse& value, 63 em::PolicyData* poldata) { 64 if (value.has_policy_data()) { 65 poldata->ParseFromString(value.policy_data()); 66 if (poldata->has_policy_type() && 67 poldata->policy_type() == kDevicePolicyType && 68 poldata->has_policy_value()) { 69 return true; 70 } 71 } 72 return false; 73 } 74 75 // static 76 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( 77 OwnerManager::KeyOpCode return_code) { 78 return (return_code == OwnerManager::KEY_UNAVAILABLE ? 79 KEY_UNAVAILABLE : BAD_SIGNATURE); 80 } 81 82 // static 83 bool SignedSettings::EnumerateWhitelist(std::vector<std::string>* whitelisted) { 84 OwnershipService* service = OwnershipService::GetSharedInstance(); 85 if (!service->has_cached_policy()) 86 return false; 87 em::ChromeDeviceSettingsProto pol; 88 pol.ParseFromString(service->cached_policy().policy_value()); 89 if (!pol.has_user_whitelist()) 90 return false; 91 92 const RepeatedPtrField<std::string>& whitelist = 93 pol.user_whitelist().user_whitelist(); 94 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); 95 it != whitelist.end(); 96 ++it) { 97 whitelisted->push_back(*it); 98 } 99 return true; 100 } 101 102 class CheckWhitelistOp : public SignedSettings { 103 public: 104 CheckWhitelistOp(const std::string& email, 105 SignedSettings::Delegate<bool>* d); 106 virtual ~CheckWhitelistOp(); 107 void Execute(); 108 void Fail(SignedSettings::ReturnCode code); 109 void Succeed(bool value); 110 // Implementation of OwnerManager::Delegate 111 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 112 const std::vector<uint8>& payload); 113 114 private: 115 bool LookUpInPolicy(const std::string& email); 116 // Always call d_->OnSettingOpCompleted() via this call. 117 // It guarantees that the callback will not be triggered until _after_ 118 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 119 // in some cases. 120 void PerformCallback(SignedSettings::ReturnCode code, bool value); 121 122 const std::string email_; 123 SignedSettings::Delegate<bool>* d_; 124 }; 125 126 class WhitelistOp : public SignedSettings, 127 public SignedSettings::Delegate<bool> { 128 public: 129 WhitelistOp(const std::string& email, 130 bool add_to_whitelist, 131 SignedSettings::Delegate<bool>* d); 132 virtual ~WhitelistOp(); 133 void Execute(); 134 void Fail(SignedSettings::ReturnCode code); 135 void Succeed(bool value); 136 // Implementation of OwnerManager::Delegate 137 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 138 const std::vector<uint8>& payload); 139 // Implementation of SignedSettings::Delegate 140 void OnSettingsOpCompleted(ReturnCode code, bool value); 141 142 private: 143 void ModifyWhitelist(const std::string& email, 144 bool add_to_whitelist, 145 em::UserWhitelistProto* whitelist_proto); 146 // Always call d_->OnSettingOpCompleted() via this call. 147 // It guarantees that the callback will not be triggered until _after_ 148 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 149 // in some cases. 150 void PerformCallback(SignedSettings::ReturnCode code, bool value); 151 152 const std::string email_; 153 const bool add_to_whitelist_; 154 SignedSettings::Delegate<bool>* d_; 155 em::PolicyFetchResponse to_store_; 156 scoped_refptr<SignedSettings> store_op_; 157 }; 158 159 class StorePropertyOp : public SignedSettings, 160 public SignedSettings::Delegate<bool> { 161 public: 162 StorePropertyOp(const std::string& name, 163 const std::string& value, 164 SignedSettings::Delegate<bool>* d); 165 virtual ~StorePropertyOp(); 166 void Execute(); 167 void Fail(SignedSettings::ReturnCode code); 168 void Succeed(bool value); 169 // Implementation of OwnerManager::Delegate 170 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 171 const std::vector<uint8>& payload); 172 // Implementation of SignedSettings::Delegate 173 void OnSettingsOpCompleted(ReturnCode code, bool value); 174 175 private: 176 void SetInPolicy(const std::string& prop, 177 const std::string& value, 178 em::PolicyData* poldata); 179 // Always call d_->OnSettingOpCompleted() via this call. 180 // It guarantees that the callback will not be triggered until _after_ 181 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 182 // in some cases. 183 void PerformCallback(SignedSettings::ReturnCode code, bool value); 184 185 std::string name_; 186 std::string value_; 187 SignedSettings::Delegate<bool>* d_; 188 em::PolicyFetchResponse to_store_; 189 scoped_refptr<SignedSettings> store_op_; 190 }; 191 192 class RetrievePropertyOp : public SignedSettings { 193 public: 194 RetrievePropertyOp(const std::string& name, 195 SignedSettings::Delegate<std::string>* d); 196 virtual ~RetrievePropertyOp(); 197 void Execute(); 198 void Fail(SignedSettings::ReturnCode code); 199 void Succeed(const std::string& value); 200 // Implementation of OwnerManager::Delegate::OnKeyOpComplete() 201 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 202 const std::vector<uint8>& payload); 203 204 private: 205 static const char* kVeritas[]; 206 207 std::string LookUpInPolicy(const std::string& prop); 208 // Always call d_->OnSettingOpCompleted() via this call. 209 // It guarantees that the callback will not be triggered until _after_ 210 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 211 // in some cases. 212 void PerformCallback(SignedSettings::ReturnCode code, 213 const std::string& value); 214 215 std::string name_; 216 std::string value_; 217 SignedSettings::Delegate<std::string>* d_; 218 }; 219 220 class StorePolicyOp : public SignedSettings { 221 public: 222 StorePolicyOp(em::PolicyFetchResponse* policy, 223 SignedSettings::Delegate<bool>* d); 224 virtual ~StorePolicyOp(); 225 void Execute(); 226 void Fail(SignedSettings::ReturnCode code); 227 void Succeed(bool value); 228 // Implementation of OwnerManager::Delegate 229 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 230 const std::vector<uint8>& payload); 231 232 private: 233 static void OnBoolComplete(void* delegate, bool success); 234 // Always call d_->OnSettingOpCompleted() via this call. 235 // It guarantees that the callback will not be triggered until _after_ 236 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 237 // in some cases. 238 void PerformCallback(SignedSettings::ReturnCode code, bool value); 239 240 em::PolicyFetchResponse* policy_; 241 SignedSettings::Delegate<bool>* d_; 242 243 void RequestStorePolicy(); 244 }; 245 246 class RetrievePolicyOp : public SignedSettings { 247 public: 248 explicit RetrievePolicyOp( 249 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d); 250 virtual ~RetrievePolicyOp(); 251 void Execute(); 252 void Fail(SignedSettings::ReturnCode code); 253 void Succeed(const em::PolicyFetchResponse& value); 254 // Implementation of OwnerManager::Delegate 255 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 256 const std::vector<uint8>& payload); 257 258 private: 259 static void OnStringComplete(void* delegate, 260 const char* policy, 261 const unsigned int len); 262 // Always call d_->OnSettingOpCompleted() via this call. 263 // It guarantees that the callback will not be triggered until _after_ 264 // Execute() returns, which is implicitly assumed by SignedSettingsHelper 265 // in some cases. 266 void PerformCallback(SignedSettings::ReturnCode code, 267 const em::PolicyFetchResponse& value); 268 269 void ProcessPolicy(const char* out, const unsigned int len); 270 271 em::PolicyFetchResponse policy_; 272 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; 273 }; 274 275 // static 276 SignedSettings* SignedSettings::CreateCheckWhitelistOp( 277 const std::string& email, 278 SignedSettings::Delegate<bool>* d) { 279 DCHECK(d != NULL); 280 return new CheckWhitelistOp(Authenticator::Canonicalize(email), d); 281 } 282 283 // static 284 SignedSettings* SignedSettings::CreateWhitelistOp( 285 const std::string& email, 286 bool add_to_whitelist, 287 SignedSettings::Delegate<bool>* d) { 288 DCHECK(d != NULL); 289 return new WhitelistOp(Authenticator::Canonicalize(email), 290 add_to_whitelist, 291 d); 292 } 293 294 // static 295 SignedSettings* SignedSettings::CreateStorePropertyOp( 296 const std::string& name, 297 const std::string& value, 298 SignedSettings::Delegate<bool>* d) { 299 DCHECK(d != NULL); 300 return new StorePropertyOp(name, value, d); 301 } 302 303 // static 304 SignedSettings* SignedSettings::CreateRetrievePropertyOp( 305 const std::string& name, 306 SignedSettings::Delegate<std::string>* d) { 307 DCHECK(d != NULL); 308 return new RetrievePropertyOp(name, d); 309 } 310 311 // static 312 SignedSettings* SignedSettings::CreateStorePolicyOp( 313 em::PolicyFetchResponse* policy, 314 SignedSettings::Delegate<bool>* d) { 315 DCHECK(d != NULL); 316 DCHECK(policy != NULL); 317 return new StorePolicyOp(policy, d); 318 } 319 320 // static 321 SignedSettings* SignedSettings::CreateRetrievePolicyOp( 322 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { 323 DCHECK(d != NULL); 324 return new RetrievePolicyOp(d); 325 } 326 327 CheckWhitelistOp::CheckWhitelistOp(const std::string& email, 328 SignedSettings::Delegate<bool>* d) 329 : email_(email), 330 d_(d) { 331 } 332 333 CheckWhitelistOp::~CheckWhitelistOp() {} 334 335 void CheckWhitelistOp::Execute() { 336 CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); 337 std::vector<uint8> sig; 338 std::string email_to_check = email_; 339 if (!service_->has_cached_policy()) { 340 TryToFetchPolicyAndCallBack(); 341 return; 342 } 343 if (LookUpInPolicy(email_to_check)) { 344 VLOG(2) << "Whitelist check was successful for " << email_to_check; 345 Succeed(true); 346 return; 347 } 348 // If the exact match was not found try to match against a wildcard entry 349 // where the domain only matches (e.g. *@example.com). In theory we should 350 // always have correctly formated mail address here but a little precaution 351 // does no harm. 352 if (email_.find('@') != std::string::npos) { 353 email_to_check = std::string("*").append(email_.substr(email_.find('@'))); 354 if (LookUpInPolicy(email_to_check)) { 355 VLOG(2) << "Whitelist check was successful for " << email_to_check; 356 Succeed(true); 357 return; 358 } 359 } 360 Fail(NOT_FOUND); 361 return; 362 } 363 364 void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) { 365 BrowserThread::PostTask( 366 BrowserThread::UI, FROM_HERE, 367 NewRunnableMethod(this, &CheckWhitelistOp::PerformCallback, code, false)); 368 } 369 370 void CheckWhitelistOp::Succeed(bool value) { 371 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 372 NewRunnableMethod(this, 373 &CheckWhitelistOp::PerformCallback, 374 SUCCESS, value)); 375 } 376 377 void CheckWhitelistOp::OnKeyOpComplete( 378 const OwnerManager::KeyOpCode return_code, 379 const std::vector<uint8>& payload) { 380 NOTREACHED(); 381 // Ensure we're on the UI thread, due to the need to send DBus traffic. 382 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 383 BrowserThread::PostTask( 384 BrowserThread::UI, FROM_HERE, 385 NewRunnableMethod(this, 386 &CheckWhitelistOp::OnKeyOpComplete, 387 return_code, payload)); 388 return; 389 } 390 if (return_code == OwnerManager::SUCCESS) { 391 VLOG(2) << "Whitelist check was successful."; 392 Succeed(true); 393 } else { 394 VLOG(2) << "Whitelist check failed."; 395 Fail(SignedSettings::MapKeyOpCode(return_code)); 396 } 397 } 398 399 bool CheckWhitelistOp::LookUpInPolicy(const std::string& email) { 400 em::ChromeDeviceSettingsProto pol; 401 pol.ParseFromString(service_->cached_policy().policy_value()); 402 if (!pol.has_user_whitelist()) 403 return false; 404 405 const RepeatedPtrField<std::string>& whitelist = 406 pol.user_whitelist().user_whitelist(); 407 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); 408 it != whitelist.end(); 409 ++it) { 410 if (email == *it) 411 return true; 412 } 413 return false; 414 } 415 416 void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code, 417 bool value) { 418 d_->OnSettingsOpCompleted(code, value); 419 } 420 421 WhitelistOp::WhitelistOp(const std::string& email, 422 bool add_to_whitelist, 423 SignedSettings::Delegate<bool>* d) 424 : email_(email), 425 add_to_whitelist_(add_to_whitelist), 426 d_(d) { 427 } 428 429 WhitelistOp::~WhitelistOp() {} 430 431 void WhitelistOp::Execute() { 432 if (!service_->has_cached_policy()) { 433 TryToFetchPolicyAndCallBack(); 434 return; 435 } 436 em::PolicyData to_sign; 437 to_sign.CheckTypeAndMergeFrom(service_->cached_policy()); 438 em::ChromeDeviceSettingsProto pol; 439 pol.ParseFromString(to_sign.policy_value()); 440 em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist(); 441 ModifyWhitelist(email_, add_to_whitelist_, whitelist_proto); 442 to_sign.set_policy_value(pol.SerializeAsString()); 443 to_store_.set_policy_data(to_sign.SerializeAsString()); 444 service_->StartSigningAttempt(to_store_.policy_data(), this); 445 } 446 447 void WhitelistOp::Fail(SignedSettings::ReturnCode code) { 448 BrowserThread::PostTask( 449 BrowserThread::UI, FROM_HERE, 450 NewRunnableMethod(this, &WhitelistOp::PerformCallback, code, false)); 451 } 452 453 void WhitelistOp::Succeed(bool value) { 454 BrowserThread::PostTask( 455 BrowserThread::UI, FROM_HERE, 456 NewRunnableMethod(this, &WhitelistOp::PerformCallback, SUCCESS, value)); 457 } 458 459 void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 460 const std::vector<uint8>& sig) { 461 // Ensure we're on the UI thread, due to the need to send DBus traffic. 462 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 463 BrowserThread::PostTask( 464 BrowserThread::UI, FROM_HERE, 465 NewRunnableMethod(this, 466 &WhitelistOp::OnKeyOpComplete, 467 return_code, sig)); 468 return; 469 } 470 VLOG(2) << "WhitelistOp::OnKeyOpComplete return_code = " << return_code; 471 // Now, sure we're on the UI thread. 472 if (return_code == OwnerManager::SUCCESS) { 473 to_store_.set_policy_data_signature( 474 std::string(reinterpret_cast<const char*>(&sig[0]), sig.size())); 475 store_op_ = CreateStorePolicyOp(&to_store_, this); 476 // d_->OnSettingsOpCompleted() will be called by this call. 477 store_op_->Execute(); 478 } else { 479 Fail(SignedSettings::MapKeyOpCode(return_code)); 480 } 481 } 482 483 void WhitelistOp::OnSettingsOpCompleted(ReturnCode code, bool value) { 484 if (value && to_store_.has_policy_data()) { 485 em::PolicyData poldata; 486 poldata.ParseFromString(to_store_.policy_data()); 487 service_->set_cached_policy(poldata); 488 Succeed(value); 489 return; 490 } 491 Fail(NOT_FOUND); 492 } 493 494 void WhitelistOp::ModifyWhitelist(const std::string& email, 495 bool add_to_whitelist, 496 em::UserWhitelistProto* whitelist_proto) { 497 int i = 0; 498 const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist(); 499 for (RepeatedPtrField<string>::const_iterator it = whitelist.begin(); 500 it != whitelist.end(); 501 ++it, ++i) { 502 if (email == *it) 503 break; 504 } 505 // |i| contains the index of |email|, if it is in |whitelist|. 506 if (add_to_whitelist) { 507 if (i >= whitelist.size()) // |email| was not in |whitelist|, we must add. 508 whitelist_proto->add_user_whitelist(email); 509 return; 510 } else { 511 if (i < whitelist.size()) { // |email| was in |whitelist|, we must remove. 512 RepeatedPtrField<string>* change_list = 513 whitelist_proto->mutable_user_whitelist(); 514 change_list->SwapElements(i, whitelist.size() - 1); // Move to end. 515 change_list->RemoveLast(); 516 } 517 return; 518 } 519 LOG(WARNING) << "Whitelist modification no-op: " << email; 520 } 521 522 void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) { 523 d_->OnSettingsOpCompleted(code, value); 524 } 525 526 StorePropertyOp::StorePropertyOp(const std::string& name, 527 const std::string& value, 528 SignedSettings::Delegate<bool>* d) 529 : name_(name), 530 value_(value), 531 d_(d), 532 store_op_(NULL) { 533 } 534 535 StorePropertyOp::~StorePropertyOp() {} 536 537 void StorePropertyOp::Execute() { 538 if (service_->GetStatus(true) != OwnershipService::OWNERSHIP_TAKEN) { 539 if (g_browser_process && 540 g_browser_process->local_state() && 541 SignedSettingsTempStorage::Store(name_, value_, 542 g_browser_process->local_state())) { 543 Succeed(true); 544 return; 545 } 546 } 547 if (!service_->has_cached_policy()) { 548 TryToFetchPolicyAndCallBack(); 549 return; 550 } 551 // Posts a task to the FILE thread to sign policy. 552 em::PolicyData to_sign; 553 to_sign.CheckTypeAndMergeFrom(service_->cached_policy()); 554 SetInPolicy(name_, value_, &to_sign); 555 to_store_.set_policy_data(to_sign.SerializeAsString()); 556 service_->StartSigningAttempt(to_store_.policy_data(), this); 557 } 558 559 void StorePropertyOp::Fail(SignedSettings::ReturnCode code) { 560 BrowserThread::PostTask( 561 BrowserThread::UI, FROM_HERE, 562 NewRunnableMethod(this, &StorePropertyOp::PerformCallback, code, false)); 563 } 564 565 void StorePropertyOp::Succeed(bool value) { 566 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 567 NewRunnableMethod(this, 568 &StorePropertyOp::PerformCallback, 569 SUCCESS, value)); 570 } 571 572 void StorePropertyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 573 const std::vector<uint8>& sig) { 574 // Ensure we're on the UI thread, due to the need to send DBus traffic. 575 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 576 BrowserThread::PostTask( 577 BrowserThread::UI, FROM_HERE, 578 NewRunnableMethod(this, 579 &StorePropertyOp::OnKeyOpComplete, 580 return_code, sig)); 581 return; 582 } 583 VLOG(2) << "StorePropertyOp::OnKeyOpComplete return_code = " << return_code; 584 // Now, sure we're on the UI thread. 585 if (return_code == OwnerManager::SUCCESS) { 586 to_store_.set_policy_data_signature( 587 std::string(reinterpret_cast<const char*>(&sig[0]), sig.size())); 588 store_op_ = CreateStorePolicyOp(&to_store_, this); 589 // d_->OnSettingsOpCompleted() will be called by this call. 590 store_op_->Execute(); 591 } else { 592 Fail(SignedSettings::MapKeyOpCode(return_code)); 593 } 594 } 595 596 void StorePropertyOp::OnSettingsOpCompleted(ReturnCode code, bool value) { 597 if (value && to_store_.has_policy_data()) { 598 em::PolicyData poldata; 599 poldata.ParseFromString(to_store_.policy_data()); 600 service_->set_cached_policy(poldata); 601 Succeed(value); 602 return; 603 } 604 Fail(NOT_FOUND); 605 } 606 607 void StorePropertyOp::SetInPolicy(const std::string& prop, 608 const std::string& value, 609 em::PolicyData* poldata) { 610 em::ChromeDeviceSettingsProto pol; 611 pol.ParseFromString(poldata->policy_value()); 612 if (prop == kAccountsPrefAllowNewUser) { 613 em::AllowNewUsersProto* allow = pol.mutable_allow_new_users(); 614 allow->set_allow_new_users(value == "true"); 615 616 } else if (prop == kAccountsPrefAllowGuest) { 617 em::GuestModeEnabledProto* guest = pol.mutable_guest_mode_enabled(); 618 guest->set_guest_mode_enabled(value == "true"); 619 620 } else if (prop == kAccountsPrefShowUserNamesOnSignIn) { 621 em::ShowUserNamesOnSigninProto* show = pol.mutable_show_user_names(); 622 show->set_show_user_names(value == "true"); 623 624 } else if (prop == kSignedDataRoamingEnabled) { 625 em::DataRoamingEnabledProto* roam = pol.mutable_data_roaming_enabled(); 626 roam->set_data_roaming_enabled(value == "true"); 627 628 } else if (prop == kSettingProxyEverywhere) { 629 // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed. 630 bool success = pol.mutable_device_proxy_settings()->ParseFromString(value); 631 DCHECK(success); 632 633 } else { 634 NOTREACHED(); 635 } 636 poldata->set_policy_value(pol.SerializeAsString()); 637 } 638 639 void StorePropertyOp::PerformCallback(SignedSettings::ReturnCode code, 640 bool value) { 641 d_->OnSettingsOpCompleted(code, value); 642 } 643 644 // static 645 const char* RetrievePropertyOp::kVeritas[] = { "false", "true" }; 646 647 RetrievePropertyOp::RetrievePropertyOp(const std::string& name, 648 SignedSettings::Delegate<std::string>* d) 649 : name_(name), 650 d_(d) { 651 } 652 653 RetrievePropertyOp::~RetrievePropertyOp() {} 654 655 void RetrievePropertyOp::Execute() { 656 CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); 657 // TODO(dilmah): Fix the race: 658 // At the moment when device becomes owned there is lapse of time after 659 // device has been owned and before temp_storage settings are finally 660 // persisted into signed settings. 661 // In this lapse of time Retrieve loses access to those settings. 662 if (service_->GetStatus(true) != OwnershipService::OWNERSHIP_TAKEN) { 663 if (g_browser_process && 664 g_browser_process->local_state() && 665 SignedSettingsTempStorage::Retrieve( 666 name_, &value_, g_browser_process->local_state())) { 667 Succeed(value_); 668 return; 669 } 670 } 671 672 if (!service_->has_cached_policy()) { 673 TryToFetchPolicyAndCallBack(); 674 return; 675 } 676 std::string value = LookUpInPolicy(name_); 677 if (value.empty()) 678 Fail(NOT_FOUND); 679 else 680 Succeed(value); 681 } 682 683 void RetrievePropertyOp::Fail(SignedSettings::ReturnCode code) { 684 BrowserThread::PostTask( 685 BrowserThread::UI, FROM_HERE, 686 NewRunnableMethod(this, 687 &RetrievePropertyOp::PerformCallback, 688 code, std::string())); 689 } 690 691 void RetrievePropertyOp::Succeed(const std::string& value) { 692 BrowserThread::PostTask( 693 BrowserThread::UI, FROM_HERE, 694 NewRunnableMethod(this, 695 &RetrievePropertyOp::PerformCallback, SUCCESS, value)); 696 } 697 698 // DEPRECATED. 699 void RetrievePropertyOp::OnKeyOpComplete( 700 const OwnerManager::KeyOpCode return_code, 701 const std::vector<uint8>& sig) { 702 NOTREACHED(); 703 } 704 705 std::string RetrievePropertyOp::LookUpInPolicy(const std::string& prop) { 706 if (prop == kDeviceOwner) { 707 const em::PolicyData& data = service_->cached_policy(); 708 if (data.has_username() && !data.has_request_token()) 709 return data.username(); 710 return ""; 711 } 712 VLOG(2) << "Looking up " << prop; 713 em::ChromeDeviceSettingsProto pol; 714 pol.ParseFromString(service_->cached_policy().policy_value()); 715 if (prop == kAccountsPrefAllowNewUser) { 716 if (pol.has_allow_new_users() && 717 pol.allow_new_users().has_allow_new_users() && 718 pol.allow_new_users().allow_new_users()) { 719 return kVeritas[1]; // New users allowed, user_whitelist() ignored. 720 } 721 // If we have the allow_new_users bool, and it is true, we honor that above. 722 // In all other cases (don't have it, have it and it is set to false, etc), 723 // We will honor the user_whitelist() if it is there and populated. 724 // Otherwise, fail open (to do otherwise could render the device unusable). 725 if (!pol.has_user_whitelist()) 726 return kVeritas[1]; // Default to allowing new users. 727 return kVeritas[pol.user_whitelist().user_whitelist_size() == 0]; 728 729 } else if (prop == kAccountsPrefAllowGuest) { 730 if (!pol.has_guest_mode_enabled() || 731 !pol.guest_mode_enabled().has_guest_mode_enabled()) 732 return kVeritas[1]; // Default to allowing guests; 733 return kVeritas[pol.guest_mode_enabled().guest_mode_enabled()]; 734 735 } else if (prop == kAccountsPrefShowUserNamesOnSignIn) { 736 if (!pol.has_show_user_names() || 737 !pol.show_user_names().has_show_user_names()) 738 return kVeritas[1]; // Default to showing pods on the login screen; 739 return kVeritas[pol.show_user_names().show_user_names()]; 740 741 } else if (prop == kSignedDataRoamingEnabled) { 742 if (!pol.has_data_roaming_enabled() || 743 !pol.data_roaming_enabled().has_data_roaming_enabled()) 744 return kVeritas[0]; // Default to disabling cellular data roaming; 745 return kVeritas[pol.data_roaming_enabled().data_roaming_enabled()]; 746 747 } else if (prop == kSettingProxyEverywhere) { 748 // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed. 749 std::string serialized; 750 if (!pol.has_device_proxy_settings() || 751 !pol.device_proxy_settings().SerializeToString(&serialized)) 752 return ""; // Default to invalid proxy config (will be ignored). 753 return serialized; 754 755 } 756 return std::string(); 757 } 758 759 void RetrievePropertyOp::PerformCallback(SignedSettings::ReturnCode code, 760 const std::string& value) { 761 d_->OnSettingsOpCompleted(code, value); 762 } 763 764 StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy, 765 SignedSettings::Delegate<bool>* d) 766 : policy_(policy), 767 d_(d) { 768 } 769 770 StorePolicyOp::~StorePolicyOp() {} 771 772 // static 773 void StorePolicyOp::OnBoolComplete(void* delegate, bool success) { 774 StorePolicyOp* op = static_cast<StorePolicyOp*>(delegate); 775 if (success) 776 op->Succeed(true); 777 else 778 op->Fail(NOT_FOUND); 779 } 780 781 void StorePolicyOp::Execute() { 782 // get protobuf contents to sign 783 if (!policy_->has_policy_data()) 784 Fail(OPERATION_FAILED); 785 if (!policy_->has_policy_data_signature()) 786 service_->StartSigningAttempt(policy_->policy_data(), this); 787 else 788 RequestStorePolicy(); 789 } 790 791 void StorePolicyOp::Fail(SignedSettings::ReturnCode code) { 792 BrowserThread::PostTask( 793 BrowserThread::UI, FROM_HERE, 794 NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, false)); 795 } 796 797 void StorePolicyOp::Succeed(bool ignored) { 798 SignedSettings::ReturnCode code = SUCCESS; 799 bool to_ret = true; 800 em::PolicyData poldata; 801 if (SignedSettings::PolicyIsSane(*policy_, &poldata)) { 802 service_->set_cached_policy(poldata); 803 } else { 804 code = NOT_FOUND; 805 to_ret = false; 806 } 807 BrowserThread::PostTask( 808 BrowserThread::UI, FROM_HERE, 809 NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, to_ret)); 810 } 811 812 void StorePolicyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, 813 const std::vector<uint8>& payload) { 814 // Ensure we're on the UI thread, due to the need to send DBus traffic. 815 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 816 BrowserThread::PostTask( 817 BrowserThread::UI, FROM_HERE, 818 NewRunnableMethod(this, 819 &StorePolicyOp::OnKeyOpComplete, 820 return_code, payload)); 821 return; 822 } 823 VLOG(2) << "StorePolicyOp::OnKeyOpComplete return_code = " << return_code; 824 // Now, sure we're on the UI thread. 825 if (return_code == OwnerManager::SUCCESS) { 826 policy_->set_policy_data_signature(std::string(payload.begin(), 827 payload.end())); 828 RequestStorePolicy(); 829 return; 830 } 831 Fail(SignedSettings::MapKeyOpCode(return_code)); 832 } 833 834 void StorePolicyOp::RequestStorePolicy() { 835 std::string serialized; 836 if (policy_->SerializeToString(&serialized)) { 837 CrosLibrary::Get()->GetLoginLibrary()->RequestStorePolicy( 838 serialized, 839 &StorePolicyOp::OnBoolComplete, 840 this); 841 } else { 842 Fail(OPERATION_FAILED); 843 } 844 } 845 846 void StorePolicyOp::PerformCallback(SignedSettings::ReturnCode code, 847 bool value) { 848 d_->OnSettingsOpCompleted(code, value); 849 } 850 851 RetrievePolicyOp::RetrievePolicyOp( 852 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) 853 : d_(d) { 854 } 855 856 RetrievePolicyOp::~RetrievePolicyOp() {} 857 858 void RetrievePolicyOp::Execute() { 859 CrosLibrary::Get()->GetLoginLibrary()->RequestRetrievePolicy( 860 &RetrievePolicyOp::OnStringComplete, this); 861 } 862 863 void RetrievePolicyOp::Fail(SignedSettings::ReturnCode code) { 864 VLOG(2) << "RetrievePolicyOp::Execute() failed with " << code; 865 BrowserThread::PostTask( 866 BrowserThread::UI, FROM_HERE, 867 NewRunnableMethod(this, &RetrievePolicyOp::PerformCallback, code, 868 em::PolicyFetchResponse())); 869 } 870 871 void RetrievePolicyOp::Succeed(const em::PolicyFetchResponse& value) { 872 em::PolicyData poldata; 873 if (SignedSettings::PolicyIsSane(value, &poldata)) { 874 service_->set_cached_policy(poldata); 875 BrowserThread::PostTask( 876 BrowserThread::UI, FROM_HERE, 877 NewRunnableMethod(this, 878 &RetrievePolicyOp::PerformCallback, 879 SUCCESS, value)); 880 } else { 881 Fail(NOT_FOUND); 882 } 883 } 884 885 void RetrievePolicyOp::OnKeyOpComplete( 886 const OwnerManager::KeyOpCode return_code, 887 const std::vector<uint8>& payload) { 888 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 889 BrowserThread::PostTask( 890 BrowserThread::UI, FROM_HERE, 891 NewRunnableMethod(this, 892 &RetrievePolicyOp::OnKeyOpComplete, 893 return_code, payload)); 894 return; 895 } 896 // Now, sure we're on the UI thread. 897 if (return_code == OwnerManager::SUCCESS) 898 Succeed(policy_); 899 else 900 Fail(SignedSettings::MapKeyOpCode(return_code)); 901 } 902 903 // static 904 void RetrievePolicyOp::OnStringComplete(void* delegate, 905 const char* out, 906 const unsigned int len) { 907 RetrievePolicyOp* op = static_cast<RetrievePolicyOp*>(delegate); 908 op->ProcessPolicy(out, len); 909 } 910 911 void RetrievePolicyOp::ProcessPolicy(const char* out, const unsigned int len) { 912 if (!out || !policy_.ParseFromString(std::string(out, len)) || 913 (!policy_.has_policy_data() && !policy_.has_policy_data_signature())) { 914 Fail(NOT_FOUND); 915 return; 916 } 917 if (!policy_.has_policy_data()) { 918 Fail(OPERATION_FAILED); 919 return; 920 } 921 if (!policy_.has_policy_data_signature()) { 922 Fail(BAD_SIGNATURE); 923 return; 924 } 925 std::vector<uint8> sig; 926 const char* sig_ptr = policy_.policy_data_signature().c_str(); 927 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); 928 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); 929 } 930 931 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, 932 const em::PolicyFetchResponse& value) { 933 d_->OnSettingsOpCompleted(code, value); 934 } 935 936 } // namespace chromeos 937