Home | History | Annotate | Download | only in login
      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