Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: chromeos/login/auth/cryptohome_authenticator.cc

Issue 1738023002: ChromeOS: Add RenameCryptohome and migration code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@462823--Chrome-OS-handles-deletion-of-Gmail-account-poorly--Create-AccountID-structure-part11--migrate-cryptohomes
Patch Set: Update after review. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromeos/dbus/mock_cryptohome_client.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stdint.h> 7 #include <stdint.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h" 15 #include "base/memory/weak_ptr.h"
16 #include "base/metrics/histogram_macros.h"
17 #include "chromeos/chromeos_switches.h"
16 #include "chromeos/cryptohome/async_method_caller.h" 18 #include "chromeos/cryptohome/async_method_caller.h"
17 #include "chromeos/cryptohome/cryptohome_parameters.h" 19 #include "chromeos/cryptohome/cryptohome_parameters.h"
18 #include "chromeos/cryptohome/homedir_methods.h" 20 #include "chromeos/cryptohome/homedir_methods.h"
19 #include "chromeos/cryptohome/system_salt_getter.h" 21 #include "chromeos/cryptohome/system_salt_getter.h"
20 #include "chromeos/dbus/cryptohome_client.h" 22 #include "chromeos/dbus/cryptohome_client.h"
21 #include "chromeos/dbus/dbus_thread_manager.h" 23 #include "chromeos/dbus/dbus_thread_manager.h"
22 #include "chromeos/login/auth/auth_status_consumer.h" 24 #include "chromeos/login/auth/auth_status_consumer.h"
23 #include "chromeos/login/auth/key.h" 25 #include "chromeos/login/auth/key.h"
24 #include "chromeos/login/auth/user_context.h" 26 #include "chromeos/login/auth/user_context.h"
25 #include "chromeos/login/login_state.h" 27 #include "chromeos/login/login_state.h"
26 #include "chromeos/login/user_names.h" 28 #include "chromeos/login/user_names.h"
27 #include "chromeos/login_event_recorder.h" 29 #include "chromeos/login_event_recorder.h"
28 #include "components/device_event_log/device_event_log.h" 30 #include "components/device_event_log/device_event_log.h"
29 #include "components/signin/core/account_id/account_id.h" 31 #include "components/signin/core/account_id/account_id.h"
32 #include "components/user_manager/known_user.h"
30 #include "components/user_manager/user_type.h" 33 #include "components/user_manager/user_type.h"
31 #include "third_party/cros_system_api/dbus/service_constants.h" 34 #include "third_party/cros_system_api/dbus/service_constants.h"
32 35
33 namespace chromeos { 36 namespace chromeos {
34 37
35 namespace { 38 namespace {
36 39
37 // The label used for the key derived from the user's GAIA credentials. 40 // The label used for the key derived from the user's GAIA credentials.
38 const char kCryptohomeGAIAKeyLabel[] = "gaia"; 41 const char kCryptohomeGAIAKeyLabel[] = "gaia";
39 42
40 // The name under which the type of key generated from the user's GAIA 43 // The name under which the type of key generated from the user's GAIA
41 // credentials is stored. 44 // credentials is stored.
42 const char kKeyProviderDataTypeName[] = "type"; 45 const char kKeyProviderDataTypeName[] = "type";
43 46
44 // The name under which the salt used to generate a key from the user's GAIA 47 // The name under which the salt used to generate a key from the user's GAIA
45 // credentials is stored. 48 // credentials is stored.
46 const char kKeyProviderDataSaltName[] = "salt"; 49 const char kKeyProviderDataSaltName[] = "salt";
47 50
51 // Name of UMA histogram.
52 const char kCryptohomeMigrationToGaiaId[] = "Cryptohome.MigrationToGaiaId";
53
54 // This enum is used to define the buckets for an enumerated UMA histogram.
55 // Hence,
56 // (a) existing enumerated constants should never be deleted or reordered, and
57 // (b) new constants should only be appended at the end of the enumeration.
58 //
59 // This must be kept in sync with enum CryptohomeMigrationToGaiaId in
60 // histograms.xml .
61 enum CryptohomeMigrationToGaiaId {
62 NOT_STARTED = 0,
63 ALREADY_MIGRATED = 1,
64 SUCCESS = 2,
65 FAILURE = 3,
66 ENTRIES_COUNT
67 };
68
69 // Report to UMA.
70 void UMACryptohomeMigrationToGaiaId(const CryptohomeMigrationToGaiaId status) {
71 UMA_HISTOGRAM_ENUMERATION(kCryptohomeMigrationToGaiaId, status,
72 CryptohomeMigrationToGaiaId::ENTRIES_COUNT);
73 }
74
48 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. 75 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN.
49 // Returns the keys unmodified otherwise. 76 // Returns the keys unmodified otherwise.
50 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, 77 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key,
51 const std::string& system_salt) { 78 const std::string& system_salt) {
52 scoped_ptr<Key> result(new Key(key)); 79 scoped_ptr<Key> result(new Key(key));
53 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN) 80 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN)
54 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt); 81 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt);
55 82
56 return result; 83 return result;
57 } 84 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 kCryptohomeGAIAKeyLabel, 174 kCryptohomeGAIAKeyLabel,
148 cryptohome::PRIV_DEFAULT)); 175 cryptohome::PRIV_DEFAULT));
149 } 176 }
150 177
151 cryptohome::HomedirMethods::GetInstance()->MountEx( 178 cryptohome::HomedirMethods::GetInstance()->MountEx(
152 cryptohome::Identification(attempt->user_context.GetAccountId()), 179 cryptohome::Identification(attempt->user_context.GetAccountId()),
153 cryptohome::Authorization(auth_key), mount, 180 cryptohome::Authorization(auth_key), mount,
154 base::Bind(&OnMount, attempt, resolver)); 181 base::Bind(&OnMount, attempt, resolver));
155 } 182 }
156 183
184 // Handle cryptohome migration status.
185 void OnCryptohomeRenamed(const base::WeakPtr<AuthAttemptState>& attempt,
186 scoped_refptr<CryptohomeAuthenticator> resolver,
187 bool ephemeral,
188 bool create_if_nonexistent,
189 bool success,
190 cryptohome::MountError return_code) {
191 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
192 "CryptohomeRename-End", false);
193 const AccountId account_id = attempt->user_context.GetAccountId();
194 if (success) {
195 cryptohome::SetGaiaIdMigrationStatusDone(account_id);
196 UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::SUCCESS);
197 } else {
198 LOG(ERROR) << "Failed to rename cryptohome for account_id='"
199 << account_id.Serialize() << "' (return_code=" << return_code
200 << ")";
201 // If rename fails, we can still use legacy cryptohome identifier.
202 // Proceed to DoMount.
203 UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::FAILURE);
204 }
205 DoMount(attempt, resolver, ephemeral, create_if_nonexistent);
206 }
207
208 // This method migrates cryptohome identifier to gaia id (if needed),
209 // and then calls Mount.
210 void EnsureCryptohomeMigratedToGaiaId(
211 const base::WeakPtr<AuthAttemptState>& attempt,
212 scoped_refptr<CryptohomeAuthenticator> resolver,
213 bool ephemeral,
214 bool create_if_nonexistent) {
215 const bool is_gaiaid_migration_started = switches::IsGaiaIdMigrationStarted();
216 if (!is_gaiaid_migration_started) {
217 UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::NOT_STARTED);
218 DoMount(attempt, resolver, ephemeral, create_if_nonexistent);
219 return;
220 }
221 const bool already_migrated = cryptohome::GetGaiaIdMigrationStatus(
222 attempt->user_context.GetAccountId());
223 const bool has_gaia_id =
224 !attempt->user_context.GetAccountId().GetGaiaId().empty();
225
226 bool need_migration = false;
227 if (!create_if_nonexistent && !already_migrated) {
228 if (has_gaia_id) {
229 need_migration = true;
230 } else {
231 LOG(WARNING) << "Account '"
232 << attempt->user_context.GetAccountId().Serialize()
233 << "' has no gaia id. Cryptohome migration skipped.";
234 }
235 }
236 if (need_migration) {
237 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
238 "CryptohomeRename-Start", false);
239 const std::string& cryptohome_id_from =
240 attempt->user_context.GetAccountId().GetUserEmail(); // Migrated
241 const std::string cryptohome_id_to =
242 attempt->user_context.GetAccountId().GetGaiaIdKey();
243
244 cryptohome::HomedirMethods::GetInstance()->RenameCryptohome(
245 cryptohome::Identification::FromString(cryptohome_id_from),
246 cryptohome::Identification::FromString(cryptohome_id_to),
247 base::Bind(&OnCryptohomeRenamed, attempt, resolver, ephemeral,
248 create_if_nonexistent));
249 return;
250 }
251 if (!already_migrated && has_gaia_id) {
252 // Mark new users migrated.
253 cryptohome::SetGaiaIdMigrationStatusDone(
254 attempt->user_context.GetAccountId());
255 }
256 if (already_migrated) {
257 UMACryptohomeMigrationToGaiaId(
258 CryptohomeMigrationToGaiaId::ALREADY_MIGRATED);
259 }
260
261 DoMount(attempt, resolver, ephemeral, create_if_nonexistent);
262 }
263
157 // Callback invoked when the system salt has been retrieved. Transforms the key 264 // Callback invoked when the system salt has been retrieved. Transforms the key
158 // in |attempt->user_context| using Chrome's default hashing algorithm and the 265 // in |attempt->user_context| using Chrome's default hashing algorithm and the
159 // system salt, then calls MountEx(). 266 // system salt, then calls MountEx().
160 void OnGetSystemSalt(const base::WeakPtr<AuthAttemptState>& attempt, 267 void OnGetSystemSalt(const base::WeakPtr<AuthAttemptState>& attempt,
161 scoped_refptr<CryptohomeAuthenticator> resolver, 268 scoped_refptr<CryptohomeAuthenticator> resolver,
162 bool ephemeral, 269 bool ephemeral,
163 bool create_if_nonexistent, 270 bool create_if_nonexistent,
164 const std::string& system_salt) { 271 const std::string& system_salt) {
165 DCHECK_EQ(Key::KEY_TYPE_PASSWORD_PLAIN, 272 DCHECK_EQ(Key::KEY_TYPE_PASSWORD_PLAIN,
166 attempt->user_context.GetKey()->GetKeyType()); 273 attempt->user_context.GetKey()->GetKeyType());
167 274
168 attempt->user_context.GetKey()->Transform( 275 attempt->user_context.GetKey()->Transform(
169 Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, 276 Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
170 system_salt); 277 system_salt);
171 278
172 DoMount(attempt, resolver, ephemeral, create_if_nonexistent); 279 EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral,
280 create_if_nonexistent);
173 } 281 }
174 282
175 // Callback invoked when cryptohome's GetKeyDataEx() method has finished. 283 // Callback invoked when cryptohome's GetKeyDataEx() method has finished.
176 // * If GetKeyDataEx() returned metadata indicating the hashing algorithm and 284 // * If GetKeyDataEx() returned metadata indicating the hashing algorithm and
177 // salt that were used to generate the key for this user's cryptohome, 285 // salt that were used to generate the key for this user's cryptohome,
178 // transforms the key in |attempt->user_context| with the same parameters. 286 // transforms the key in |attempt->user_context| with the same parameters.
179 // * Otherwise, starts the retrieval of the system salt so that the key in 287 // * Otherwise, starts the retrieval of the system salt so that the key in
180 // |attempt->user_context| can be transformed with Chrome's default hashing 288 // |attempt->user_context| can be transformed with Chrome's default hashing
181 // algorithm and the system salt. 289 // algorithm and the system salt.
182 // The resulting key is then passed to cryptohome's MountEx(). 290 // The resulting key is then passed to cryptohome's MountEx().
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 329
222 if (!salt) { 330 if (!salt) {
223 LOGIN_LOG(ERROR) << "Missing salt."; 331 LOGIN_LOG(ERROR) << "Missing salt.";
224 RecordKeyErrorAndResolve(attempt, resolver); 332 RecordKeyErrorAndResolve(attempt, resolver);
225 return; 333 return;
226 } 334 }
227 335
228 attempt->user_context.GetKey()->Transform( 336 attempt->user_context.GetKey()->Transform(
229 static_cast<Key::KeyType>(*type), 337 static_cast<Key::KeyType>(*type),
230 *salt); 338 *salt);
231 DoMount(attempt, resolver, ephemeral, create_if_nonexistent); 339 EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral,
340 create_if_nonexistent);
232 return; 341 return;
233 } 342 }
234 } else { 343 } else {
235 LOGIN_LOG(EVENT) << "GetKeyDataEx() returned " << key_definitions.size() 344 LOGIN_LOG(EVENT) << "GetKeyDataEx() returned " << key_definitions.size()
236 << " entries."; 345 << " entries.";
237 } 346 }
238 } 347 }
239 348
240 SystemSaltGetter::Get()->GetSystemSalt(base::Bind(&OnGetSystemSalt, 349 SystemSaltGetter::Get()->GetSystemSalt(base::Bind(&OnGetSystemSalt,
241 attempt, 350 attempt,
(...skipping 12 matching lines...) Expand all
254 // transformed accordingly before calling MountEx(). 363 // transformed accordingly before calling MountEx().
255 void StartMount(const base::WeakPtr<AuthAttemptState>& attempt, 364 void StartMount(const base::WeakPtr<AuthAttemptState>& attempt,
256 scoped_refptr<CryptohomeAuthenticator> resolver, 365 scoped_refptr<CryptohomeAuthenticator> resolver,
257 bool ephemeral, 366 bool ephemeral,
258 bool create_if_nonexistent) { 367 bool create_if_nonexistent) {
259 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( 368 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
260 "CryptohomeMount-Start", false); 369 "CryptohomeMount-Start", false);
261 370
262 if (attempt->user_context.GetKey()->GetKeyType() != 371 if (attempt->user_context.GetKey()->GetKeyType() !=
263 Key::KEY_TYPE_PASSWORD_PLAIN) { 372 Key::KEY_TYPE_PASSWORD_PLAIN) {
264 DoMount(attempt, resolver, ephemeral, create_if_nonexistent); 373 EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral,
374 create_if_nonexistent);
265 return; 375 return;
266 } 376 }
267 377
268 cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx( 378 cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx(
269 cryptohome::Identification(attempt->user_context.GetAccountId()), 379 cryptohome::Identification(attempt->user_context.GetAccountId()),
270 kCryptohomeGAIAKeyLabel, base::Bind(&OnGetKeyDataEx, attempt, resolver, 380 kCryptohomeGAIAKeyLabel, base::Bind(&OnGetKeyDataEx, attempt, resolver,
271 ephemeral, create_if_nonexistent)); 381 ephemeral, create_if_nonexistent));
272 } 382 }
273 383
274 // Calls cryptohome's mount method for guest and also get the user hash from 384 // Calls cryptohome's mount method for guest and also get the user hash from
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 Resolve(); 980 Resolve();
871 } 981 }
872 982
873 void CryptohomeAuthenticator::SetOwnerState(bool owner_check_finished, 983 void CryptohomeAuthenticator::SetOwnerState(bool owner_check_finished,
874 bool check_result) { 984 bool check_result) {
875 owner_is_verified_ = owner_check_finished; 985 owner_is_verified_ = owner_check_finished;
876 user_can_login_ = check_result; 986 user_can_login_ = check_result;
877 } 987 }
878 988
879 } // namespace chromeos 989 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/dbus/mock_cryptohome_client.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698