signed_settings.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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
24namespace chromeos {
25using google::protobuf::RepeatedPtrField;
26using std::string;
27
28// static
29const char SignedSettings::kDevicePolicyType[] = "google/chromeos/device";
30
31SignedSettings::Relay::Relay(SignedSettings* s) : settings_(s) {
32}
33
34SignedSettings::Relay::~Relay() {}
35
36void 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
46SignedSettings::SignedSettings()
47    : service_(OwnershipService::GetSharedInstance()),
48      relay_(NULL),
49      polfetcher_(NULL) {
50}
51
52SignedSettings::~SignedSettings() {}
53
54void 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
62bool 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
76SignedSettings::ReturnCode SignedSettings::MapKeyOpCode(
77    OwnerManager::KeyOpCode return_code) {
78  return (return_code == OwnerManager::KEY_UNAVAILABLE ?
79          KEY_UNAVAILABLE : BAD_SIGNATURE);
80}
81
82// static
83bool 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
102class 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
126class 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
159class 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
192class 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
220class 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
246class 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
276SignedSettings* 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
284SignedSettings* 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
295SignedSettings* 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
304SignedSettings* 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
312SignedSettings* 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
321SignedSettings* SignedSettings::CreateRetrievePolicyOp(
322    SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) {
323  DCHECK(d != NULL);
324  return new RetrievePolicyOp(d);
325}
326
327CheckWhitelistOp::CheckWhitelistOp(const std::string& email,
328                                   SignedSettings::Delegate<bool>* d)
329    : email_(email),
330      d_(d) {
331}
332
333CheckWhitelistOp::~CheckWhitelistOp() {}
334
335void 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
364void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) {
365  BrowserThread::PostTask(
366      BrowserThread::UI, FROM_HERE,
367      NewRunnableMethod(this, &CheckWhitelistOp::PerformCallback, code, false));
368}
369
370void CheckWhitelistOp::Succeed(bool value) {
371  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
372                          NewRunnableMethod(this,
373                                            &CheckWhitelistOp::PerformCallback,
374                                            SUCCESS, value));
375}
376
377void 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
399bool 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
416void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code,
417                                       bool value) {
418  d_->OnSettingsOpCompleted(code, value);
419}
420
421WhitelistOp::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
429WhitelistOp::~WhitelistOp() {}
430
431void 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
447void WhitelistOp::Fail(SignedSettings::ReturnCode code) {
448  BrowserThread::PostTask(
449      BrowserThread::UI, FROM_HERE,
450      NewRunnableMethod(this, &WhitelistOp::PerformCallback, code, false));
451}
452
453void WhitelistOp::Succeed(bool value) {
454  BrowserThread::PostTask(
455      BrowserThread::UI, FROM_HERE,
456      NewRunnableMethod(this, &WhitelistOp::PerformCallback, SUCCESS, value));
457}
458
459void 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
483void 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
494void 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
522void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) {
523  d_->OnSettingsOpCompleted(code, value);
524}
525
526StorePropertyOp::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
535StorePropertyOp::~StorePropertyOp() {}
536
537void 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
559void StorePropertyOp::Fail(SignedSettings::ReturnCode code) {
560  BrowserThread::PostTask(
561      BrowserThread::UI, FROM_HERE,
562      NewRunnableMethod(this, &StorePropertyOp::PerformCallback, code, false));
563}
564
565void StorePropertyOp::Succeed(bool value) {
566  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
567                          NewRunnableMethod(this,
568                                            &StorePropertyOp::PerformCallback,
569                                            SUCCESS, value));
570}
571
572void 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
596void 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
607void 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
639void StorePropertyOp::PerformCallback(SignedSettings::ReturnCode code,
640                                      bool value) {
641  d_->OnSettingsOpCompleted(code, value);
642}
643
644// static
645const char* RetrievePropertyOp::kVeritas[] = { "false", "true" };
646
647RetrievePropertyOp::RetrievePropertyOp(const std::string& name,
648                                       SignedSettings::Delegate<std::string>* d)
649    : name_(name),
650      d_(d) {
651}
652
653RetrievePropertyOp::~RetrievePropertyOp() {}
654
655void 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
683void 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
691void 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.
699void RetrievePropertyOp::OnKeyOpComplete(
700    const OwnerManager::KeyOpCode return_code,
701    const std::vector<uint8>& sig) {
702  NOTREACHED();
703}
704
705std::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
759void RetrievePropertyOp::PerformCallback(SignedSettings::ReturnCode code,
760                                         const std::string& value) {
761  d_->OnSettingsOpCompleted(code, value);
762}
763
764StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy,
765                             SignedSettings::Delegate<bool>* d)
766    : policy_(policy),
767      d_(d) {
768}
769
770StorePolicyOp::~StorePolicyOp() {}
771
772// static
773void 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
781void 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
791void StorePolicyOp::Fail(SignedSettings::ReturnCode code) {
792  BrowserThread::PostTask(
793      BrowserThread::UI, FROM_HERE,
794      NewRunnableMethod(this, &StorePolicyOp::PerformCallback, code, false));
795}
796
797void 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
812void 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
834void 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
846void StorePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
847                                    bool value) {
848  d_->OnSettingsOpCompleted(code, value);
849}
850
851RetrievePolicyOp::RetrievePolicyOp(
852    SignedSettings::Delegate<const em::PolicyFetchResponse&>* d)
853    : d_(d) {
854}
855
856RetrievePolicyOp::~RetrievePolicyOp() {}
857
858void RetrievePolicyOp::Execute() {
859  CrosLibrary::Get()->GetLoginLibrary()->RequestRetrievePolicy(
860      &RetrievePolicyOp::OnStringComplete, this);
861}
862
863void 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
871void 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
885void 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
904void 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
911void 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
931void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code,
932                                       const em::PolicyFetchResponse& value) {
933  d_->OnSettingsOpCompleted(code, value);
934}
935
936}  // namespace chromeos
937