diff options
author | alemate <alemate@chromium.org> | 2016-03-09 15:02:35 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-09 23:03:40 +0000 |
commit | ad238d39cab83b2c09094a2f769e603bedb40e54 (patch) | |
tree | 1cc2a68d4bb850b1be2c3b0b01e986f66c13ef61 /chromeos | |
parent | 1e270c8e09de0b1863cb7a66c02259439e059eda (diff) | |
download | chromium_src-ad238d39cab83b2c09094a2f769e603bedb40e54.zip chromium_src-ad238d39cab83b2c09094a2f769e603bedb40e54.tar.gz chromium_src-ad238d39cab83b2c09094a2f769e603bedb40e54.tar.bz2 |
ChromeOS: Add RenameCryptohome and migration code.
This CL adds support for renaming existing cryptohomes to new id
(RenameCreptohome dbus call).
BUG=462823
TEST=manual
Review URL: https://codereview.chromium.org/1738023002
Cr-Commit-Position: refs/heads/master@{#380253}
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/cryptohome/homedir_methods.cc | 8 | ||||
-rw-r--r-- | chromeos/cryptohome/homedir_methods.h | 6 | ||||
-rw-r--r-- | chromeos/cryptohome/mock_homedir_methods.h | 4 | ||||
-rw-r--r-- | chromeos/dbus/cryptohome_client.cc | 20 | ||||
-rw-r--r-- | chromeos/dbus/cryptohome_client.h | 7 | ||||
-rw-r--r-- | chromeos/dbus/fake_cryptohome_client.cc | 8 | ||||
-rw-r--r-- | chromeos/dbus/fake_cryptohome_client.h | 3 | ||||
-rw-r--r-- | chromeos/dbus/mock_cryptohome_client.h | 4 | ||||
-rw-r--r-- | chromeos/login/auth/cryptohome_authenticator.cc | 116 |
9 files changed, 173 insertions, 3 deletions
diff --git a/chromeos/cryptohome/homedir_methods.cc b/chromeos/cryptohome/homedir_methods.cc index 81bf153..bd276ec 100644 --- a/chromeos/cryptohome/homedir_methods.cc +++ b/chromeos/cryptohome/homedir_methods.cc @@ -278,6 +278,14 @@ class HomedirMethodsImpl : public HomedirMethods { weak_ptr_factory_.GetWeakPtr(), callback)); } + void RenameCryptohome(const Identification& id_from, + const Identification& id_to, + const Callback& callback) override { + DBusThreadManager::Get()->GetCryptohomeClient()->RenameCryptohome( + id_from, id_to, base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + private: void OnGetKeyDataExCallback(const GetKeyDataCallback& callback, chromeos::DBusMethodCallStatus call_status, diff --git a/chromeos/cryptohome/homedir_methods.h b/chromeos/cryptohome/homedir_methods.h index 17f0f55..3f40f4a 100644 --- a/chromeos/cryptohome/homedir_methods.h +++ b/chromeos/cryptohome/homedir_methods.h @@ -89,6 +89,12 @@ class CHROMEOS_EXPORT HomedirMethods { const std::string& label, const Callback& callback) = 0; + // Asks cryptohomed to change cryptohome identification |id_from| to |id_to|, + // which results in cryptohome directory renaming. + virtual void RenameCryptohome(const Identification& id_from, + const Identification& id_to, + const Callback& callback) = 0; + // Creates the global HomedirMethods instance. static void Initialize(); diff --git a/chromeos/cryptohome/mock_homedir_methods.h b/chromeos/cryptohome/mock_homedir_methods.h index 81a82a2..b2e5e8a 100644 --- a/chromeos/cryptohome/mock_homedir_methods.h +++ b/chromeos/cryptohome/mock_homedir_methods.h @@ -51,6 +51,10 @@ class CHROMEOS_EXPORT MockHomedirMethods : public HomedirMethods { const KeyDefinition& key, const std::string& signature, const Callback& callback)); + MOCK_METHOD3(RenameCryptohome, + void(const Identification& id_from, + const Identification& id_to, + const Callback& callback)); private: bool success_; diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc index 0df97a3..bdf5125 100644 --- a/chromeos/dbus/cryptohome_client.cc +++ b/chromeos/dbus/cryptohome_client.cc @@ -128,6 +128,26 @@ class CryptohomeClientImpl : public CryptohomeClient { } // CryptohomeClient override. + void RenameCryptohome(const cryptohome::Identification& cryptohome_id_from, + const cryptohome::Identification& cryptohome_id_to, + const ProtobufMethodCallback& callback) override { + const char* method_name = cryptohome::kCryptohomeRenameCryptohome; + dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); + + cryptohome::AccountIdentifier id_from_proto; + cryptohome::AccountIdentifier id_to_proto; + FillIdentificationProtobuf(cryptohome_id_from, &id_from_proto); + FillIdentificationProtobuf(cryptohome_id_to, &id_to_proto); + + dbus::MessageWriter writer(&method_call); + writer.AppendProtoAsArrayOfBytes(id_from_proto); + writer.AppendProtoAsArrayOfBytes(id_to_proto); + proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs, + base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + + // CryptohomeClient override. void GetSystemSalt(const GetSystemSaltCallback& callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSystemSalt); diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h index 233ff93..15ce84f 100644 --- a/chromeos/dbus/cryptohome_client.h +++ b/chromeos/dbus/cryptohome_client.h @@ -139,6 +139,13 @@ class CHROMEOS_EXPORT CryptohomeClient : public DBusClient { virtual void AsyncRemove(const cryptohome::Identification& cryptohome_id, const AsyncMethodCallback& callback) = 0; + // Calls RenameCryptohome method. |callback| is called after the method + // call succeeds. + virtual void RenameCryptohome( + const cryptohome::Identification& cryptohome_id_from, + const cryptohome::Identification& cryptohome_id_to, + const ProtobufMethodCallback& callback) = 0; + // Calls GetSystemSalt method. |callback| is called after the method call // succeeds. virtual void GetSystemSalt(const GetSystemSaltCallback& callback) = 0; diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc index 2ae9197..e85161c 100644 --- a/chromeos/dbus/fake_cryptohome_client.cc +++ b/chromeos/dbus/fake_cryptohome_client.cc @@ -93,6 +93,14 @@ void FakeCryptohomeClient::AsyncRemove( ReturnAsyncMethodResult(callback, false); } +void FakeCryptohomeClient::RenameCryptohome( + const cryptohome::Identification& cryptohome_id_from, + const cryptohome::Identification& cryptohome_id_to, + const ProtobufMethodCallback& callback) { + cryptohome::BaseReply reply; + ReturnProtobufMethodCallback(reply, callback); +} + void FakeCryptohomeClient::GetSystemSalt( const GetSystemSaltCallback& callback) { base::MessageLoop::current()->PostTask( diff --git a/chromeos/dbus/fake_cryptohome_client.h b/chromeos/dbus/fake_cryptohome_client.h index 20402dc..9fb1f49 100644 --- a/chromeos/dbus/fake_cryptohome_client.h +++ b/chromeos/dbus/fake_cryptohome_client.h @@ -38,6 +38,9 @@ class CHROMEOS_EXPORT FakeCryptohomeClient : public CryptohomeClient { const AsyncMethodCallback& callback) override; void AsyncRemove(const cryptohome::Identification& cryptohome_id, const AsyncMethodCallback& callback) override; + void RenameCryptohome(const cryptohome::Identification& cryptohome_id_from, + const cryptohome::Identification& cryptohome_id_to, + const ProtobufMethodCallback& callback) override; void GetSystemSalt(const GetSystemSaltCallback& callback) override; void GetSanitizedUsername(const cryptohome::Identification& cryptohome_id, const StringDBusMethodCallback& callback) override; diff --git a/chromeos/dbus/mock_cryptohome_client.h b/chromeos/dbus/mock_cryptohome_client.h index c4e166b..35b683b 100644 --- a/chromeos/dbus/mock_cryptohome_client.h +++ b/chromeos/dbus/mock_cryptohome_client.h @@ -42,6 +42,10 @@ class MockCryptohomeClient : public CryptohomeClient { MOCK_METHOD2(AsyncRemove, void(const cryptohome::Identification& cryptohome_id, const AsyncMethodCallback& callback)); + MOCK_METHOD3(RenameCryptohome, + void(const cryptohome::Identification& id_from, + const cryptohome::Identification& id_to, + const ProtobufMethodCallback& callback)); MOCK_METHOD1(GetSystemSalt, void(const GetSystemSaltCallback& callback)); MOCK_METHOD2(GetSanitizedUsername, diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc index 913af5d..afae8d96 100644 --- a/chromeos/login/auth/cryptohome_authenticator.cc +++ b/chromeos/login/auth/cryptohome_authenticator.cc @@ -13,6 +13,8 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" +#include "base/metrics/histogram_macros.h" +#include "chromeos/chromeos_switches.h" #include "chromeos/cryptohome/async_method_caller.h" #include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/cryptohome/homedir_methods.h" @@ -27,6 +29,7 @@ #include "chromeos/login_event_recorder.h" #include "components/device_event_log/device_event_log.h" #include "components/signin/core/account_id/account_id.h" +#include "components/user_manager/known_user.h" #include "components/user_manager/user_type.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -45,6 +48,30 @@ const char kKeyProviderDataTypeName[] = "type"; // credentials is stored. const char kKeyProviderDataSaltName[] = "salt"; +// Name of UMA histogram. +const char kCryptohomeMigrationToGaiaId[] = "Cryptohome.MigrationToGaiaId"; + +// This enum is used to define the buckets for an enumerated UMA histogram. +// Hence, +// (a) existing enumerated constants should never be deleted or reordered, and +// (b) new constants should only be appended at the end of the enumeration. +// +// This must be kept in sync with enum CryptohomeMigrationToGaiaId in +// histograms.xml . +enum CryptohomeMigrationToGaiaId { + NOT_STARTED = 0, + ALREADY_MIGRATED = 1, + SUCCESS = 2, + FAILURE = 3, + ENTRIES_COUNT +}; + +// Report to UMA. +void UMACryptohomeMigrationToGaiaId(const CryptohomeMigrationToGaiaId status) { + UMA_HISTOGRAM_ENUMERATION(kCryptohomeMigrationToGaiaId, status, + CryptohomeMigrationToGaiaId::ENTRIES_COUNT); +} + // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. // Returns the keys unmodified otherwise. scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, @@ -154,6 +181,86 @@ void DoMount(const base::WeakPtr<AuthAttemptState>& attempt, base::Bind(&OnMount, attempt, resolver)); } +// Handle cryptohome migration status. +void OnCryptohomeRenamed(const base::WeakPtr<AuthAttemptState>& attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent, + bool success, + cryptohome::MountError return_code) { + chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( + "CryptohomeRename-End", false); + const AccountId account_id = attempt->user_context.GetAccountId(); + if (success) { + cryptohome::SetGaiaIdMigrationStatusDone(account_id); + UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::SUCCESS); + } else { + LOG(ERROR) << "Failed to rename cryptohome for account_id='" + << account_id.Serialize() << "' (return_code=" << return_code + << ")"; + // If rename fails, we can still use legacy cryptohome identifier. + // Proceed to DoMount. + UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::FAILURE); + } + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); +} + +// This method migrates cryptohome identifier to gaia id (if needed), +// and then calls Mount. +void EnsureCryptohomeMigratedToGaiaId( + const base::WeakPtr<AuthAttemptState>& attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent) { + const bool is_gaiaid_migration_started = switches::IsGaiaIdMigrationStarted(); + if (!is_gaiaid_migration_started) { + UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::NOT_STARTED); + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + return; + } + const bool already_migrated = cryptohome::GetGaiaIdMigrationStatus( + attempt->user_context.GetAccountId()); + const bool has_gaia_id = + !attempt->user_context.GetAccountId().GetGaiaId().empty(); + + bool need_migration = false; + if (!create_if_nonexistent && !already_migrated) { + if (has_gaia_id) { + need_migration = true; + } else { + LOG(WARNING) << "Account '" + << attempt->user_context.GetAccountId().Serialize() + << "' has no gaia id. Cryptohome migration skipped."; + } + } + if (need_migration) { + chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( + "CryptohomeRename-Start", false); + const std::string& cryptohome_id_from = + attempt->user_context.GetAccountId().GetUserEmail(); // Migrated + const std::string cryptohome_id_to = + attempt->user_context.GetAccountId().GetGaiaIdKey(); + + cryptohome::HomedirMethods::GetInstance()->RenameCryptohome( + cryptohome::Identification::FromString(cryptohome_id_from), + cryptohome::Identification::FromString(cryptohome_id_to), + base::Bind(&OnCryptohomeRenamed, attempt, resolver, ephemeral, + create_if_nonexistent)); + return; + } + if (!already_migrated && has_gaia_id) { + // Mark new users migrated. + cryptohome::SetGaiaIdMigrationStatusDone( + attempt->user_context.GetAccountId()); + } + if (already_migrated) { + UMACryptohomeMigrationToGaiaId( + CryptohomeMigrationToGaiaId::ALREADY_MIGRATED); + } + + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); +} + // Callback invoked when the system salt has been retrieved. Transforms the key // in |attempt->user_context| using Chrome's default hashing algorithm and the // system salt, then calls MountEx(). @@ -169,7 +276,8 @@ void OnGetSystemSalt(const base::WeakPtr<AuthAttemptState>& attempt, Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt); - DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral, + create_if_nonexistent); } // Callback invoked when cryptohome's GetKeyDataEx() method has finished. @@ -228,7 +336,8 @@ void OnGetKeyDataEx( attempt->user_context.GetKey()->Transform( static_cast<Key::KeyType>(*type), *salt); - DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral, + create_if_nonexistent); return; } } else { @@ -261,7 +370,8 @@ void StartMount(const base::WeakPtr<AuthAttemptState>& attempt, if (attempt->user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) { - DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + EnsureCryptohomeMigratedToGaiaId(attempt, resolver, ephemeral, + create_if_nonexistent); return; } |