summaryrefslogtreecommitdiffstats
path: root/chromeos/login
diff options
context:
space:
mode:
authorantrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-09 21:22:51 +0000
committerantrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-09 21:22:51 +0000
commit4c40e06ed86c6512ddaa958fdb649d96c2a69286 (patch)
tree8f4ffe49ea74b0324a7a1846cf97d5d4ae0044da /chromeos/login
parent8854626b2d073c6f2d80a182088121e156e86c5c (diff)
downloadchromium_src-4c40e06ed86c6512ddaa958fdb649d96c2a69286.zip
chromium_src-4c40e06ed86c6512ddaa958fdb649d96c2a69286.tar.gz
chromium_src-4c40e06ed86c6512ddaa958fdb649d96c2a69286.tar.bz2
[Athena] Extract Chrome OS authentication stack
Move Key/User context BUG=387613 TBR=stevenjb@chromium.org TBR=davemoore@chromium.org TBR=darin@chromium.org Review URL: https://codereview.chromium.org/378513005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282126 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/login')
-rw-r--r--chromeos/login/DEPS4
-rw-r--r--chromeos/login/auth/key.cc114
-rw-r--r--chromeos/login/auth/key.h54
-rw-r--r--chromeos/login/auth/key_unittest.cc47
-rw-r--r--chromeos/login/auth/user_context.cc129
-rw-r--r--chromeos/login/auth/user_context.h74
-rw-r--r--chromeos/login/user_names.cc31
-rw-r--r--chromeos/login/user_names.h45
8 files changed, 498 insertions, 0 deletions
diff --git a/chromeos/login/DEPS b/chromeos/login/DEPS
new file mode 100644
index 0000000..85bd5c2
--- /dev/null
+++ b/chromeos/login/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+components/user_manager",
+ "+google_apis",
+]
diff --git a/chromeos/login/auth/key.cc b/chromeos/login/auth/key.cc
new file mode 100644
index 0000000..099659b
--- /dev/null
+++ b/chromeos/login/auth/key.cc
@@ -0,0 +1,114 @@
+// 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/key.h"
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "crypto/sha2.h"
+#include "crypto/symmetric_key.h"
+
+namespace chromeos {
+
+namespace {
+
+// Parameters for the transformation to KEY_TYPE_SALTED_AES256_1234.
+const int kNumIterations = 1234;
+const int kKeySizeInBits = 256;
+
+} // namespace
+
+Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) {
+}
+
+Key::Key(const Key& other)
+ : key_type_(other.key_type_),
+ salt_(other.salt_),
+ secret_(other.secret_),
+ label_(other.label_) {
+}
+
+Key::Key(const std::string& plain_text_password)
+ : key_type_(KEY_TYPE_PASSWORD_PLAIN), secret_(plain_text_password) {
+}
+
+Key::Key(KeyType key_type, const std::string& salt, const std::string& secret)
+ : key_type_(key_type), salt_(salt), secret_(secret) {
+}
+
+Key::~Key() {
+}
+
+bool Key::operator==(const Key& other) const {
+ return other.key_type_ == key_type_ && other.salt_ == salt_ &&
+ other.secret_ == secret_ && other.label_ == label_;
+}
+
+Key::KeyType Key::GetKeyType() const {
+ return key_type_;
+}
+
+const std::string& Key::GetSecret() const {
+ return secret_;
+}
+
+const std::string& Key::GetLabel() const {
+ return label_;
+}
+
+void Key::SetLabel(const std::string& label) {
+ label_ = label;
+}
+
+void Key::ClearSecret() {
+ secret_.clear();
+}
+
+void Key::Transform(KeyType target_key_type, const std::string& salt) {
+ if (key_type_ != KEY_TYPE_PASSWORD_PLAIN) {
+ NOTREACHED();
+ return;
+ }
+
+ switch (target_key_type) {
+ case KEY_TYPE_SALTED_SHA256_TOP_HALF: {
+ // TODO(stevenjb/nkostylev): Handle empty salt gracefully.
+ CHECK(!salt.empty());
+ char hash[crypto::kSHA256Length];
+ crypto::SHA256HashString(salt + secret_, &hash, sizeof(hash));
+
+ // Keep only the first half of the hash for 'weak' hashing so that the
+ // plain text secret cannot be reconstructed even if the hashing is
+ // reversed.
+ secret_ = StringToLowerASCII(base::HexEncode(
+ reinterpret_cast<const void*>(hash), sizeof(hash) / 2));
+ break;
+ }
+ case KEY_TYPE_SALTED_PBKDF2_AES256_1234: {
+ scoped_ptr<crypto::SymmetricKey> key(
+ crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
+ secret_,
+ salt,
+ kNumIterations,
+ kKeySizeInBits));
+ std::string raw_secret;
+ key->GetRawKey(&raw_secret);
+ base::Base64Encode(raw_secret, &secret_);
+ break;
+ }
+ default:
+ // The resulting key will be sent to cryptohomed. It should always be
+ // hashed. If hashing fails, crash instead of sending a plain-text key.
+ CHECK(false);
+ return;
+ }
+
+ key_type_ = target_key_type;
+ salt_ = salt;
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/key.h b/chromeos/login/auth/key.h
new file mode 100644
index 0000000..8aee6dd
--- /dev/null
+++ b/chromeos/login/auth/key.h
@@ -0,0 +1,54 @@
+// 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_KEY_H_
+#define CHROMEOS_LOGIN_AUTH_KEY_H_
+
+#include <string>
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+
+// Key for user authentication. The class supports hashing of plain text
+// passwords to generate keys as well as the use of pre-hashed keys.
+class CHROMEOS_EXPORT Key {
+ public:
+ enum KeyType {
+ // Plain text password.
+ KEY_TYPE_PASSWORD_PLAIN,
+ // SHA256 of salt + password, first half only, lower-case hex encoded.
+ KEY_TYPE_SALTED_SHA256_TOP_HALF,
+ // PBKDF2 with 256 bit AES and 1234 iterations, base64 encoded.
+ KEY_TYPE_SALTED_PBKDF2_AES256_1234,
+ };
+
+ Key();
+ Key(const Key& other);
+ explicit Key(const std::string& plain_text_password);
+ Key(KeyType key_type, const std::string& salt, const std::string& secret);
+ ~Key();
+
+ bool operator==(const Key& other) const;
+
+ KeyType GetKeyType() const;
+ const std::string& GetSecret() const;
+ const std::string& GetLabel() const;
+
+ void SetLabel(const std::string& label);
+
+ void ClearSecret();
+
+ void Transform(KeyType target_key_type, const std::string& salt);
+
+ private:
+ KeyType key_type_;
+ std::string salt_;
+ std::string secret_;
+ std::string label_;
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_KEY_H_
diff --git a/chromeos/login/auth/key_unittest.cc b/chromeos/login/auth/key_unittest.cc
new file mode 100644
index 0000000..76e38cb
--- /dev/null
+++ b/chromeos/login/auth/key_unittest.cc
@@ -0,0 +1,47 @@
+// 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/key.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+const char kPassword[] = "password";
+const char kLabel[] = "label";
+const char kSalt[] =
+ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
+
+} // namespace
+
+TEST(KeyTest, ClearSecret) {
+ Key key(kPassword);
+ key.SetLabel(kLabel);
+ EXPECT_EQ(Key::KEY_TYPE_PASSWORD_PLAIN, key.GetKeyType());
+ EXPECT_EQ(kPassword, key.GetSecret());
+ EXPECT_EQ(kLabel, key.GetLabel());
+
+ key.ClearSecret();
+ EXPECT_EQ(Key::KEY_TYPE_PASSWORD_PLAIN, key.GetKeyType());
+ EXPECT_TRUE(key.GetSecret().empty());
+ EXPECT_EQ(kLabel, key.GetLabel());
+}
+
+TEST(KeyTest, TransformToSaltedSHA256TopHalf) {
+ Key key(kPassword);
+ key.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, kSalt);
+ EXPECT_EQ(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, key.GetKeyType());
+ EXPECT_EQ("5b01941771e47fa408380aa675703f4f", key.GetSecret());
+}
+
+TEST(KeyTest, TransformToSaltedAES2561234) {
+ Key key(kPassword);
+ key.Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, kSalt);
+ EXPECT_EQ(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, key.GetKeyType());
+ EXPECT_EQ("GUkNnvqoULf/cXbZscVUnANmLBB0ovjGZsj1sKzP5BE=", key.GetSecret());
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/user_context.cc b/chromeos/login/auth/user_context.cc
new file mode 100644
index 0000000..78f12bc
--- /dev/null
+++ b/chromeos/login/auth/user_context.cc
@@ -0,0 +1,129 @@
+// 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/user_context.h"
+#include "chromeos/login/user_names.h"
+
+namespace chromeos {
+
+UserContext::UserContext()
+ : is_using_oauth_(true),
+ auth_flow_(AUTH_FLOW_OFFLINE),
+ user_type_(user_manager::USER_TYPE_REGULAR) {
+}
+
+UserContext::UserContext(const UserContext& other)
+ : user_id_(other.user_id_),
+ key_(other.key_),
+ auth_code_(other.auth_code_),
+ user_id_hash_(other.user_id_hash_),
+ is_using_oauth_(other.is_using_oauth_),
+ auth_flow_(other.auth_flow_),
+ user_type_(other.user_type_) {
+}
+
+UserContext::UserContext(const std::string& user_id)
+ : user_id_(login::CanonicalizeUserID(user_id)),
+ is_using_oauth_(true),
+ auth_flow_(AUTH_FLOW_OFFLINE),
+ user_type_(user_manager::USER_TYPE_REGULAR) {
+}
+
+UserContext::UserContext(user_manager::UserType user_type,
+ const std::string& user_id)
+ : is_using_oauth_(true),
+ auth_flow_(AUTH_FLOW_OFFLINE),
+ user_type_(user_type) {
+ if (user_type_ == user_manager::USER_TYPE_REGULAR)
+ user_id_ = login::CanonicalizeUserID(user_id);
+ else
+ user_id_ = user_id;
+}
+
+UserContext::~UserContext() {
+}
+
+bool UserContext::operator==(const UserContext& context) const {
+ return context.user_id_ == user_id_ && context.key_ == key_ &&
+ context.auth_code_ == auth_code_ &&
+ context.user_id_hash_ == user_id_hash_ &&
+ context.is_using_oauth_ == is_using_oauth_ &&
+ context.auth_flow_ == auth_flow_ && context.user_type_ == user_type_;
+}
+
+bool UserContext::operator!=(const UserContext& context) const {
+ return !(*this == context);
+}
+
+const std::string& UserContext::GetUserID() const {
+ return user_id_;
+}
+
+const Key* UserContext::GetKey() const {
+ return &key_;
+}
+
+Key* UserContext::GetKey() {
+ return &key_;
+}
+
+const std::string& UserContext::GetAuthCode() const {
+ return auth_code_;
+}
+
+const std::string& UserContext::GetUserIDHash() const {
+ return user_id_hash_;
+}
+
+bool UserContext::IsUsingOAuth() const {
+ return is_using_oauth_;
+}
+
+UserContext::AuthFlow UserContext::GetAuthFlow() const {
+ return auth_flow_;
+}
+
+user_manager::UserType UserContext::GetUserType() const {
+ return user_type_;
+}
+
+bool UserContext::HasCredentials() const {
+ return (!user_id_.empty() && !key_.GetSecret().empty()) ||
+ !auth_code_.empty();
+}
+
+void UserContext::SetUserID(const std::string& user_id) {
+ user_id_ = login::CanonicalizeUserID(user_id);
+}
+
+void UserContext::SetKey(const Key& key) {
+ key_ = key;
+}
+
+void UserContext::SetAuthCode(const std::string& auth_code) {
+ auth_code_ = auth_code;
+}
+
+void UserContext::SetUserIDHash(const std::string& user_id_hash) {
+ user_id_hash_ = user_id_hash;
+}
+
+void UserContext::SetIsUsingOAuth(bool is_using_oauth) {
+ is_using_oauth_ = is_using_oauth;
+}
+
+void UserContext::SetAuthFlow(AuthFlow auth_flow) {
+ auth_flow_ = auth_flow;
+}
+
+void UserContext::SetUserType(user_manager::UserType user_type) {
+ user_type_ = user_type;
+}
+
+void UserContext::ClearSecrets() {
+ key_.ClearSecret();
+ auth_code_.clear();
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h
new file mode 100644
index 0000000..8382495
--- /dev/null
+++ b/chromeos/login/auth/user_context.h
@@ -0,0 +1,74 @@
+// 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_USER_CONTEXT_H_
+#define CHROMEOS_LOGIN_AUTH_USER_CONTEXT_H_
+
+#include <string>
+
+#include "chromeos/chromeos_export.h"
+#include "chromeos/login/auth/key.h"
+#include "components/user_manager/user_type.h"
+
+namespace chromeos {
+
+// Information that is passed around while authentication is in progress. The
+// credentials may consist of a |user_id_|, |key_| pair or a GAIA |auth_code_|.
+// The |user_id_hash_| is used to locate the user's home directory
+// mount point for the user. It is set when the mount has been completed.
+class CHROMEOS_EXPORT UserContext {
+ public:
+ // The authentication flow used during sign-in.
+ enum AuthFlow {
+ // Online authentication against GAIA. GAIA did not redirect to a SAML IdP.
+ AUTH_FLOW_GAIA_WITHOUT_SAML,
+ // Online authentication against GAIA. GAIA redirected to a SAML IdP.
+ AUTH_FLOW_GAIA_WITH_SAML,
+ // Offline authentication against a cached key.
+ AUTH_FLOW_OFFLINE
+ };
+
+ UserContext();
+ UserContext(const UserContext& other);
+ explicit UserContext(const std::string& user_id);
+ UserContext(user_manager::UserType user_type, const std::string& user_id);
+ ~UserContext();
+
+ bool operator==(const UserContext& context) const;
+ bool operator!=(const UserContext& context) const;
+
+ const std::string& GetUserID() const;
+ const Key* GetKey() const;
+ Key* GetKey();
+ const std::string& GetAuthCode() const;
+ const std::string& GetUserIDHash() const;
+ bool IsUsingOAuth() const;
+ AuthFlow GetAuthFlow() const;
+ user_manager::UserType GetUserType() const;
+
+ bool HasCredentials() const;
+
+ void SetUserID(const std::string& user_id);
+ void SetKey(const Key& key);
+ void SetAuthCode(const std::string& auth_code);
+ void SetUserIDHash(const std::string& user_id_hash);
+ void SetIsUsingOAuth(bool is_using_oauth);
+ void SetAuthFlow(AuthFlow auth_flow);
+ void SetUserType(user_manager::UserType user_type);
+
+ void ClearSecrets();
+
+ private:
+ std::string user_id_;
+ Key key_;
+ std::string auth_code_;
+ std::string user_id_hash_;
+ bool is_using_oauth_;
+ AuthFlow auth_flow_;
+ user_manager::UserType user_type_;
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_USER_CONTEXT_H_
diff --git a/chromeos/login/user_names.cc b/chromeos/login/user_names.cc
new file mode 100644
index 0000000..f8964f9
--- /dev/null
+++ b/chromeos/login/user_names.cc
@@ -0,0 +1,31 @@
+// 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/user_names.h"
+
+#include "google_apis/gaia/gaia_auth_util.h"
+
+namespace chromeos {
+
+namespace login {
+
+const char* kStubUser = "stub-user@example.com";
+
+const char* kSignInUser = "sign-in-user-id";
+
+// Should match cros constant in platform/libchromeos/chromeos/cryptohome.h
+const char* kGuestUserName = "$guest";
+
+const char* kLocallyManagedUserDomain = "locally-managed.localhost";
+
+const char* kRetailModeUserName = "demouser@";
+
+std::string CanonicalizeUserID(const std::string& user_id) {
+ if (user_id == chromeos::login::kGuestUserName)
+ return user_id;
+ return gaia::CanonicalizeEmail(user_id);
+}
+
+} // namespace login
+
+} // namespace chromeos
diff --git a/chromeos/login/user_names.h b/chromeos/login/user_names.h
new file mode 100644
index 0000000..4c296f7
--- /dev/null
+++ b/chromeos/login/user_names.h
@@ -0,0 +1,45 @@
+// 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_USER_NAMES_H_
+#define CHROMEOS_LOGIN_USER_NAMES_H_
+
+#include <string>
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+
+namespace login {
+
+// Username for stub login when not running on ChromeOS.
+CHROMEOS_EXPORT extern const char* kStubUser;
+
+// Username for the login screen. It is only used to identify login screen
+// tries to set default wallpaper. It is not a real user.
+CHROMEOS_EXPORT extern const char* kSignInUser;
+
+// Magic e-mail addresses are bad. They exist here because some code already
+// depends on them and it is hard to figure out what. Any user types added in
+// the future should be identified by a new |UserType|, not a new magic e-mail
+// address.
+// Username for Guest session user.
+CHROMEOS_EXPORT extern const char* kGuestUserName;
+
+// Domain that is used for all locally managed users.
+CHROMEOS_EXPORT extern const char* kLocallyManagedUserDomain;
+
+// The retail mode user has a magic, domainless e-mail address.
+CHROMEOS_EXPORT extern const char* kRetailModeUserName;
+
+// Canonicalizes a GAIA user ID, accounting for the legacy guest mode user ID
+// which does trips up gaia::CanonicalizeEmail() because it does not contain an
+// @ symbol.
+CHROMEOS_EXPORT std::string CanonicalizeUserID(const std::string& user_id);
+
+} // namespace login
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_USER_NAMES_H_