• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Relay(SignedSettings * s)31 SignedSettings::Relay::Relay(SignedSettings* s) : settings_(s) {
32 }
33 
~Relay()34 SignedSettings::Relay::~Relay() {}
35 
OnSettingsOpCompleted(SignedSettings::ReturnCode code,const em::PolicyFetchResponse & value)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 
SignedSettings()46 SignedSettings::SignedSettings()
47     : service_(OwnershipService::GetSharedInstance()),
48       relay_(NULL),
49       polfetcher_(NULL) {
50 }
51 
~SignedSettings()52 SignedSettings::~SignedSettings() {}
53 
TryToFetchPolicyAndCallBack()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
PolicyIsSane(const em::PolicyFetchResponse & value,em::PolicyData * poldata)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
MapKeyOpCode(OwnerManager::KeyOpCode return_code)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
EnumerateWhitelist(std::vector<std::string> * whitelisted)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
CreateCheckWhitelistOp(const std::string & email,SignedSettings::Delegate<bool> * d)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
CreateWhitelistOp(const std::string & email,bool add_to_whitelist,SignedSettings::Delegate<bool> * d)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
CreateStorePropertyOp(const std::string & name,const std::string & value,SignedSettings::Delegate<bool> * d)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
CreateRetrievePropertyOp(const std::string & name,SignedSettings::Delegate<std::string> * d)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
CreateStorePolicyOp(em::PolicyFetchResponse * policy,SignedSettings::Delegate<bool> * d)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
CreateRetrievePolicyOp(SignedSettings::Delegate<const em::PolicyFetchResponse &> * d)321 SignedSettings* SignedSettings::CreateRetrievePolicyOp(
322     SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) {
323   DCHECK(d != NULL);
324   return new RetrievePolicyOp(d);
325 }
326 
CheckWhitelistOp(const std::string & email,SignedSettings::Delegate<bool> * d)327 CheckWhitelistOp::CheckWhitelistOp(const std::string& email,
328                                    SignedSettings::Delegate<bool>* d)
329     : email_(email),
330       d_(d) {
331 }
332 
~CheckWhitelistOp()333 CheckWhitelistOp::~CheckWhitelistOp() {}
334 
Execute()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 
Fail(SignedSettings::ReturnCode code)364 void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) {
365   BrowserThread::PostTask(
366       BrowserThread::UI, FROM_HERE,
367       NewRunnableMethod(this, &CheckWhitelistOp::PerformCallback, code, false));
368 }
369 
Succeed(bool value)370 void CheckWhitelistOp::Succeed(bool value) {
371   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
372                           NewRunnableMethod(this,
373                                             &CheckWhitelistOp::PerformCallback,
374                                             SUCCESS, value));
375 }
376 
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & payload)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 
LookUpInPolicy(const std::string & email)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 
PerformCallback(SignedSettings::ReturnCode code,bool value)416 void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code,
417                                        bool value) {
418   d_->OnSettingsOpCompleted(code, value);
419 }
420 
WhitelistOp(const std::string & email,bool add_to_whitelist,SignedSettings::Delegate<bool> * d)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 
~WhitelistOp()429 WhitelistOp::~WhitelistOp() {}
430 
Execute()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 
Fail(SignedSettings::ReturnCode code)447 void WhitelistOp::Fail(SignedSettings::ReturnCode code) {
448   BrowserThread::PostTask(
449       BrowserThread::UI, FROM_HERE,
450       NewRunnableMethod(this, &WhitelistOp::PerformCallback, code, false));
451 }
452 
Succeed(bool value)453 void WhitelistOp::Succeed(bool value) {
454   BrowserThread::PostTask(
455       BrowserThread::UI, FROM_HERE,
456       NewRunnableMethod(this, &WhitelistOp::PerformCallback, SUCCESS, value));
457 }
458 
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & sig)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 
OnSettingsOpCompleted(ReturnCode code,bool value)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 
ModifyWhitelist(const std::string & email,bool add_to_whitelist,em::UserWhitelistProto * whitelist_proto)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 
PerformCallback(SignedSettings::ReturnCode code,bool value)522 void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) {
523   d_->OnSettingsOpCompleted(code, value);
524 }
525 
StorePropertyOp(const std::string & name,const std::string & value,SignedSettings::Delegate<bool> * d)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 
~StorePropertyOp()535 StorePropertyOp::~StorePropertyOp() {}
536 
Execute()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 
Fail(SignedSettings::ReturnCode code)559 void StorePropertyOp::Fail(SignedSettings::ReturnCode code) {
560   BrowserThread::PostTask(
561       BrowserThread::UI, FROM_HERE,
562       NewRunnableMethod(this, &StorePropertyOp::PerformCallback, code, false));
563 }
564 
Succeed(bool value)565 void StorePropertyOp::Succeed(bool value) {
566   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
567                           NewRunnableMethod(this,
568                                             &StorePropertyOp::PerformCallback,
569                                             SUCCESS, value));
570 }
571 
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & sig)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 
OnSettingsOpCompleted(ReturnCode code,bool value)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 
SetInPolicy(const std::string & prop,const std::string & value,em::PolicyData * poldata)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 
PerformCallback(SignedSettings::ReturnCode code,bool value)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 
RetrievePropertyOp(const std::string & name,SignedSettings::Delegate<std::string> * d)647 RetrievePropertyOp::RetrievePropertyOp(const std::string& name,
648                                        SignedSettings::Delegate<std::string>* d)
649     : name_(name),
650       d_(d) {
651 }
652 
~RetrievePropertyOp()653 RetrievePropertyOp::~RetrievePropertyOp() {}
654 
Execute()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 
Fail(SignedSettings::ReturnCode code)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 
Succeed(const std::string & value)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.
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & sig)699 void RetrievePropertyOp::OnKeyOpComplete(
700     const OwnerManager::KeyOpCode return_code,
701     const std::vector<uint8>& sig) {
702   NOTREACHED();
703 }
704 
LookUpInPolicy(const std::string & prop)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 
PerformCallback(SignedSettings::ReturnCode code,const std::string & value)759 void RetrievePropertyOp::PerformCallback(SignedSettings::ReturnCode code,
760                                          const std::string& value) {
761   d_->OnSettingsOpCompleted(code, value);
762 }
763 
StorePolicyOp(em::PolicyFetchResponse * policy,SignedSettings::Delegate<bool> * d)764 StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy,
765                              SignedSettings::Delegate<bool>* d)
766     : policy_(policy),
767       d_(d) {
768 }
769 
~StorePolicyOp()770 StorePolicyOp::~StorePolicyOp() {}
771 
772 // static
OnBoolComplete(void * delegate,bool success)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 
Execute()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 
Fail(SignedSettings::ReturnCode code)791 void StorePolicyOp::Fail(SignedSettings::ReturnCode code) {
792   BrowserThread::PostTask(
793       BrowserThread::UI, FROM_HERE,
794       NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, false));
795 }
796 
Succeed(bool ignored)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 
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & payload)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 
RequestStorePolicy()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 
PerformCallback(SignedSettings::ReturnCode code,bool value)846 void StorePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
847                                     bool value) {
848   d_->OnSettingsOpCompleted(code, value);
849 }
850 
RetrievePolicyOp(SignedSettings::Delegate<const em::PolicyFetchResponse &> * d)851 RetrievePolicyOp::RetrievePolicyOp(
852     SignedSettings::Delegate<const em::PolicyFetchResponse&>* d)
853     : d_(d) {
854 }
855 
~RetrievePolicyOp()856 RetrievePolicyOp::~RetrievePolicyOp() {}
857 
Execute()858 void RetrievePolicyOp::Execute() {
859   CrosLibrary::Get()->GetLoginLibrary()->RequestRetrievePolicy(
860       &RetrievePolicyOp::OnStringComplete, this);
861 }
862 
Fail(SignedSettings::ReturnCode code)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 
Succeed(const em::PolicyFetchResponse & value)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 
OnKeyOpComplete(const OwnerManager::KeyOpCode return_code,const std::vector<uint8> & payload)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
OnStringComplete(void * delegate,const char * out,const unsigned int len)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 
ProcessPolicy(const char * out,const unsigned int len)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 
PerformCallback(SignedSettings::ReturnCode code,const em::PolicyFetchResponse & value)931 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
932                                        const em::PolicyFetchResponse& value) {
933   d_->OnSettingsOpCompleted(code, value);
934 }
935 
936 }  // namespace chromeos
937