OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chromeos/login/auth/cryptohome_authenticator.h" | 5 #include "chromeos/login/auth/cryptohome_authenticator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "chromeos/cryptohome/async_method_caller.h" | 11 #include "chromeos/cryptohome/async_method_caller.h" |
| 12 #include "chromeos/cryptohome/cryptohome_parameters.h" |
| 13 #include "chromeos/cryptohome/homedir_methods.h" |
12 #include "chromeos/cryptohome/system_salt_getter.h" | 14 #include "chromeos/cryptohome/system_salt_getter.h" |
13 #include "chromeos/dbus/cryptohome_client.h" | 15 #include "chromeos/dbus/cryptohome_client.h" |
14 #include "chromeos/dbus/dbus_thread_manager.h" | 16 #include "chromeos/dbus/dbus_thread_manager.h" |
15 #include "chromeos/login/auth/auth_status_consumer.h" | 17 #include "chromeos/login/auth/auth_status_consumer.h" |
16 #include "chromeos/login/auth/key.h" | 18 #include "chromeos/login/auth/key.h" |
17 #include "chromeos/login/auth/user_context.h" | 19 #include "chromeos/login/auth/user_context.h" |
18 #include "chromeos/login/login_state.h" | 20 #include "chromeos/login/login_state.h" |
19 #include "chromeos/login/user_names.h" | 21 #include "chromeos/login/user_names.h" |
20 #include "chromeos/login_event_recorder.h" | 22 #include "chromeos/login_event_recorder.h" |
21 #include "components/user_manager/user_type.h" | 23 #include "components/user_manager/user_type.h" |
22 #include "third_party/cros_system_api/dbus/service_constants.h" | 24 #include "third_party/cros_system_api/dbus/service_constants.h" |
23 | 25 |
24 namespace chromeos { | 26 namespace chromeos { |
25 | 27 |
26 namespace { | 28 namespace { |
27 | 29 |
| 30 // The label used for the key derived from the user's GAIA credentials. |
| 31 const char kCryptohomeGAIAKeyLabel[] = "gaia"; |
| 32 |
28 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. | 33 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. |
29 // Returns the keys unmodified otherwise. | 34 // Returns the keys unmodified otherwise. |
30 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, | 35 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, |
31 const std::string& system_salt) { | 36 const std::string& system_salt) { |
32 scoped_ptr<Key> result(new Key(key)); | 37 scoped_ptr<Key> result(new Key(key)); |
33 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN) | 38 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN) |
34 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt); | 39 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt); |
35 | 40 |
36 return result.Pass(); | 41 return result.Pass(); |
37 } | 42 } |
(...skipping 23 matching lines...) Expand all Loading... |
61 void TriggerResolveWithLoginTimeMarker( | 66 void TriggerResolveWithLoginTimeMarker( |
62 const std::string& marker_name, | 67 const std::string& marker_name, |
63 AuthAttemptState* attempt, | 68 AuthAttemptState* attempt, |
64 scoped_refptr<CryptohomeAuthenticator> resolver, | 69 scoped_refptr<CryptohomeAuthenticator> resolver, |
65 bool success, | 70 bool success, |
66 cryptohome::MountError return_code) { | 71 cryptohome::MountError return_code) { |
67 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(marker_name, false); | 72 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(marker_name, false); |
68 TriggerResolve(attempt, resolver, success, return_code); | 73 TriggerResolve(attempt, resolver, success, return_code); |
69 } | 74 } |
70 | 75 |
| 76 void TriggerResolveWithHashAndLoginTimeMarker( |
| 77 const std::string& marker_name, |
| 78 AuthAttemptState* attempt, |
| 79 scoped_refptr<CryptohomeAuthenticator> resolver, |
| 80 bool success, |
| 81 cryptohome::MountError return_code, |
| 82 const std::string& mount_hash) { |
| 83 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(marker_name, false); |
| 84 attempt->RecordCryptohomeStatus(success, return_code); |
| 85 if (success) |
| 86 attempt->RecordUsernameHash(mount_hash); |
| 87 else |
| 88 attempt->RecordUsernameHashFailed(); |
| 89 resolver->Resolve(); |
| 90 } |
| 91 |
71 // Calls cryptohome's mount method. | 92 // Calls cryptohome's mount method. |
72 void Mount(AuthAttemptState* attempt, | 93 void Mount(AuthAttemptState* attempt, |
73 scoped_refptr<CryptohomeAuthenticator> resolver, | 94 scoped_refptr<CryptohomeAuthenticator> resolver, |
74 int flags, | 95 bool ephemeral, |
| 96 bool create_if_nonexistent, |
75 const std::string& system_salt) { | 97 const std::string& system_salt) { |
76 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( | 98 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( |
77 "CryptohomeMount-Start", false); | 99 "CryptohomeMount-Start", false); |
78 // Set state that username_hash is requested here so that test implementation | 100 // Set state that username_hash is requested here so that test implementation |
79 // that returns directly would not generate 2 OnLoginSucces() calls. | 101 // that returns directly would not generate 2 OnLoginSucces() calls. |
80 attempt->UsernameHashRequested(); | 102 attempt->UsernameHashRequested(); |
81 | 103 |
82 scoped_ptr<Key> key = | 104 scoped_ptr<Key> key = |
83 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); | 105 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); |
84 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount( | 106 // Set the authentication's key label to an empty string, which is a wildcard |
85 attempt->user_context.GetUserID(), | 107 // allowing any key to match. This is necessary because cryptohomes created by |
86 key->GetSecret(), | 108 // Chrome OS M38 and older will have a legacy key with no label while those |
87 flags, | 109 // created by Chrome OS M39 and newer will have a key with the label |
88 base::Bind(&TriggerResolveWithLoginTimeMarker, | 110 // kCryptohomeGAIAKeyLabel. |
| 111 const cryptohome::KeyDefinition auth_key(key->GetSecret(), |
| 112 std::string(), |
| 113 cryptohome::PRIV_DEFAULT); |
| 114 cryptohome::MountParameters mount(ephemeral); |
| 115 if (create_if_nonexistent) { |
| 116 mount.create_keys.push_back(cryptohome::KeyDefinition( |
| 117 key->GetSecret(), |
| 118 kCryptohomeGAIAKeyLabel, |
| 119 cryptohome::PRIV_DEFAULT)); |
| 120 } |
| 121 |
| 122 cryptohome::HomedirMethods::GetInstance()->MountEx( |
| 123 cryptohome::Identification(attempt->user_context.GetUserID()), |
| 124 cryptohome::Authorization(auth_key), |
| 125 mount, |
| 126 base::Bind(&TriggerResolveWithHashAndLoginTimeMarker, |
89 "CryptohomeMount-End", | 127 "CryptohomeMount-End", |
90 attempt, | 128 attempt, |
91 resolver)); | 129 resolver)); |
92 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( | |
93 attempt->user_context.GetUserID(), | |
94 base::Bind(&TriggerResolveHash, attempt, resolver)); | |
95 } | 130 } |
96 | 131 |
97 // Calls cryptohome's mount method for guest and also get the user hash from | 132 // Calls cryptohome's mount method for guest and also get the user hash from |
98 // cryptohome. | 133 // cryptohome. |
99 void MountGuestAndGetHash(AuthAttemptState* attempt, | 134 void MountGuestAndGetHash(AuthAttemptState* attempt, |
100 scoped_refptr<CryptohomeAuthenticator> resolver) { | 135 scoped_refptr<CryptohomeAuthenticator> resolver) { |
101 attempt->UsernameHashRequested(); | 136 attempt->UsernameHashRequested(); |
102 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest( | 137 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest( |
103 base::Bind(&TriggerResolveWithLoginTimeMarker, | 138 base::Bind(&TriggerResolveWithLoginTimeMarker, |
104 "CryptohomeMount-End", | 139 "CryptohomeMount-End", |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 false, // unlock | 249 false, // unlock |
215 false, // online_complete | 250 false, // online_complete |
216 !IsKnownUser(user_context))); | 251 !IsKnownUser(user_context))); |
217 // Reset the verified flag. | 252 // Reset the verified flag. |
218 owner_is_verified_ = false; | 253 owner_is_verified_ = false; |
219 | 254 |
220 SystemSaltGetter::Get()->GetSystemSalt( | 255 SystemSaltGetter::Get()->GetSystemSalt( |
221 base::Bind(&Mount, | 256 base::Bind(&Mount, |
222 current_state_.get(), | 257 current_state_.get(), |
223 scoped_refptr<CryptohomeAuthenticator>(this), | 258 scoped_refptr<CryptohomeAuthenticator>(this), |
224 cryptohome::MOUNT_FLAGS_NONE)); | 259 false /* ephemeral */, |
| 260 false /* create_if_nonexistent */)); |
225 } | 261 } |
226 | 262 |
227 void CryptohomeAuthenticator::CompleteLogin(Profile* profile, | 263 void CryptohomeAuthenticator::CompleteLogin(Profile* profile, |
228 const UserContext& user_context) { | 264 const UserContext& user_context) { |
229 authentication_profile_ = profile; | 265 authentication_profile_ = profile; |
230 current_state_.reset(new AuthAttemptState(user_context, | 266 current_state_.reset(new AuthAttemptState(user_context, |
231 user_manager::USER_TYPE_REGULAR, | 267 user_manager::USER_TYPE_REGULAR, |
232 true, // unlock | 268 true, // unlock |
233 false, // online_complete | 269 false, // online_complete |
234 !IsKnownUser(user_context))); | 270 !IsKnownUser(user_context))); |
235 | 271 |
236 // Reset the verified flag. | 272 // Reset the verified flag. |
237 owner_is_verified_ = false; | 273 owner_is_verified_ = false; |
238 | 274 |
239 SystemSaltGetter::Get()->GetSystemSalt( | 275 SystemSaltGetter::Get()->GetSystemSalt( |
240 base::Bind(&Mount, | 276 base::Bind(&Mount, |
241 current_state_.get(), | 277 current_state_.get(), |
242 scoped_refptr<CryptohomeAuthenticator>(this), | 278 scoped_refptr<CryptohomeAuthenticator>(this), |
243 cryptohome::MOUNT_FLAGS_NONE)); | 279 false /* ephemeral */, |
| 280 false /* create_if_nonexistent */)); |
244 | 281 |
245 // For login completion from extension, we just need to resolve the current | 282 // For login completion from extension, we just need to resolve the current |
246 // auth attempt state, the rest of OAuth related tasks will be done in | 283 // auth attempt state, the rest of OAuth related tasks will be done in |
247 // parallel. | 284 // parallel. |
248 task_runner_->PostTask( | 285 task_runner_->PostTask( |
249 FROM_HERE, | 286 FROM_HERE, |
250 base::Bind(&CryptohomeAuthenticator::ResolveLoginCompletionStatus, this)); | 287 base::Bind(&CryptohomeAuthenticator::ResolveLoginCompletionStatus, this)); |
251 } | 288 } |
252 | 289 |
253 void CryptohomeAuthenticator::AuthenticateToUnlock( | 290 void CryptohomeAuthenticator::AuthenticateToUnlock( |
(...skipping 18 matching lines...) Expand all Loading... |
272 current_state_.reset(new AuthAttemptState(user_context, | 309 current_state_.reset(new AuthAttemptState(user_context, |
273 user_manager::USER_TYPE_SUPERVISED, | 310 user_manager::USER_TYPE_SUPERVISED, |
274 false, // unlock | 311 false, // unlock |
275 false, // online_complete | 312 false, // online_complete |
276 false)); // user_is_new | 313 false)); // user_is_new |
277 remove_user_data_on_failure_ = false; | 314 remove_user_data_on_failure_ = false; |
278 SystemSaltGetter::Get()->GetSystemSalt( | 315 SystemSaltGetter::Get()->GetSystemSalt( |
279 base::Bind(&Mount, | 316 base::Bind(&Mount, |
280 current_state_.get(), | 317 current_state_.get(), |
281 scoped_refptr<CryptohomeAuthenticator>(this), | 318 scoped_refptr<CryptohomeAuthenticator>(this), |
282 cryptohome::MOUNT_FLAGS_NONE)); | 319 false /* ephemeral */, |
| 320 false /* create_if_nonexistent */)); |
283 } | 321 } |
284 | 322 |
285 void CryptohomeAuthenticator::LoginRetailMode() { | 323 void CryptohomeAuthenticator::LoginRetailMode() { |
286 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 324 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
287 // Note: |kRetailModeUserEMail| is used in other places to identify a retail | 325 // Note: |kRetailModeUserEMail| is used in other places to identify a retail |
288 // mode session. | 326 // mode session. |
289 current_state_.reset( | 327 current_state_.reset( |
290 new AuthAttemptState(UserContext(chromeos::login::kRetailModeUserName), | 328 new AuthAttemptState(UserContext(chromeos::login::kRetailModeUserName), |
291 user_manager::USER_TYPE_RETAIL_MODE, | 329 user_manager::USER_TYPE_RETAIL_MODE, |
292 false, // unlock | 330 false, // unlock |
(...skipping 27 matching lines...) Expand all Loading... |
320 user_manager::USER_TYPE_PUBLIC_ACCOUNT, | 358 user_manager::USER_TYPE_PUBLIC_ACCOUNT, |
321 false, // unlock | 359 false, // unlock |
322 false, // online_complete | 360 false, // online_complete |
323 false)); // user_is_new | 361 false)); // user_is_new |
324 remove_user_data_on_failure_ = false; | 362 remove_user_data_on_failure_ = false; |
325 ephemeral_mount_attempted_ = true; | 363 ephemeral_mount_attempted_ = true; |
326 SystemSaltGetter::Get()->GetSystemSalt( | 364 SystemSaltGetter::Get()->GetSystemSalt( |
327 base::Bind(&Mount, | 365 base::Bind(&Mount, |
328 current_state_.get(), | 366 current_state_.get(), |
329 scoped_refptr<CryptohomeAuthenticator>(this), | 367 scoped_refptr<CryptohomeAuthenticator>(this), |
330 cryptohome::CREATE_IF_MISSING | cryptohome::ENSURE_EPHEMERAL)); | 368 true /* ephemeral */, |
| 369 true /* create_if_nonexistent */)); |
331 } | 370 } |
332 | 371 |
333 void CryptohomeAuthenticator::LoginAsKioskAccount( | 372 void CryptohomeAuthenticator::LoginAsKioskAccount( |
334 const std::string& app_user_id, | 373 const std::string& app_user_id, |
335 bool use_guest_mount) { | 374 bool use_guest_mount) { |
336 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 375 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
337 | 376 |
338 const std::string user_id = | 377 const std::string user_id = |
339 use_guest_mount ? chromeos::login::kGuestUserName : app_user_id; | 378 use_guest_mount ? chromeos::login::kGuestUserName : app_user_id; |
340 current_state_.reset(new AuthAttemptState(UserContext(user_id), | 379 current_state_.reset(new AuthAttemptState(UserContext(user_id), |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 495 |
457 void CryptohomeAuthenticator::OnOwnershipChecked(bool is_owner) { | 496 void CryptohomeAuthenticator::OnOwnershipChecked(bool is_owner) { |
458 // Now we can check if this user is the owner. | 497 // Now we can check if this user is the owner. |
459 user_can_login_ = is_owner; | 498 user_can_login_ = is_owner; |
460 owner_is_verified_ = true; | 499 owner_is_verified_ = true; |
461 Resolve(); | 500 Resolve(); |
462 } | 501 } |
463 | 502 |
464 void CryptohomeAuthenticator::Resolve() { | 503 void CryptohomeAuthenticator::Resolve() { |
465 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 504 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
466 int mount_flags = cryptohome::MOUNT_FLAGS_NONE; | 505 bool create_if_nonexistent = false; |
467 CryptohomeAuthenticator::AuthState state = ResolveState(); | 506 CryptohomeAuthenticator::AuthState state = ResolveState(); |
468 VLOG(1) << "Resolved state to: " << state; | 507 VLOG(1) << "Resolved state to: " << state; |
469 switch (state) { | 508 switch (state) { |
470 case CONTINUE: | 509 case CONTINUE: |
471 case POSSIBLE_PW_CHANGE: | 510 case POSSIBLE_PW_CHANGE: |
472 case NO_MOUNT: | 511 case NO_MOUNT: |
473 // These are intermediate states; we need more info from a request that | 512 // These are intermediate states; we need more info from a request that |
474 // is still pending. | 513 // is still pending. |
475 break; | 514 break; |
476 case FAILED_MOUNT: | 515 case FAILED_MOUNT: |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 AuthFailure(AuthFailure::USERNAME_HASH_FAILED))); | 559 AuthFailure(AuthFailure::USERNAME_HASH_FAILED))); |
521 break; | 560 break; |
522 case REMOVED_DATA_AFTER_FAILURE: | 561 case REMOVED_DATA_AFTER_FAILURE: |
523 remove_user_data_on_failure_ = false; | 562 remove_user_data_on_failure_ = false; |
524 task_runner_->PostTask(FROM_HERE, | 563 task_runner_->PostTask(FROM_HERE, |
525 base::Bind(&CryptohomeAuthenticator::OnAuthFailure, | 564 base::Bind(&CryptohomeAuthenticator::OnAuthFailure, |
526 this, | 565 this, |
527 *delayed_login_failure_)); | 566 *delayed_login_failure_)); |
528 break; | 567 break; |
529 case CREATE_NEW: | 568 case CREATE_NEW: |
530 mount_flags |= cryptohome::CREATE_IF_MISSING; | 569 create_if_nonexistent = true; |
531 case RECOVER_MOUNT: | 570 case RECOVER_MOUNT: |
532 current_state_->ResetCryptohomeStatus(); | 571 current_state_->ResetCryptohomeStatus(); |
533 SystemSaltGetter::Get()->GetSystemSalt( | 572 SystemSaltGetter::Get()->GetSystemSalt( |
534 base::Bind(&Mount, | 573 base::Bind(&Mount, |
535 current_state_.get(), | 574 current_state_.get(), |
536 scoped_refptr<CryptohomeAuthenticator>(this), | 575 scoped_refptr<CryptohomeAuthenticator>(this), |
537 mount_flags)); | 576 false /*ephemeral*/, |
| 577 create_if_nonexistent)); |
538 break; | 578 break; |
539 case NEED_OLD_PW: | 579 case NEED_OLD_PW: |
540 task_runner_->PostTask( | 580 task_runner_->PostTask( |
541 FROM_HERE, | 581 FROM_HERE, |
542 base::Bind(&CryptohomeAuthenticator::OnPasswordChangeDetected, this)); | 582 base::Bind(&CryptohomeAuthenticator::OnPasswordChangeDetected, this)); |
543 break; | 583 break; |
544 case ONLINE_FAILED: | 584 case ONLINE_FAILED: |
545 case NEED_NEW_PW: | 585 case NEED_NEW_PW: |
546 case HAVE_NEW_PW: | 586 case HAVE_NEW_PW: |
547 NOTREACHED() << "Using obsolete ClientLogin code path."; | 587 NOTREACHED() << "Using obsolete ClientLogin code path."; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 Resolve(); | 788 Resolve(); |
749 } | 789 } |
750 | 790 |
751 void CryptohomeAuthenticator::SetOwnerState(bool owner_check_finished, | 791 void CryptohomeAuthenticator::SetOwnerState(bool owner_check_finished, |
752 bool check_result) { | 792 bool check_result) { |
753 owner_is_verified_ = owner_check_finished; | 793 owner_is_verified_ = owner_check_finished; |
754 user_can_login_ = check_result; | 794 user_can_login_ = check_result; |
755 } | 795 } |
756 | 796 |
757 } // namespace chromeos | 797 } // namespace chromeos |
OLD | NEW |