summaryrefslogtreecommitdiffstats
path: root/chromeos/login
diff options
context:
space:
mode:
authorxiyuan <xiyuan@chromium.org>2014-10-14 17:49:49 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-15 00:51:27 +0000
commit00fd892bd95a5a4460a746cae9f8df9ad23d4063 (patch)
tree5f4d77a5e0a43d3ee45088de682bc73310eb009f /chromeos/login
parent53a23efdc6f0a70ab81d68ff8501da9e56a45fbf (diff)
downloadchromium_src-00fd892bd95a5a4460a746cae9f8df9ad23d4063.zip
chromium_src-00fd892bd95a5a4460a746cae9f8df9ad23d4063.tar.gz
chromium_src-00fd892bd95a5a4460a746cae9f8df9ad23d4063.tar.bz2
easy-signin: Use ExtendedAuthenticator for unlock.
- Use ExtendedAuthenticator for unlock so that cryptohome CheckKeyEx is used to check all keys. This solves the problem in 419532 that password based key is not checked when signing in using the phone. - Make ExtendedAuthenticator an interface. - Implementation is moved to ExtendedAuthenticatorImpl. - Added a FakeExtendedAuthenticator. - Make ScreenLockerTester::InjectMockAuthenticator to mock ExtendedAuthenticator as well. BUG=419532, 351268 TBR=pam@chromium.org for supervised_user change Review URL: https://codereview.chromium.org/642753003 Cr-Commit-Position: refs/heads/master@{#299602}
Diffstat (limited to 'chromeos/login')
-rw-r--r--chromeos/login/auth/extended_authenticator.cc352
-rw-r--r--chromeos/login/auth/extended_authenticator.h99
-rw-r--r--chromeos/login/auth/extended_authenticator_impl.cc366
-rw-r--r--chromeos/login/auth/extended_authenticator_impl.h103
-rw-r--r--chromeos/login/auth/fake_extended_authenticator.cc113
-rw-r--r--chromeos/login/auth/fake_extended_authenticator.h65
6 files changed, 688 insertions, 410 deletions
diff --git a/chromeos/login/auth/extended_authenticator.cc b/chromeos/login/auth/extended_authenticator.cc
index 0b81439..cd5a3f2 100644
--- a/chromeos/login/auth/extended_authenticator.cc
+++ b/chromeos/login/auth/extended_authenticator.cc
@@ -4,358 +4,26 @@
#include "chromeos/login/auth/extended_authenticator.h"
-#include "base/bind.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "chromeos/cryptohome/async_method_caller.h"
-#include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/cryptohome/homedir_methods.h"
-#include "chromeos/cryptohome/system_salt_getter.h"
-#include "chromeos/dbus/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/login/auth/auth_status_consumer.h"
-#include "chromeos/login/auth/key.h"
-#include "chromeos/login/auth/user_context.h"
-#include "chromeos/login_event_recorder.h"
-#include "crypto/sha2.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "chromeos/login/auth/extended_authenticator_impl.h"
namespace chromeos {
-namespace {
-
-void RecordStartMarker(const std::string& marker) {
- std::string full_marker = "Cryptohome-";
- full_marker.append(marker);
- full_marker.append("-Start");
- chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
-}
-
-void RecordEndMarker(const std::string& marker) {
- std::string full_marker = "Cryptohome-";
- full_marker.append(marker);
- full_marker.append("-End");
- chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
-}
-
-} // namespace
-
-ExtendedAuthenticator::ExtendedAuthenticator(NewAuthStatusConsumer* consumer)
- : salt_obtained_(false), consumer_(consumer), old_consumer_(NULL) {
- SystemSaltGetter::Get()->GetSystemSalt(
- base::Bind(&ExtendedAuthenticator::OnSaltObtained, this));
-}
-
-ExtendedAuthenticator::ExtendedAuthenticator(AuthStatusConsumer* consumer)
- : salt_obtained_(false), consumer_(NULL), old_consumer_(consumer) {
- SystemSaltGetter::Get()->GetSystemSalt(
- base::Bind(&ExtendedAuthenticator::OnSaltObtained, this));
-}
-
-void ExtendedAuthenticator::SetConsumer(AuthStatusConsumer* consumer) {
- old_consumer_ = consumer;
-}
-
-void ExtendedAuthenticator::AuthenticateToMount(
- const UserContext& context,
- const ResultCallback& success_callback) {
- TransformKeyIfNeeded(context,
- base::Bind(&ExtendedAuthenticator::DoAuthenticateToMount,
- this,
- success_callback));
-}
-
-void ExtendedAuthenticator::AuthenticateToCheck(
- const UserContext& context,
- const base::Closure& success_callback) {
- TransformKeyIfNeeded(context,
- base::Bind(&ExtendedAuthenticator::DoAuthenticateToCheck,
- this,
- success_callback));
+// static
+scoped_refptr<ExtendedAuthenticator> ExtendedAuthenticator::Create(
+ NewAuthStatusConsumer* consumer) {
+ return make_scoped_refptr(new ExtendedAuthenticatorImpl(consumer));
}
-void ExtendedAuthenticator::CreateMount(
- const std::string& user_id,
- const std::vector<cryptohome::KeyDefinition>& keys,
- const ResultCallback& success_callback) {
- RecordStartMarker("MountEx");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_id);
- cryptohome::Identification id(canonicalized);
- cryptohome::Authorization auth(keys.front());
- cryptohome::MountParameters mount(false);
- for (size_t i = 0; i < keys.size(); i++) {
- mount.create_keys.push_back(keys[i]);
- }
- UserContext context(user_id);
- Key key(keys.front().secret);
- key.SetLabel(keys.front().label);
- context.SetKey(key);
-
- cryptohome::HomedirMethods::GetInstance()->MountEx(
- id,
- auth,
- mount,
- base::Bind(&ExtendedAuthenticator::OnMountComplete,
- this,
- "MountEx",
- context,
- success_callback));
-}
-
-void ExtendedAuthenticator::AddKey(const UserContext& context,
- const cryptohome::KeyDefinition& key,
- bool replace_existing,
- const base::Closure& success_callback) {
- TransformKeyIfNeeded(context,
- base::Bind(&ExtendedAuthenticator::DoAddKey,
- this,
- key,
- replace_existing,
- success_callback));
-}
-
-void ExtendedAuthenticator::UpdateKeyAuthorized(
- const UserContext& context,
- const cryptohome::KeyDefinition& key,
- const std::string& signature,
- const base::Closure& success_callback) {
- TransformKeyIfNeeded(context,
- base::Bind(&ExtendedAuthenticator::DoUpdateKeyAuthorized,
- this,
- key,
- signature,
- success_callback));
-}
-
-void ExtendedAuthenticator::RemoveKey(const UserContext& context,
- const std::string& key_to_remove,
- const base::Closure& success_callback) {
- TransformKeyIfNeeded(context,
- base::Bind(&ExtendedAuthenticator::DoRemoveKey,
- this,
- key_to_remove,
- success_callback));
+// static
+scoped_refptr<ExtendedAuthenticator> ExtendedAuthenticator::Create(
+ AuthStatusConsumer* consumer) {
+ return make_scoped_refptr(new ExtendedAuthenticatorImpl(consumer));
}
-void ExtendedAuthenticator::TransformKeyIfNeeded(
- const UserContext& user_context,
- const ContextCallback& callback) {
- if (user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) {
- callback.Run(user_context);
- return;
- }
-
- if (!salt_obtained_) {
- system_salt_callbacks_.push_back(
- base::Bind(&ExtendedAuthenticator::TransformKeyIfNeeded,
- this,
- user_context,
- callback));
- return;
- }
-
- UserContext transformed_context = user_context;
- transformed_context.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
- system_salt_);
- callback.Run(transformed_context);
+ExtendedAuthenticator::ExtendedAuthenticator() {
}
ExtendedAuthenticator::~ExtendedAuthenticator() {
}
-void ExtendedAuthenticator::OnSaltObtained(const std::string& system_salt) {
- salt_obtained_ = true;
- system_salt_ = system_salt;
- for (std::vector<base::Closure>::const_iterator it =
- system_salt_callbacks_.begin();
- it != system_salt_callbacks_.end();
- ++it) {
- it->Run();
- }
- system_salt_callbacks_.clear();
-}
-
-void ExtendedAuthenticator::DoAuthenticateToMount(
- const ResultCallback& success_callback,
- const UserContext& user_context) {
- RecordStartMarker("MountEx");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
- cryptohome::Identification id(canonicalized);
- const Key* const key = user_context.GetKey();
- cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
- cryptohome::MountParameters mount(false);
-
- cryptohome::HomedirMethods::GetInstance()->MountEx(
- id,
- auth,
- mount,
- base::Bind(&ExtendedAuthenticator::OnMountComplete,
- this,
- "MountEx",
- user_context,
- success_callback));
-}
-
-void ExtendedAuthenticator::DoAuthenticateToCheck(
- const base::Closure& success_callback,
- const UserContext& user_context) {
- RecordStartMarker("CheckKeyEx");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
- cryptohome::Identification id(canonicalized);
- const Key* const key = user_context.GetKey();
- cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
-
- cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
- id,
- auth,
- base::Bind(&ExtendedAuthenticator::OnOperationComplete,
- this,
- "CheckKeyEx",
- user_context,
- success_callback));
-}
-
-void ExtendedAuthenticator::DoAddKey(const cryptohome::KeyDefinition& key,
- bool replace_existing,
- const base::Closure& success_callback,
- const UserContext& user_context) {
- RecordStartMarker("AddKeyEx");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
- cryptohome::Identification id(canonicalized);
- const Key* const auth_key = user_context.GetKey();
- cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
-
- cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
- id,
- auth,
- key,
- replace_existing,
- base::Bind(&ExtendedAuthenticator::OnOperationComplete,
- this,
- "AddKeyEx",
- user_context,
- success_callback));
-}
-
-void ExtendedAuthenticator::DoUpdateKeyAuthorized(
- const cryptohome::KeyDefinition& key,
- const std::string& signature,
- const base::Closure& success_callback,
- const UserContext& user_context) {
- RecordStartMarker("UpdateKeyAuthorized");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
- cryptohome::Identification id(canonicalized);
- const Key* const auth_key = user_context.GetKey();
- cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
-
- cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
- id,
- auth,
- key,
- signature,
- base::Bind(&ExtendedAuthenticator::OnOperationComplete,
- this,
- "UpdateKeyAuthorized",
- user_context,
- success_callback));
-}
-
-void ExtendedAuthenticator::DoRemoveKey(const std::string& key_to_remove,
- const base::Closure& success_callback,
- const UserContext& user_context) {
- RecordStartMarker("RemoveKeyEx");
-
- std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
- cryptohome::Identification id(canonicalized);
- const Key* const auth_key = user_context.GetKey();
- cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
-
- cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
- id,
- auth,
- key_to_remove,
- base::Bind(&ExtendedAuthenticator::OnOperationComplete,
- this,
- "RemoveKeyEx",
- user_context,
- success_callback));
-}
-
-void ExtendedAuthenticator::OnMountComplete(
- const std::string& time_marker,
- const UserContext& user_context,
- const ResultCallback& success_callback,
- bool success,
- cryptohome::MountError return_code,
- const std::string& mount_hash) {
- RecordEndMarker(time_marker);
- UserContext copy = user_context;
- copy.SetUserIDHash(mount_hash);
- if (return_code == cryptohome::MOUNT_ERROR_NONE) {
- if (!success_callback.is_null())
- success_callback.Run(mount_hash);
- if (old_consumer_)
- old_consumer_->OnAuthSuccess(copy);
- return;
- }
- AuthState state = FAILED_MOUNT;
- if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
- return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
- return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
- state = FAILED_TPM;
- }
- if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
- state = NO_MOUNT;
- }
- if (consumer_)
- consumer_->OnAuthenticationFailure(state);
- if (old_consumer_) {
- AuthFailure failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME);
- old_consumer_->OnAuthFailure(failure);
- }
-}
-
-void ExtendedAuthenticator::OnOperationComplete(
- const std::string& time_marker,
- const UserContext& user_context,
- const base::Closure& success_callback,
- bool success,
- cryptohome::MountError return_code) {
- RecordEndMarker(time_marker);
- if (return_code == cryptohome::MOUNT_ERROR_NONE) {
- if (!success_callback.is_null())
- success_callback.Run();
- if (old_consumer_)
- old_consumer_->OnAuthSuccess(user_context);
- return;
- }
-
- LOG(ERROR) << "Supervised user cryptohome error, code: " << return_code;
-
- AuthState state = FAILED_MOUNT;
-
- if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
- return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
- return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
- state = FAILED_TPM;
- }
-
- if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
- state = NO_MOUNT;
-
- if (consumer_)
- consumer_->OnAuthenticationFailure(state);
-
- if (old_consumer_) {
- AuthFailure failure(AuthFailure::UNLOCK_FAILED);
- old_consumer_->OnAuthFailure(failure);
- }
-}
-
} // namespace chromeos
diff --git a/chromeos/login/auth/extended_authenticator.h b/chromeos/login/auth/extended_authenticator.h
index 589989f..d80b209 100644
--- a/chromeos/login/auth/extended_authenticator.h
+++ b/chromeos/login/auth/extended_authenticator.h
@@ -14,15 +14,14 @@
#include "base/memory/scoped_ptr.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
class AuthStatusConsumer;
class UserContext;
-// Interaction with cryptohomed: mount home dirs, create new home dirs, update
-// passwords.
+// An interface to interact with cryptohomed: mount home dirs, create new home
+// dirs, update passwords.
//
// Typical flow:
// AuthenticateToMount() calls cryptohomed to perform offline login,
@@ -47,11 +46,13 @@ class CHROMEOS_EXPORT ExtendedAuthenticator
virtual void OnAuthenticationFailure(AuthState state) = 0;
};
- explicit ExtendedAuthenticator(NewAuthStatusConsumer* consumer);
- explicit ExtendedAuthenticator(AuthStatusConsumer* consumer);
+ static scoped_refptr<ExtendedAuthenticator> Create(
+ NewAuthStatusConsumer* consumer);
+ static scoped_refptr<ExtendedAuthenticator> Create(
+ AuthStatusConsumer* consumer);
// Updates consumer of the class.
- void SetConsumer(AuthStatusConsumer* consumer);
+ virtual void SetConsumer(AuthStatusConsumer* consumer) = 0;
// This call will attempt to mount the home dir for the user, key (and key
// label) in |context|. If the key is of type KEY_TYPE_PASSWORD_PLAIN, it will
@@ -59,101 +60,63 @@ class CHROMEOS_EXPORT ExtendedAuthenticator
// call assumes that the home dir already exist for the user and will return
// an error otherwise. On success, the user ID hash (used as the mount point)
// will be passed to |success_callback|.
- void AuthenticateToMount(const UserContext& context,
- const ResultCallback& success_callback);
+ virtual void AuthenticateToMount(const UserContext& context,
+ const ResultCallback& success_callback) = 0;
// This call will attempt to authenticate the user with the key (and key
// label) in |context|. No further actions are taken after authentication.
- void AuthenticateToCheck(const UserContext& context,
- const base::Closure& success_callback);
+ virtual void AuthenticateToCheck(const UserContext& context,
+ const base::Closure& success_callback) = 0;
// This call will create and mount the home dir for |user_id| with the given
// |keys| if the home dir is missing. If the home dir exists already, a mount
// attempt will be performed using the first key in |keys| for authentication.
// Note that all |keys| should have been transformed from plain text already.
// This method does not alter them.
- void CreateMount(const std::string& user_id,
- const std::vector<cryptohome::KeyDefinition>& keys,
- const ResultCallback& success_callback);
+ virtual void CreateMount(const std::string& user_id,
+ const std::vector<cryptohome::KeyDefinition>& keys,
+ const ResultCallback& success_callback) = 0;
// Attempts to add a new |key| for the user identified/authorized by
// |context|. If a key with the same label already exists, the behavior
// depends on the |replace_existing| flag. If the flag is set, the old key is
// replaced. If the flag is not set, an error occurs. It is not allowed to
// replace the key used for authorization.
- void AddKey(const UserContext& context,
- const cryptohome::KeyDefinition& key,
- bool replace_existing,
- const base::Closure& success_callback);
+ virtual void AddKey(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback) = 0;
// Attempts to perform an authorized update of the key in |context| with the
// new |key|. The update is authorized by providing the |signature| of the
// key. The original key must have the |PRIV_AUTHORIZED_UPDATE| privilege to
// perform this operation. The key labels in |context| and in |key| should be
// the same.
- void UpdateKeyAuthorized(const UserContext& context,
- const cryptohome::KeyDefinition& key,
- const std::string& signature,
- const base::Closure& success_callback);
+ virtual void UpdateKeyAuthorized(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback) = 0;
// Attempts to remove the key labeled |key_to_remove| for the user identified/
// authorized by |context|. It is possible to remove the key used for
// authorization, although it should be done with extreme care.
- void RemoveKey(const UserContext& context,
- const std::string& key_to_remove,
- const base::Closure& success_callback);
+ virtual void RemoveKey(const UserContext& context,
+ const std::string& key_to_remove,
+ const base::Closure& success_callback) = 0;
// Hashes the key in |user_context| with the system salt it its type is
// KEY_TYPE_PASSWORD_PLAIN and passes the resulting UserContext to the
// |callback|.
- void TransformKeyIfNeeded(const UserContext& user_context,
- const ContextCallback& callback);
+ virtual void TransformKeyIfNeeded(const UserContext& user_context,
+ const ContextCallback& callback) = 0;
+
+ protected:
+ ExtendedAuthenticator();
+ virtual ~ExtendedAuthenticator();
private:
friend class base::RefCountedThreadSafe<ExtendedAuthenticator>;
- ~ExtendedAuthenticator();
-
- // Callback for system salt getter.
- void OnSaltObtained(const std::string& system_salt);
-
- // Performs actual operation with fully configured |context|.
- void DoAuthenticateToMount(const ResultCallback& success_callback,
- const UserContext& context);
- void DoAuthenticateToCheck(const base::Closure& success_callback,
- const UserContext& context);
- void DoAddKey(const cryptohome::KeyDefinition& key,
- bool replace_existing,
- const base::Closure& success_callback,
- const UserContext& context);
- void DoUpdateKeyAuthorized(const cryptohome::KeyDefinition& key,
- const std::string& signature,
- const base::Closure& success_callback,
- const UserContext& context);
- void DoRemoveKey(const std::string& key_to_remove,
- const base::Closure& success_callback,
- const UserContext& context);
-
- // Inner operation callbacks.
- void OnMountComplete(const std::string& time_marker,
- const UserContext& context,
- const ResultCallback& success_callback,
- bool success,
- cryptohome::MountError return_code,
- const std::string& mount_hash);
- void OnOperationComplete(const std::string& time_marker,
- const UserContext& context,
- const base::Closure& success_callback,
- bool success,
- cryptohome::MountError return_code);
-
- bool salt_obtained_;
- std::string system_salt_;
- std::vector<base::Closure> system_salt_callbacks_;
-
- NewAuthStatusConsumer* consumer_;
- AuthStatusConsumer* old_consumer_;
-
DISALLOW_COPY_AND_ASSIGN(ExtendedAuthenticator);
};
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc
new file mode 100644
index 0000000..f4c1023
--- /dev/null
+++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -0,0 +1,366 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/login/auth/extended_authenticator_impl.h"
+
+#include "base/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "chromeos/cryptohome/async_method_caller.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/cryptohome/homedir_methods.h"
+#include "chromeos/cryptohome/system_salt_getter.h"
+#include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/login/auth/auth_status_consumer.h"
+#include "chromeos/login/auth/key.h"
+#include "chromeos/login/auth/user_context.h"
+#include "chromeos/login_event_recorder.h"
+#include "crypto/sha2.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+
+void RecordStartMarker(const std::string& marker) {
+ std::string full_marker = "Cryptohome-";
+ full_marker.append(marker);
+ full_marker.append("-Start");
+ chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
+}
+
+void RecordEndMarker(const std::string& marker) {
+ std::string full_marker = "Cryptohome-";
+ full_marker.append(marker);
+ full_marker.append("-End");
+ chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
+}
+
+} // namespace
+
+ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
+ NewAuthStatusConsumer* consumer)
+ : salt_obtained_(false), consumer_(consumer), old_consumer_(NULL) {
+ SystemSaltGetter::Get()->GetSystemSalt(
+ base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained, this));
+}
+
+ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
+ AuthStatusConsumer* consumer)
+ : salt_obtained_(false), consumer_(NULL), old_consumer_(consumer) {
+ SystemSaltGetter::Get()->GetSystemSalt(
+ base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained, this));
+}
+
+void ExtendedAuthenticatorImpl::SetConsumer(AuthStatusConsumer* consumer) {
+ old_consumer_ = consumer;
+}
+
+void ExtendedAuthenticatorImpl::AuthenticateToMount(
+ const UserContext& context,
+ const ResultCallback& success_callback) {
+ TransformKeyIfNeeded(
+ context,
+ base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToMount,
+ this,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::AuthenticateToCheck(
+ const UserContext& context,
+ const base::Closure& success_callback) {
+ TransformKeyIfNeeded(
+ context,
+ base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToCheck,
+ this,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::CreateMount(
+ const std::string& user_id,
+ const std::vector<cryptohome::KeyDefinition>& keys,
+ const ResultCallback& success_callback) {
+ RecordStartMarker("MountEx");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_id);
+ cryptohome::Identification id(canonicalized);
+ cryptohome::Authorization auth(keys.front());
+ cryptohome::MountParameters mount(false);
+ for (size_t i = 0; i < keys.size(); i++) {
+ mount.create_keys.push_back(keys[i]);
+ }
+ UserContext context(user_id);
+ Key key(keys.front().secret);
+ key.SetLabel(keys.front().label);
+ context.SetKey(key);
+
+ cryptohome::HomedirMethods::GetInstance()->MountEx(
+ id,
+ auth,
+ mount,
+ base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete,
+ this,
+ "MountEx",
+ context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::AddKey(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback) {
+ TransformKeyIfNeeded(context,
+ base::Bind(&ExtendedAuthenticatorImpl::DoAddKey,
+ this,
+ key,
+ replace_existing,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::UpdateKeyAuthorized(
+ const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback) {
+ TransformKeyIfNeeded(
+ context,
+ base::Bind(&ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized,
+ this,
+ key,
+ signature,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::RemoveKey(const UserContext& context,
+ const std::string& key_to_remove,
+ const base::Closure& success_callback) {
+ TransformKeyIfNeeded(context,
+ base::Bind(&ExtendedAuthenticatorImpl::DoRemoveKey,
+ this,
+ key_to_remove,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::TransformKeyIfNeeded(
+ const UserContext& user_context,
+ const ContextCallback& callback) {
+ if (user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) {
+ callback.Run(user_context);
+ return;
+ }
+
+ if (!salt_obtained_) {
+ system_salt_callbacks_.push_back(
+ base::Bind(&ExtendedAuthenticatorImpl::TransformKeyIfNeeded,
+ this,
+ user_context,
+ callback));
+ return;
+ }
+
+ UserContext transformed_context = user_context;
+ transformed_context.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
+ system_salt_);
+ callback.Run(transformed_context);
+}
+
+ExtendedAuthenticatorImpl::~ExtendedAuthenticatorImpl() {
+}
+
+void ExtendedAuthenticatorImpl::OnSaltObtained(const std::string& system_salt) {
+ salt_obtained_ = true;
+ system_salt_ = system_salt;
+ for (std::vector<base::Closure>::const_iterator it =
+ system_salt_callbacks_.begin();
+ it != system_salt_callbacks_.end();
+ ++it) {
+ it->Run();
+ }
+ system_salt_callbacks_.clear();
+}
+
+void ExtendedAuthenticatorImpl::DoAuthenticateToMount(
+ const ResultCallback& success_callback,
+ const UserContext& user_context) {
+ RecordStartMarker("MountEx");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
+ cryptohome::Identification id(canonicalized);
+ const Key* const key = user_context.GetKey();
+ cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
+ cryptohome::MountParameters mount(false);
+
+ cryptohome::HomedirMethods::GetInstance()->MountEx(
+ id,
+ auth,
+ mount,
+ base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete,
+ this,
+ "MountEx",
+ user_context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::DoAuthenticateToCheck(
+ const base::Closure& success_callback,
+ const UserContext& user_context) {
+ RecordStartMarker("CheckKeyEx");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
+ cryptohome::Identification id(canonicalized);
+ const Key* const key = user_context.GetKey();
+ cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
+
+ cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
+ id,
+ auth,
+ base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
+ this,
+ "CheckKeyEx",
+ user_context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::DoAddKey(const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback,
+ const UserContext& user_context) {
+ RecordStartMarker("AddKeyEx");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
+ cryptohome::Identification id(canonicalized);
+ const Key* const auth_key = user_context.GetKey();
+ cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
+
+ cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
+ id,
+ auth,
+ key,
+ replace_existing,
+ base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
+ this,
+ "AddKeyEx",
+ user_context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized(
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback,
+ const UserContext& user_context) {
+ RecordStartMarker("UpdateKeyAuthorized");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
+ cryptohome::Identification id(canonicalized);
+ const Key* const auth_key = user_context.GetKey();
+ cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
+
+ cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
+ id,
+ auth,
+ key,
+ signature,
+ base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
+ this,
+ "UpdateKeyAuthorized",
+ user_context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::DoRemoveKey(const std::string& key_to_remove,
+ const base::Closure& success_callback,
+ const UserContext& user_context) {
+ RecordStartMarker("RemoveKeyEx");
+
+ std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
+ cryptohome::Identification id(canonicalized);
+ const Key* const auth_key = user_context.GetKey();
+ cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
+
+ cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
+ id,
+ auth,
+ key_to_remove,
+ base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
+ this,
+ "RemoveKeyEx",
+ user_context,
+ success_callback));
+}
+
+void ExtendedAuthenticatorImpl::OnMountComplete(
+ const std::string& time_marker,
+ const UserContext& user_context,
+ const ResultCallback& success_callback,
+ bool success,
+ cryptohome::MountError return_code,
+ const std::string& mount_hash) {
+ RecordEndMarker(time_marker);
+ UserContext copy = user_context;
+ copy.SetUserIDHash(mount_hash);
+ if (return_code == cryptohome::MOUNT_ERROR_NONE) {
+ if (!success_callback.is_null())
+ success_callback.Run(mount_hash);
+ if (old_consumer_)
+ old_consumer_->OnAuthSuccess(copy);
+ return;
+ }
+ AuthState state = FAILED_MOUNT;
+ if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
+ return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
+ return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
+ state = FAILED_TPM;
+ }
+ if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
+ state = NO_MOUNT;
+ }
+ if (consumer_)
+ consumer_->OnAuthenticationFailure(state);
+ if (old_consumer_) {
+ AuthFailure failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME);
+ old_consumer_->OnAuthFailure(failure);
+ }
+}
+
+void ExtendedAuthenticatorImpl::OnOperationComplete(
+ const std::string& time_marker,
+ const UserContext& user_context,
+ const base::Closure& success_callback,
+ bool success,
+ cryptohome::MountError return_code) {
+ RecordEndMarker(time_marker);
+ if (return_code == cryptohome::MOUNT_ERROR_NONE) {
+ if (!success_callback.is_null())
+ success_callback.Run();
+ if (old_consumer_)
+ old_consumer_->OnAuthSuccess(user_context);
+ return;
+ }
+
+ LOG(ERROR) << "Supervised user cryptohome error, code: " << return_code;
+
+ AuthState state = FAILED_MOUNT;
+
+ if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
+ return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
+ return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
+ state = FAILED_TPM;
+ }
+
+ if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
+ state = NO_MOUNT;
+
+ if (consumer_)
+ consumer_->OnAuthenticationFailure(state);
+
+ if (old_consumer_) {
+ AuthFailure failure(AuthFailure::UNLOCK_FAILED);
+ old_consumer_->OnAuthFailure(failure);
+ }
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/extended_authenticator_impl.h b/chromeos/login/auth/extended_authenticator_impl.h
new file mode 100644
index 0000000..103cbd2
--- /dev/null
+++ b/chromeos/login/auth/extended_authenticator_impl.h
@@ -0,0 +1,103 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_LOGIN_AUTH_EXTENDED_AUTHENTICATOR_IMPL_H_
+#define CHROMEOS_LOGIN_AUTH_EXTENDED_AUTHENTICATOR_IMPL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/login/auth/extended_authenticator.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+class AuthStatusConsumer;
+class UserContext;
+
+// Implements ExtendedAuthenticator.
+class CHROMEOS_EXPORT ExtendedAuthenticatorImpl : public ExtendedAuthenticator {
+ public:
+ explicit ExtendedAuthenticatorImpl(NewAuthStatusConsumer* consumer);
+ explicit ExtendedAuthenticatorImpl(AuthStatusConsumer* consumer);
+
+ // ExtendedAuthenticator:
+ virtual void SetConsumer(AuthStatusConsumer* consumer) override;
+ virtual void AuthenticateToMount(
+ const UserContext& context,
+ const ResultCallback& success_callback) override;
+ virtual void AuthenticateToCheck(
+ const UserContext& context,
+ const base::Closure& success_callback) override;
+ virtual void CreateMount(const std::string& user_id,
+ const std::vector<cryptohome::KeyDefinition>& keys,
+ const ResultCallback& success_callback) override;
+ virtual void AddKey(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback) override;
+ virtual void UpdateKeyAuthorized(
+ const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback) override;
+ virtual void RemoveKey(const UserContext& context,
+ const std::string& key_to_remove,
+ const base::Closure& success_callback) override;
+ virtual void TransformKeyIfNeeded(const UserContext& user_context,
+ const ContextCallback& callback) override;
+
+ private:
+ virtual ~ExtendedAuthenticatorImpl();
+
+ // Callback for system salt getter.
+ void OnSaltObtained(const std::string& system_salt);
+
+ // Performs actual operation with fully configured |context|.
+ void DoAuthenticateToMount(const ResultCallback& success_callback,
+ const UserContext& context);
+ void DoAuthenticateToCheck(const base::Closure& success_callback,
+ const UserContext& context);
+ void DoAddKey(const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback,
+ const UserContext& context);
+ void DoUpdateKeyAuthorized(const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback,
+ const UserContext& context);
+ void DoRemoveKey(const std::string& key_to_remove,
+ const base::Closure& success_callback,
+ const UserContext& context);
+
+ // Inner operation callbacks.
+ void OnMountComplete(const std::string& time_marker,
+ const UserContext& context,
+ const ResultCallback& success_callback,
+ bool success,
+ cryptohome::MountError return_code,
+ const std::string& mount_hash);
+ void OnOperationComplete(const std::string& time_marker,
+ const UserContext& context,
+ const base::Closure& success_callback,
+ bool success,
+ cryptohome::MountError return_code);
+
+ bool salt_obtained_;
+ std::string system_salt_;
+ std::vector<base::Closure> system_salt_callbacks_;
+
+ NewAuthStatusConsumer* consumer_;
+ AuthStatusConsumer* old_consumer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtendedAuthenticatorImpl);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_EXTENDED_AUTHENTICATOR_IMPL_H_
diff --git a/chromeos/login/auth/fake_extended_authenticator.cc b/chromeos/login/auth/fake_extended_authenticator.cc
new file mode 100644
index 0000000..90b569b
--- /dev/null
+++ b/chromeos/login/auth/fake_extended_authenticator.cc
@@ -0,0 +1,113 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/login/auth/fake_extended_authenticator.h"
+
+#include "base/logging.h"
+#include "chromeos/login/auth/auth_status_consumer.h"
+
+namespace chromeos {
+
+FakeExtendedAuthenticator::FakeExtendedAuthenticator(
+ NewAuthStatusConsumer* consumer,
+ const UserContext& expected_user_context)
+ : consumer_(consumer),
+ old_consumer_(NULL),
+ expected_user_context_(expected_user_context) {
+}
+
+FakeExtendedAuthenticator::FakeExtendedAuthenticator(
+ AuthStatusConsumer* consumer,
+ const UserContext& expected_user_context)
+ : consumer_(NULL),
+ old_consumer_(consumer),
+ expected_user_context_(expected_user_context) {
+}
+
+FakeExtendedAuthenticator::~FakeExtendedAuthenticator() {
+}
+
+void FakeExtendedAuthenticator::SetConsumer(AuthStatusConsumer* consumer) {
+ old_consumer_ = consumer;
+}
+
+void FakeExtendedAuthenticator::AuthenticateToMount(
+ const UserContext& context,
+ const ResultCallback& success_callback) {
+ if (expected_user_context_ == context) {
+ UserContext reported_user_context(context);
+ const std::string mount_hash = reported_user_context.GetUserID() + "-hash";
+ reported_user_context.SetUserIDHash(mount_hash);
+ if (!success_callback.is_null())
+ success_callback.Run(mount_hash);
+ OnAuthSuccess(reported_user_context);
+ return;
+ }
+
+ OnAuthFailure(FAILED_MOUNT,
+ AuthFailure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME));
+}
+
+void FakeExtendedAuthenticator::AuthenticateToCheck(
+ const UserContext& context,
+ const base::Closure& success_callback) {
+ if (expected_user_context_ == context) {
+ if (!success_callback.is_null())
+ success_callback.Run();
+ OnAuthSuccess(context);
+ return;
+ }
+
+ OnAuthFailure(FAILED_MOUNT,
+ AuthFailure(AuthFailure::UNLOCK_FAILED));
+}
+
+void FakeExtendedAuthenticator::CreateMount(const std::string& user_id,
+ const std::vector<cryptohome::KeyDefinition>& keys,
+ const ResultCallback& success_callback) {
+ NOTREACHED();
+}
+
+void FakeExtendedAuthenticator::AddKey(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback) {
+ NOTREACHED();
+}
+
+void FakeExtendedAuthenticator::UpdateKeyAuthorized(
+ const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback) {
+ NOTREACHED();
+}
+
+void FakeExtendedAuthenticator::RemoveKey(const UserContext& context,
+ const std::string& key_to_remove,
+ const base::Closure& success_callback) {
+ NOTREACHED();
+}
+
+void FakeExtendedAuthenticator::TransformKeyIfNeeded(
+ const UserContext& user_context,
+ const ContextCallback& callback) {
+ if (!callback.is_null())
+ callback.Run(user_context);
+}
+
+void FakeExtendedAuthenticator::OnAuthSuccess(const UserContext& context) {
+ if (old_consumer_)
+ old_consumer_->OnAuthSuccess(context);
+}
+
+void FakeExtendedAuthenticator::OnAuthFailure(AuthState state,
+ const AuthFailure& error) {
+ if (consumer_)
+ consumer_->OnAuthenticationFailure(state);
+ if (old_consumer_)
+ old_consumer_->OnAuthFailure(error);
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/fake_extended_authenticator.h b/chromeos/login/auth/fake_extended_authenticator.h
new file mode 100644
index 0000000..54b0319f
--- /dev/null
+++ b/chromeos/login/auth/fake_extended_authenticator.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_LOGIN_AUTH_FAKE_EXTENDED_AUTHENTICATOR_H_
+#define CHROMEOS_LOGIN_AUTH_FAKE_EXTENDED_AUTHENTICATOR_H_
+
+#include "base/macros.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/login/auth/extended_authenticator.h"
+#include "chromeos/login/auth/user_context.h"
+
+namespace chromeos {
+
+class AuthFailure;
+
+class CHROMEOS_EXPORT FakeExtendedAuthenticator : public ExtendedAuthenticator {
+ public:
+ FakeExtendedAuthenticator(NewAuthStatusConsumer* consumer,
+ const UserContext& expected_user_context);
+ FakeExtendedAuthenticator(AuthStatusConsumer* consumer,
+ const UserContext& expected_user_context);
+
+ // ExtendedAuthenticator:
+ virtual void SetConsumer(AuthStatusConsumer* consumer) override;
+ virtual void AuthenticateToMount(
+ const UserContext& context,
+ const ResultCallback& success_callback) override;
+ virtual void AuthenticateToCheck(
+ const UserContext& context,
+ const base::Closure& success_callback) override;
+ virtual void CreateMount(const std::string& user_id,
+ const std::vector<cryptohome::KeyDefinition>& keys,
+ const ResultCallback& success_callback) override;
+ virtual void AddKey(const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ bool replace_existing,
+ const base::Closure& success_callback) override;
+ virtual void UpdateKeyAuthorized(
+ const UserContext& context,
+ const cryptohome::KeyDefinition& key,
+ const std::string& signature,
+ const base::Closure& success_callback) override;
+ virtual void RemoveKey(const UserContext& context,
+ const std::string& key_to_remove,
+ const base::Closure& success_callback) override;
+ virtual void TransformKeyIfNeeded(const UserContext& user_context,
+ const ContextCallback& callback) override;
+ private:
+ virtual ~FakeExtendedAuthenticator();
+
+ void OnAuthSuccess(const UserContext& context);
+ void OnAuthFailure(AuthState state, const AuthFailure& error);
+
+ NewAuthStatusConsumer* consumer_;
+ AuthStatusConsumer* old_consumer_;
+
+ UserContext expected_user_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeExtendedAuthenticator);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_FAKE_EXTENDED_AUTHENTICATOR_H_