OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/login/signed_settings.h" | 5 #include "chrome/browser/chromeos/login/signed_settings.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 return false; | 73 return false; |
74 } | 74 } |
75 | 75 |
76 // static | 76 // static |
77 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( | 77 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( |
78 OwnerManager::KeyOpCode return_code) { | 78 OwnerManager::KeyOpCode return_code) { |
79 return (return_code == OwnerManager::KEY_UNAVAILABLE ? | 79 return (return_code == OwnerManager::KEY_UNAVAILABLE ? |
80 KEY_UNAVAILABLE : BAD_SIGNATURE); | 80 KEY_UNAVAILABLE : BAD_SIGNATURE); |
81 } | 81 } |
82 | 82 |
83 // static | |
84 bool SignedSettings::EnumerateWhitelist(std::vector<std::string>* whitelisted) { | |
85 OwnershipService* service = OwnershipService::GetSharedInstance(); | |
86 if (!service->has_cached_policy()) | |
87 return false; | |
88 em::ChromeDeviceSettingsProto pol; | |
89 pol.ParseFromString(service->cached_policy().policy_value()); | |
90 if (!pol.has_user_whitelist()) | |
91 return false; | |
92 | |
93 const RepeatedPtrField<std::string>& whitelist = | |
94 pol.user_whitelist().user_whitelist(); | |
95 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); | |
96 it != whitelist.end(); | |
97 ++it) { | |
98 whitelisted->push_back(*it); | |
99 } | |
100 return true; | |
101 } | |
102 | |
103 class CheckWhitelistOp : public SignedSettings { | |
104 public: | |
105 CheckWhitelistOp(const std::string& email, | |
106 SignedSettings::Delegate<bool>* d); | |
107 virtual ~CheckWhitelistOp(); | |
108 void Execute(); | |
109 void Fail(SignedSettings::ReturnCode code); | |
110 void Succeed(bool value); | |
111 // Implementation of OwnerManager::Delegate | |
112 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
113 const std::vector<uint8>& payload); | |
114 | |
115 private: | |
116 bool LookUpInPolicy(const std::string& email); | |
117 // Always call d_->OnSettingOpCompleted() via this call. | |
118 // It guarantees that the callback will not be triggered until _after_ | |
119 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
120 // in some cases. | |
121 void PerformCallback(SignedSettings::ReturnCode code, bool value); | |
122 | |
123 const std::string email_; | |
124 SignedSettings::Delegate<bool>* d_; | |
125 }; | |
126 | |
127 class WhitelistOp : public SignedSettings, | |
128 public SignedSettings::Delegate<bool> { | |
129 public: | |
130 WhitelistOp(const std::string& email, | |
131 bool add_to_whitelist, | |
132 SignedSettings::Delegate<bool>* d); | |
133 virtual ~WhitelistOp(); | |
134 void Execute(); | |
135 void Fail(SignedSettings::ReturnCode code); | |
136 void Succeed(bool value); | |
137 // Implementation of OwnerManager::Delegate | |
138 void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
139 const std::vector<uint8>& payload); | |
140 // Implementation of SignedSettings::Delegate | |
141 void OnSettingsOpCompleted(ReturnCode code, bool value); | |
142 | |
143 private: | |
144 void ModifyWhitelist(const std::string& email, | |
145 bool add_to_whitelist, | |
146 em::UserWhitelistProto* whitelist_proto); | |
147 // Always call d_->OnSettingOpCompleted() via this call. | |
148 // It guarantees that the callback will not be triggered until _after_ | |
149 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
150 // in some cases. | |
151 void PerformCallback(SignedSettings::ReturnCode code, bool value); | |
152 | |
153 const std::string email_; | |
154 const bool add_to_whitelist_; | |
155 SignedSettings::Delegate<bool>* d_; | |
156 em::PolicyFetchResponse to_store_; | |
157 scoped_refptr<SignedSettings> store_op_; | |
158 }; | |
159 | |
160 class StorePropertyOp : public SignedSettings, | 83 class StorePropertyOp : public SignedSettings, |
161 public SignedSettings::Delegate<bool> { | 84 public SignedSettings::Delegate<bool> { |
162 public: | 85 public: |
163 StorePropertyOp(const std::string& name, | 86 StorePropertyOp(const std::string& name, |
164 const base::Value& value, | 87 const base::Value& value, |
165 SignedSettings::Delegate<bool>* d); | 88 SignedSettings::Delegate<bool>* d); |
166 virtual ~StorePropertyOp(); | 89 virtual ~StorePropertyOp(); |
167 void Execute(); | 90 void Execute(); |
168 void Fail(SignedSettings::ReturnCode code); | 91 void Fail(SignedSettings::ReturnCode code); |
169 void Succeed(bool value); | 92 void Succeed(bool value); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 void PerformCallback(SignedSettings::ReturnCode code, | 188 void PerformCallback(SignedSettings::ReturnCode code, |
266 const em::PolicyFetchResponse& value); | 189 const em::PolicyFetchResponse& value); |
267 | 190 |
268 void ProcessPolicy(const char* out, const unsigned int len); | 191 void ProcessPolicy(const char* out, const unsigned int len); |
269 | 192 |
270 em::PolicyFetchResponse policy_; | 193 em::PolicyFetchResponse policy_; |
271 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; | 194 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; |
272 }; | 195 }; |
273 | 196 |
274 // static | 197 // static |
275 SignedSettings* SignedSettings::CreateCheckWhitelistOp( | |
276 const std::string& email, | |
277 SignedSettings::Delegate<bool>* d) { | |
278 DCHECK(d != NULL); | |
279 return new CheckWhitelistOp(Authenticator::Canonicalize(email), d); | |
280 } | |
281 | |
282 // static | |
283 SignedSettings* SignedSettings::CreateWhitelistOp( | |
284 const std::string& email, | |
285 bool add_to_whitelist, | |
286 SignedSettings::Delegate<bool>* d) { | |
287 DCHECK(d != NULL); | |
288 return new WhitelistOp(Authenticator::Canonicalize(email), | |
289 add_to_whitelist, | |
290 d); | |
291 } | |
292 | |
293 // static | |
294 SignedSettings* SignedSettings::CreateStorePropertyOp( | 198 SignedSettings* SignedSettings::CreateStorePropertyOp( |
295 const std::string& name, | 199 const std::string& name, |
296 const base::Value& value, | 200 const base::Value& value, |
297 SignedSettings::Delegate<bool>* d) { | 201 SignedSettings::Delegate<bool>* d) { |
298 DCHECK(d != NULL); | 202 DCHECK(d != NULL); |
299 return new StorePropertyOp(name, value, d); | 203 return new StorePropertyOp(name, value, d); |
300 } | 204 } |
301 | 205 |
302 // static | 206 // static |
303 SignedSettings* SignedSettings::CreateRetrievePropertyOp( | 207 SignedSettings* SignedSettings::CreateRetrievePropertyOp( |
(...skipping 12 matching lines...) Expand all Loading... |
316 return new StorePolicyOp(policy, d); | 220 return new StorePolicyOp(policy, d); |
317 } | 221 } |
318 | 222 |
319 // static | 223 // static |
320 SignedSettings* SignedSettings::CreateRetrievePolicyOp( | 224 SignedSettings* SignedSettings::CreateRetrievePolicyOp( |
321 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { | 225 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { |
322 DCHECK(d != NULL); | 226 DCHECK(d != NULL); |
323 return new RetrievePolicyOp(d); | 227 return new RetrievePolicyOp(d); |
324 } | 228 } |
325 | 229 |
326 CheckWhitelistOp::CheckWhitelistOp(const std::string& email, | |
327 SignedSettings::Delegate<bool>* d) | |
328 : email_(email), | |
329 d_(d) { | |
330 } | |
331 | |
332 CheckWhitelistOp::~CheckWhitelistOp() {} | |
333 | |
334 void CheckWhitelistOp::Execute() { | |
335 CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); | |
336 std::vector<uint8> sig; | |
337 std::string email_to_check = email_; | |
338 if (!service_->has_cached_policy()) { | |
339 TryToFetchPolicyAndCallBack(); | |
340 return; | |
341 } | |
342 if (LookUpInPolicy(email_to_check)) { | |
343 VLOG(2) << "Whitelist check was successful for " << email_to_check; | |
344 Succeed(true); | |
345 return; | |
346 } | |
347 // If the exact match was not found try to match against a wildcard entry | |
348 // where the domain only matches (e.g. *@example.com). In theory we should | |
349 // always have correctly formated mail address here but a little precaution | |
350 // does no harm. | |
351 if (email_.find('@') != std::string::npos) { | |
352 email_to_check = std::string("*").append(email_.substr(email_.find('@'))); | |
353 if (LookUpInPolicy(email_to_check)) { | |
354 VLOG(2) << "Whitelist check was successful for " << email_to_check; | |
355 Succeed(true); | |
356 return; | |
357 } | |
358 } | |
359 Fail(NOT_FOUND); | |
360 return; | |
361 } | |
362 | |
363 void CheckWhitelistOp::Fail(SignedSettings::ReturnCode code) { | |
364 BrowserThread::PostTask( | |
365 BrowserThread::UI, FROM_HERE, | |
366 base::Bind(&CheckWhitelistOp::PerformCallback, this, code, false)); | |
367 } | |
368 | |
369 void CheckWhitelistOp::Succeed(bool value) { | |
370 BrowserThread::PostTask( | |
371 BrowserThread::UI, FROM_HERE, | |
372 base::Bind(&CheckWhitelistOp::PerformCallback, this, SUCCESS, value)); | |
373 } | |
374 | |
375 void CheckWhitelistOp::OnKeyOpComplete( | |
376 const OwnerManager::KeyOpCode return_code, | |
377 const std::vector<uint8>& payload) { | |
378 NOTREACHED(); | |
379 // Ensure we're on the UI thread, due to the need to send DBus traffic. | |
380 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
381 BrowserThread::PostTask( | |
382 BrowserThread::UI, FROM_HERE, | |
383 base::Bind(&CheckWhitelistOp::OnKeyOpComplete, this, return_code, | |
384 payload)); | |
385 return; | |
386 } | |
387 if (return_code == OwnerManager::SUCCESS) { | |
388 VLOG(2) << "Whitelist check was successful."; | |
389 Succeed(true); | |
390 } else { | |
391 VLOG(2) << "Whitelist check failed."; | |
392 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
393 } | |
394 } | |
395 | |
396 bool CheckWhitelistOp::LookUpInPolicy(const std::string& email) { | |
397 em::ChromeDeviceSettingsProto pol; | |
398 pol.ParseFromString(service_->cached_policy().policy_value()); | |
399 if (!pol.has_user_whitelist()) | |
400 return false; | |
401 | |
402 const RepeatedPtrField<std::string>& whitelist = | |
403 pol.user_whitelist().user_whitelist(); | |
404 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); | |
405 it != whitelist.end(); | |
406 ++it) { | |
407 if (email == *it) | |
408 return true; | |
409 } | |
410 return false; | |
411 } | |
412 | |
413 void CheckWhitelistOp::PerformCallback(SignedSettings::ReturnCode code, | |
414 bool value) { | |
415 d_->OnSettingsOpCompleted(code, value); | |
416 } | |
417 | |
418 WhitelistOp::WhitelistOp(const std::string& email, | |
419 bool add_to_whitelist, | |
420 SignedSettings::Delegate<bool>* d) | |
421 : email_(email), | |
422 add_to_whitelist_(add_to_whitelist), | |
423 d_(d) { | |
424 } | |
425 | |
426 WhitelistOp::~WhitelistOp() {} | |
427 | |
428 void WhitelistOp::Execute() { | |
429 if (!service_->has_cached_policy()) { | |
430 TryToFetchPolicyAndCallBack(); | |
431 return; | |
432 } | |
433 em::PolicyData to_sign; | |
434 to_sign.CheckTypeAndMergeFrom(service_->cached_policy()); | |
435 em::ChromeDeviceSettingsProto pol; | |
436 pol.ParseFromString(to_sign.policy_value()); | |
437 em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist(); | |
438 ModifyWhitelist(email_, add_to_whitelist_, whitelist_proto); | |
439 to_sign.set_policy_value(pol.SerializeAsString()); | |
440 to_store_.set_policy_data(to_sign.SerializeAsString()); | |
441 service_->StartSigningAttempt(to_store_.policy_data(), this); | |
442 } | |
443 | |
444 void WhitelistOp::Fail(SignedSettings::ReturnCode code) { | |
445 BrowserThread::PostTask( | |
446 BrowserThread::UI, FROM_HERE, | |
447 base::Bind(&WhitelistOp::PerformCallback, this, code, false)); | |
448 } | |
449 | |
450 void WhitelistOp::Succeed(bool value) { | |
451 BrowserThread::PostTask( | |
452 BrowserThread::UI, FROM_HERE, | |
453 base::Bind(&WhitelistOp::PerformCallback, this, SUCCESS, value)); | |
454 } | |
455 | |
456 void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
457 const std::vector<uint8>& sig) { | |
458 // Ensure we're on the UI thread, due to the need to send DBus traffic. | |
459 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
460 BrowserThread::PostTask( | |
461 BrowserThread::UI, FROM_HERE, | |
462 base::Bind(&WhitelistOp::OnKeyOpComplete, this, return_code, sig)); | |
463 return; | |
464 } | |
465 VLOG(2) << "WhitelistOp::OnKeyOpComplete return_code = " << return_code; | |
466 // Now, sure we're on the UI thread. | |
467 if (return_code == OwnerManager::SUCCESS) { | |
468 to_store_.set_policy_data_signature( | |
469 std::string(reinterpret_cast<const char*>(&sig[0]), sig.size())); | |
470 store_op_ = CreateStorePolicyOp(&to_store_, this); | |
471 // d_->OnSettingsOpCompleted() will be called by this call. | |
472 store_op_->Execute(); | |
473 } else { | |
474 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
475 } | |
476 } | |
477 | |
478 void WhitelistOp::OnSettingsOpCompleted(ReturnCode code, bool value) { | |
479 if (value && to_store_.has_policy_data()) { | |
480 em::PolicyData poldata; | |
481 poldata.ParseFromString(to_store_.policy_data()); | |
482 service_->set_cached_policy(poldata); | |
483 Succeed(value); | |
484 return; | |
485 } | |
486 Fail(NOT_FOUND); | |
487 } | |
488 | |
489 void WhitelistOp::ModifyWhitelist(const std::string& email, | |
490 bool add_to_whitelist, | |
491 em::UserWhitelistProto* whitelist_proto) { | |
492 int i = 0; | |
493 const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist(); | |
494 for (RepeatedPtrField<string>::const_iterator it = whitelist.begin(); | |
495 it != whitelist.end(); | |
496 ++it, ++i) { | |
497 if (email == *it) | |
498 break; | |
499 } | |
500 // |i| contains the index of |email|, if it is in |whitelist|. | |
501 if (add_to_whitelist) { | |
502 if (i >= whitelist.size()) // |email| was not in |whitelist|, we must add. | |
503 whitelist_proto->add_user_whitelist(email); | |
504 return; | |
505 } else { | |
506 if (i < whitelist.size()) { // |email| was in |whitelist|, we must remove. | |
507 RepeatedPtrField<string>* change_list = | |
508 whitelist_proto->mutable_user_whitelist(); | |
509 change_list->SwapElements(i, whitelist.size() - 1); // Move to end. | |
510 change_list->RemoveLast(); | |
511 } | |
512 return; | |
513 } | |
514 LOG(WARNING) << "Whitelist modification no-op: " << email; | |
515 } | |
516 | |
517 void WhitelistOp::PerformCallback(SignedSettings::ReturnCode code, bool value) { | |
518 d_->OnSettingsOpCompleted(code, value); | |
519 } | |
520 | |
521 StorePropertyOp::StorePropertyOp(const std::string& name, | 230 StorePropertyOp::StorePropertyOp(const std::string& name, |
522 const base::Value& value, | 231 const base::Value& value, |
523 SignedSettings::Delegate<bool>* d) | 232 SignedSettings::Delegate<bool>* d) |
524 : name_(name), | 233 : name_(name), |
525 value_(value.DeepCopy()), | 234 value_(value.DeepCopy()), |
526 d_(d), | 235 d_(d), |
527 store_op_(NULL) { | 236 store_op_(NULL) { |
528 } | 237 } |
529 | 238 |
530 StorePropertyOp::~StorePropertyOp() {} | 239 StorePropertyOp::~StorePropertyOp() {} |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); | 704 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); |
996 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); | 705 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); |
997 } | 706 } |
998 | 707 |
999 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, | 708 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, |
1000 const em::PolicyFetchResponse& value) { | 709 const em::PolicyFetchResponse& value) { |
1001 d_->OnSettingsOpCompleted(code, value); | 710 d_->OnSettingsOpCompleted(code, value); |
1002 } | 711 } |
1003 | 712 |
1004 } // namespace chromeos | 713 } // namespace chromeos |
OLD | NEW |