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