Commit 9b7653d4 authored by Irina Fedorova's avatar Irina Fedorova Committed by Commit Bot

Add StartWeakCheck to InsecureCredentialsManager

This CL adds a simple version of the StartWeakCheck function to the
InsecureCredentialsManager that doesn't use the zxcvbn-cpp library yet.
Checking long passwords is implemented as it will be in the final
version of password weakness check. It also adds the GetWeakCredentials
function to the InsecureCredentialsManager.

Bug: 1119752
Change-Id: I50013c9824701fdccabda7a76644f37c90fa6227
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2398622
Commit-Queue: Irina Fedorova <irfedorova@google.com>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805723}
parent f13b78ef
...@@ -242,6 +242,8 @@ static_library("browser") { ...@@ -242,6 +242,8 @@ static_library("browser") {
"ui/post_save_compromised_helper.h", "ui/post_save_compromised_helper.h",
"ui/saved_passwords_presenter.cc", "ui/saved_passwords_presenter.cc",
"ui/saved_passwords_presenter.h", "ui/saved_passwords_presenter.h",
"ui/weak_check_utility.cc",
"ui/weak_check_utility.h",
"votes_uploader.cc", "votes_uploader.cc",
"votes_uploader.h", "votes_uploader.h",
"well_known_change_password_state.cc", "well_known_change_password_state.cc",
...@@ -635,6 +637,7 @@ source_set("unit_tests") { ...@@ -635,6 +637,7 @@ source_set("unit_tests") {
"ui/insecure_credentials_manager_unittest.cc", "ui/insecure_credentials_manager_unittest.cc",
"ui/post_save_compromised_helper_unittest.cc", "ui/post_save_compromised_helper_unittest.cc",
"ui/saved_passwords_presenter_unittest.cc", "ui/saved_passwords_presenter_unittest.cc",
"ui/weak_check_utility_unittest.cc",
"vote_uploads_test_matchers.h", "vote_uploads_test_matchers.h",
"votes_uploader_unittest.cc", "votes_uploader_unittest.cc",
"well_known_change_password_state_unittest.cc", "well_known_change_password_state_unittest.cc",
......
...@@ -8,13 +8,16 @@ ...@@ -8,13 +8,16 @@
#include <iterator> #include <iterator>
#include <set> #include <set>
#include "base/bind.h"
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/compromised_credentials_table.h" #include "components/password_manager/core/browser/compromised_credentials_table.h"
#include "components/password_manager/core/browser/ui/credential_utils.h" #include "components/password_manager/core/browser/ui/credential_utils.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h" #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
#include "components/password_manager/core/browser/ui/weak_check_utility.h"
#include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_features.h"
namespace password_manager { namespace password_manager {
...@@ -64,12 +67,13 @@ InsecureCredentialTypeFlags ConvertCompromiseType(CompromiseType type) { ...@@ -64,12 +67,13 @@ InsecureCredentialTypeFlags ConvertCompromiseType(CompromiseType type) {
NOTREACHED(); NOTREACHED();
} }
// This function takes two lists of insecure credentials and saved passwords and // This function takes three lists of compromised credentials, weak passwords
// joins them, producing a map that contains CredentialWithPassword as keys and // and saved passwords and joins them, producing a map that contains
// vector<autofill::PasswordForm> as values with InsecureCredentialTypeFlags as // CredentialWithPassword as keys and vector<autofill::PasswordForm> as values
// values. // with InsecureCredentialTypeFlags as values.
CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords( CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords(
const std::vector<CompromisedCredentials>& credentials, const std::vector<CompromisedCredentials>& compromised_credentials,
const base::flat_set<base::string16>& weak_passwords,
SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { SavedPasswordsPresenter::SavedPasswordsView saved_passwords) {
CredentialPasswordsMap credentials_to_forms; CredentialPasswordsMap credentials_to_forms;
...@@ -96,7 +100,7 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords( ...@@ -96,7 +100,7 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords(
// size of 1, however. // size of 1, however.
std::multiset<autofill::PasswordForm, CredentialWithoutPasswordLess> std::multiset<autofill::PasswordForm, CredentialWithoutPasswordLess>
password_forms(saved_passwords.begin(), saved_passwords.end()); password_forms(saved_passwords.begin(), saved_passwords.end());
for (const auto& credential : credentials) { for (const auto& credential : compromised_credentials) {
auto range = password_forms.equal_range(credential); auto range = password_forms.equal_range(credential);
// Make use of a set to only filter out repeated passwords, if any. // Make use of a set to only filter out repeated passwords, if any.
std::for_each( std::for_each(
...@@ -106,8 +110,7 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords( ...@@ -106,8 +110,7 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords(
credentials_to_forms[compromised_credential]; credentials_to_forms[compromised_credential];
// Using |= operator to save in a bit mask both Leaked and Phished. // Using |= operator to save in a bit mask both Leaked and Phished.
credential_to_form.type = credential_to_form.type |=
credential_to_form.type |
ConvertCompromiseType(credential.compromise_type); ConvertCompromiseType(credential.compromise_type);
// Use the latest time. Relevant when the same credential is both // Use the latest time. Relevant when the same credential is both
...@@ -122,19 +125,36 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords( ...@@ -122,19 +125,36 @@ CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords(
}); });
} }
for (const auto& form : saved_passwords) {
if (weak_passwords.contains(form.password_value)) {
CredentialView weak_credential(form);
auto& credential_to_form = credentials_to_forms[weak_credential];
credential_to_form.type |= InsecureCredentialTypeFlags::kWeakCredential;
// This helps not to create a copy of the |form| in case the credential
// has also been compromised. This is important because we don't want to
// delete the form twice in the RemoveCredential.
if (!IsCompromised(credential_to_form.type)) {
credential_to_form.forms.push_back(form);
}
}
}
return credentials_to_forms; return credentials_to_forms;
} }
std::vector<CredentialWithPassword> ExtractCompromisedCredentials( std::vector<CredentialWithPassword> ExtractInsecureCredentials(
const CredentialPasswordsMap& credentials_to_forms) { const CredentialPasswordsMap& credentials_to_forms,
bool (*condition)(const InsecureCredentialTypeFlags&)) {
std::vector<CredentialWithPassword> credentials; std::vector<CredentialWithPassword> credentials;
credentials.reserve(credentials_to_forms.size());
for (const auto& credential_to_forms : credentials_to_forms) { for (const auto& credential_to_forms : credentials_to_forms) {
if (condition(credential_to_forms.second.type)) {
CredentialWithPassword credential(credential_to_forms.first); CredentialWithPassword credential(credential_to_forms.first);
credential.insecure_type = credential_to_forms.second.type; credential.insecure_type = credential_to_forms.second.type;
credential.create_time = credential_to_forms.second.latest_time; credential.create_time = credential_to_forms.second.latest_time;
credentials.push_back(std::move(credential)); credentials.push_back(std::move(credential));
} }
}
return credentials; return credentials;
} }
...@@ -205,6 +225,14 @@ void InsecureCredentialsManager::Init() { ...@@ -205,6 +225,14 @@ void InsecureCredentialsManager::Init() {
compromised_credentials_reader_.Init(); compromised_credentials_reader_.Init();
} }
void InsecureCredentialsManager::StartWeakCheck() {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&BulkWeakCheck, presenter_->GetSavedPasswords()),
base::BindOnce(&InsecureCredentialsManager::OnWeakCheckDone,
weak_ptr_factory_.GetWeakPtr()));
}
void InsecureCredentialsManager::SaveCompromisedCredential( void InsecureCredentialsManager::SaveCompromisedCredential(
const LeakCheckCredential& credential) { const LeakCheckCredential& credential) {
// Iterate over all currently saved credentials and mark those as compromised // Iterate over all currently saved credentials and mark those as compromised
...@@ -265,7 +293,12 @@ bool InsecureCredentialsManager::RemoveCredential( ...@@ -265,7 +293,12 @@ bool InsecureCredentialsManager::RemoveCredential(
std::vector<CredentialWithPassword> std::vector<CredentialWithPassword>
InsecureCredentialsManager::GetCompromisedCredentials() const { InsecureCredentialsManager::GetCompromisedCredentials() const {
return ExtractCompromisedCredentials(credentials_to_forms_); return ExtractInsecureCredentials(credentials_to_forms_, &IsCompromised);
}
std::vector<CredentialWithPassword>
InsecureCredentialsManager::GetWeakCredentials() const {
return ExtractInsecureCredentials(credentials_to_forms_, &IsWeak);
} }
SavedPasswordsPresenter::SavedPasswordsView SavedPasswordsPresenter::SavedPasswordsView
...@@ -285,29 +318,51 @@ void InsecureCredentialsManager::RemoveObserver(Observer* observer) { ...@@ -285,29 +318,51 @@ void InsecureCredentialsManager::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void InsecureCredentialsManager::OnWeakCheckDone(
base::flat_set<base::string16> weak_passwords) {
weak_passwords_ = std::move(weak_passwords);
credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords(
compromised_credentials_, weak_passwords_,
presenter_->GetSavedPasswords());
NotifyWeakCredentialsChanged();
}
// Re-computes the list of compromised credentials with passwords after // Re-computes the list of compromised credentials with passwords after
// obtaining a new list of compromised credentials. // obtaining a new list of compromised credentials.
void InsecureCredentialsManager::OnCompromisedCredentialsChanged( void InsecureCredentialsManager::OnCompromisedCredentialsChanged(
const std::vector<CompromisedCredentials>& compromised_credentials) { const std::vector<CompromisedCredentials>& compromised_credentials) {
compromised_credentials_ = compromised_credentials; compromised_credentials_ = compromised_credentials;
UpdateCachedDataAndNotifyObservers(presenter_->GetSavedPasswords());
credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords(
compromised_credentials_, weak_passwords_,
presenter_->GetSavedPasswords());
NotifyCompromisedCredentialsChanged();
} }
// Re-computes the list of insecure credentials with passwords after obtaining a // Re-computes the list of insecure credentials with passwords after obtaining a
// new list of saved passwords. // new list of saved passwords.
void InsecureCredentialsManager::OnSavedPasswordsChanged( void InsecureCredentialsManager::OnSavedPasswordsChanged(
SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { SavedPasswordsPresenter::SavedPasswordsView saved_passwords) {
UpdateCachedDataAndNotifyObservers(saved_passwords); credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords(
compromised_credentials_, weak_passwords_, saved_passwords);
NotifyCompromisedCredentialsChanged();
NotifyWeakCredentialsChanged();
} }
void InsecureCredentialsManager::UpdateCachedDataAndNotifyObservers( void InsecureCredentialsManager::NotifyCompromisedCredentialsChanged() {
SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { std::vector<CredentialWithPassword> compromised_credentials =
credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords( ExtractInsecureCredentials(credentials_to_forms_, &IsCompromised);
compromised_credentials_, saved_passwords); for (auto& observer : observers_) {
std::vector<CredentialWithPassword> credentials = observer.OnCompromisedCredentialsChanged(compromised_credentials);
ExtractCompromisedCredentials(credentials_to_forms_); }
}
void InsecureCredentialsManager::NotifyWeakCredentialsChanged() {
std::vector<CredentialWithPassword> weak_credentials =
ExtractInsecureCredentials(credentials_to_forms_, &IsWeak);
for (auto& observer : observers_) { for (auto& observer : observers_) {
observer.OnCompromisedCredentialsChanged(credentials); observer.OnWeakCredentialsChanged(weak_credentials);
} }
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "base/containers/flat_set.h"
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
...@@ -37,6 +38,13 @@ enum class InsecureCredentialTypeFlags { ...@@ -37,6 +38,13 @@ enum class InsecureCredentialTypeFlags {
kWeakCredential = 1 << 2, kWeakCredential = 1 << 2,
}; };
constexpr InsecureCredentialTypeFlags operator&(
InsecureCredentialTypeFlags lhs,
InsecureCredentialTypeFlags rhs) {
return static_cast<InsecureCredentialTypeFlags>(static_cast<int>(lhs) &
static_cast<int>(rhs));
}
constexpr InsecureCredentialTypeFlags operator|( constexpr InsecureCredentialTypeFlags operator|(
InsecureCredentialTypeFlags lhs, InsecureCredentialTypeFlags lhs,
InsecureCredentialTypeFlags rhs) { InsecureCredentialTypeFlags rhs) {
...@@ -44,6 +52,26 @@ constexpr InsecureCredentialTypeFlags operator|( ...@@ -44,6 +52,26 @@ constexpr InsecureCredentialTypeFlags operator|(
static_cast<int>(rhs)); static_cast<int>(rhs));
} }
constexpr InsecureCredentialTypeFlags& operator|=(
InsecureCredentialTypeFlags& lhs,
InsecureCredentialTypeFlags rhs) {
lhs = lhs | rhs;
return lhs;
}
// Checks that |flag| contains at least one of compromised types.
constexpr bool IsCompromised(const InsecureCredentialTypeFlags& flag) {
return (flag & (InsecureCredentialTypeFlags::kCredentialLeaked |
InsecureCredentialTypeFlags::kCredentialPhished)) !=
InsecureCredentialTypeFlags::kSecure;
}
// Checks that |flag| contains weak type.
constexpr bool IsWeak(const InsecureCredentialTypeFlags& flag) {
return (flag & InsecureCredentialTypeFlags::kWeakCredential) !=
InsecureCredentialTypeFlags::kSecure;
}
// Simple struct that augments key values of InsecureCredentials and a password. // Simple struct that augments key values of InsecureCredentials and a password.
struct CredentialView { struct CredentialView {
CredentialView(std::string signon_realm, CredentialView(std::string signon_realm,
...@@ -125,6 +153,10 @@ class InsecureCredentialsManager ...@@ -125,6 +153,10 @@ class InsecureCredentialsManager
void Init(); void Init();
// Computes weak credentials in a separate thread and then passes the result
// to OnWeakCheckDone.
void StartWeakCheck();
// Marks all saved credentials which have same username & password as // Marks all saved credentials which have same username & password as
// compromised. // compromised.
void SaveCompromisedCredential(const LeakCheckCredential& credential); void SaveCompromisedCredential(const LeakCheckCredential& credential);
...@@ -141,6 +173,9 @@ class InsecureCredentialsManager ...@@ -141,6 +173,9 @@ class InsecureCredentialsManager
// Returns a vector of currently compromised credentials. // Returns a vector of currently compromised credentials.
std::vector<CredentialWithPassword> GetCompromisedCredentials() const; std::vector<CredentialWithPassword> GetCompromisedCredentials() const;
// Returns a vector of currently weak credentials.
std::vector<CredentialWithPassword> GetWeakCredentials() const;
// Returns password forms which map to provided insecure credential. // Returns password forms which map to provided insecure credential.
// In most of the cases vector will have 1 element only. // In most of the cases vector will have 1 element only.
SavedPasswordsPresenter::SavedPasswordsView GetSavedPasswordsFor( SavedPasswordsPresenter::SavedPasswordsView GetSavedPasswordsFor(
...@@ -154,6 +189,10 @@ class InsecureCredentialsManager ...@@ -154,6 +189,10 @@ class InsecureCredentialsManager
using CredentialPasswordsMap = using CredentialPasswordsMap =
std::map<CredentialView, CredentialMetadata, PasswordCredentialLess>; std::map<CredentialView, CredentialMetadata, PasswordCredentialLess>;
// Updates |weak_passwords| set and notifies observers that weak credentials
// were changed.
void OnWeakCheckDone(base::flat_set<base::string16> weak_passwords);
// CompromisedCredentialsReader::Observer: // CompromisedCredentialsReader::Observer:
void OnCompromisedCredentialsChanged( void OnCompromisedCredentialsChanged(
const std::vector<CompromisedCredentials>& compromised_credentials) const std::vector<CompromisedCredentials>& compromised_credentials)
...@@ -163,9 +202,11 @@ class InsecureCredentialsManager ...@@ -163,9 +202,11 @@ class InsecureCredentialsManager
void OnSavedPasswordsChanged( void OnSavedPasswordsChanged(
SavedPasswordsPresenter::SavedPasswordsView passwords) override; SavedPasswordsPresenter::SavedPasswordsView passwords) override;
// Function to update |credentials_to_forms_| and notify observers. // Notifies observers when compromised credentials have changed.
void UpdateCachedDataAndNotifyObservers( void NotifyCompromisedCredentialsChanged();
SavedPasswordsPresenter::SavedPasswordsView saved_passwords);
// Notifies observers when weak credentials have changed.
void NotifyWeakCredentialsChanged();
// Returns the `profile_store_` or `account_store_` if `form` is stored in the // Returns the `profile_store_` or `account_store_` if `form` is stored in the
// profile store of the account store accordingly. // profile store of the account store accordingly.
...@@ -186,6 +227,9 @@ class InsecureCredentialsManager ...@@ -186,6 +227,9 @@ class InsecureCredentialsManager
// Cache of the most recently obtained compromised credentials. // Cache of the most recently obtained compromised credentials.
std::vector<CompromisedCredentials> compromised_credentials_; std::vector<CompromisedCredentials> compromised_credentials_;
// Cache of the most recently obtained weak passwords.
base::flat_set<base::string16> weak_passwords_;
// A map that matches CredentialView to corresponding PasswordForms, latest // A map that matches CredentialView to corresponding PasswordForms, latest
// create_type and combined insecure type. // create_type and combined insecure type.
CredentialPasswordsMap credentials_to_forms_; CredentialPasswordsMap credentials_to_forms_;
...@@ -201,6 +245,8 @@ class InsecureCredentialsManager ...@@ -201,6 +245,8 @@ class InsecureCredentialsManager
observed_saved_password_presenter_{this}; observed_saved_password_presenter_{this};
base::ObserverList<Observer, /*check_empty=*/true> observers_; base::ObserverList<Observer, /*check_empty=*/true> observers_;
base::WeakPtrFactory<InsecureCredentialsManager> weak_ptr_factory_{this};
}; };
} // namespace password_manager } // namespace password_manager
......
...@@ -29,6 +29,11 @@ constexpr char kPassword1[] = "f00b4r"; ...@@ -29,6 +29,11 @@ constexpr char kPassword1[] = "f00b4r";
constexpr char kPassword2[] = "s3cr3t"; constexpr char kPassword2[] = "s3cr3t";
constexpr char kPassword3[] = "484her"; constexpr char kPassword3[] = "484her";
constexpr char kWeakPassword1[] = "123456";
constexpr char kWeakPassword2[] = "654321";
constexpr char kStrongPassword1[] = "qjdGd6mGdSLnfp8sfsnF5sndslDdnn%ndkfsn8vdv";
constexpr char kStrongPassword2[] = "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
using autofill::PasswordForm; using autofill::PasswordForm;
using ::testing::ElementsAre; using ::testing::ElementsAre;
using ::testing::ElementsAreArray; using ::testing::ElementsAreArray;
...@@ -84,11 +89,11 @@ CredentialWithPassword MakeCompromisedCredential( ...@@ -84,11 +89,11 @@ CredentialWithPassword MakeCompromisedCredential(
return credential_with_password; return credential_with_password;
} }
class CompromisedCredentialsManagerTest : public ::testing::Test { class InsecureCredentialsManagerTest : public ::testing::Test {
protected: protected:
CompromisedCredentialsManagerTest() { store_->Init(/*prefs=*/nullptr); } InsecureCredentialsManagerTest() { store_->Init(/*prefs=*/nullptr); }
~CompromisedCredentialsManagerTest() override { ~InsecureCredentialsManagerTest() override {
store_->ShutdownOnUIThread(); store_->ShutdownOnUIThread();
task_env_.RunUntilIdle(); task_env_.RunUntilIdle();
} }
...@@ -99,8 +104,8 @@ class CompromisedCredentialsManagerTest : public ::testing::Test { ...@@ -99,8 +104,8 @@ class CompromisedCredentialsManagerTest : public ::testing::Test {
void RunUntilIdle() { task_env_.RunUntilIdle(); } void RunUntilIdle() { task_env_.RunUntilIdle(); }
private: private:
base::test::SingleThreadTaskEnvironment task_env_{ base::test::TaskEnvironment task_env_{
base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME}; base::test::TaskEnvironment::TimeSource::MOCK_TIME};
scoped_refptr<TestPasswordStore> store_ = scoped_refptr<TestPasswordStore> store_ =
base::MakeRefCounted<TestPasswordStore>(); base::MakeRefCounted<TestPasswordStore>();
SavedPasswordsPresenter presenter_{store_}; SavedPasswordsPresenter presenter_{store_};
...@@ -127,7 +132,7 @@ std::ostream& operator<<(std::ostream& out, ...@@ -127,7 +132,7 @@ std::ostream& operator<<(std::ostream& out,
} }
// Tests whether adding and removing an observer works as expected. // Tests whether adding and removing an observer works as expected.
TEST_F(CompromisedCredentialsManagerTest, TEST_F(InsecureCredentialsManagerTest,
NotifyObserversAboutCompromisedCredentialChanges) { NotifyObserversAboutCompromisedCredentialChanges) {
std::vector<CompromisedCredentials> credentials = { std::vector<CompromisedCredentials> credentials = {
MakeCompromised(kExampleCom, kUsername1)}; MakeCompromised(kExampleCom, kUsername1)};
...@@ -172,7 +177,7 @@ TEST_F(CompromisedCredentialsManagerTest, ...@@ -172,7 +177,7 @@ TEST_F(CompromisedCredentialsManagerTest,
// Tests removing a compromised credentials by compromise type triggers an // Tests removing a compromised credentials by compromise type triggers an
// observer works as expected. // observer works as expected.
TEST_F(CompromisedCredentialsManagerTest, TEST_F(InsecureCredentialsManagerTest,
NotifyObserversAboutRemovingCompromisedCredentialsByCompromisedType) { NotifyObserversAboutRemovingCompromisedCredentialsByCompromisedType) {
CompromisedCredentials phished_credentials = CompromisedCredentials phished_credentials =
MakeCompromised(kExampleCom, kUsername1, CompromiseType::kPhished); MakeCompromised(kExampleCom, kUsername1, CompromiseType::kPhished);
...@@ -206,7 +211,7 @@ TEST_F(CompromisedCredentialsManagerTest, ...@@ -206,7 +211,7 @@ TEST_F(CompromisedCredentialsManagerTest,
} }
// Tests whether adding and removing an observer works as expected. // Tests whether adding and removing an observer works as expected.
TEST_F(CompromisedCredentialsManagerTest, TEST_F(InsecureCredentialsManagerTest,
NotifyObserversAboutSavedPasswordsChanges) { NotifyObserversAboutSavedPasswordsChanges) {
StrictMockInsecureCredentialsManagerObserver observer; StrictMockInsecureCredentialsManagerObserver observer;
provider().AddObserver(&observer); provider().AddObserver(&observer);
...@@ -239,7 +244,7 @@ TEST_F(CompromisedCredentialsManagerTest, ...@@ -239,7 +244,7 @@ TEST_F(CompromisedCredentialsManagerTest,
// Tests that the provider is able to join a single password with a compromised // Tests that the provider is able to join a single password with a compromised
// credential. // credential.
TEST_F(CompromisedCredentialsManagerTest, JoinSingleCredentials) { TEST_F(InsecureCredentialsManagerTest, JoinSingleCredentials) {
PasswordForm password = PasswordForm password =
MakeSavedPassword(kExampleCom, kUsername1, kPassword1); MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
...@@ -256,7 +261,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinSingleCredentials) { ...@@ -256,7 +261,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinSingleCredentials) {
// Tests that the provider is able to join a password with a credential that was // Tests that the provider is able to join a password with a credential that was
// compromised in multiple ways. // compromised in multiple ways.
TEST_F(CompromisedCredentialsManagerTest, JoinPhishedAndLeaked) { TEST_F(InsecureCredentialsManagerTest, JoinPhishedAndLeaked) {
PasswordForm password = PasswordForm password =
MakeSavedPassword(kExampleCom, kUsername1, kPassword1); MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
CompromisedCredentials leaked = CompromisedCredentials leaked =
...@@ -279,7 +284,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinPhishedAndLeaked) { ...@@ -279,7 +284,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinPhishedAndLeaked) {
// Tests that the provider reacts whenever the saved passwords or the // Tests that the provider reacts whenever the saved passwords or the
// compromised credentials change. // compromised credentials change.
TEST_F(CompromisedCredentialsManagerTest, ReactToChangesInBothTables) { TEST_F(InsecureCredentialsManagerTest, ReactToChangesInBothTables) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1), MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
...@@ -320,7 +325,7 @@ TEST_F(CompromisedCredentialsManagerTest, ReactToChangesInBothTables) { ...@@ -320,7 +325,7 @@ TEST_F(CompromisedCredentialsManagerTest, ReactToChangesInBothTables) {
// Tests that the provider is able to join multiple passwords with compromised // Tests that the provider is able to join multiple passwords with compromised
// credentials. // credentials.
TEST_F(CompromisedCredentialsManagerTest, JoinMultipleCredentials) { TEST_F(InsecureCredentialsManagerTest, JoinMultipleCredentials) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1), MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
...@@ -346,7 +351,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinMultipleCredentials) { ...@@ -346,7 +351,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinMultipleCredentials) {
// Tests that joining a compromised credential with saved passwords with a // Tests that joining a compromised credential with saved passwords with a
// different username results in an empty list. // different username results in an empty list.
TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentUsername) { TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentUsername) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername2, kPassword1), MakeSavedPassword(kExampleCom, kUsername2, kPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
...@@ -363,7 +368,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentUsername) { ...@@ -363,7 +368,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentUsername) {
// Tests that joining a compromised credential with saved passwords with a // Tests that joining a compromised credential with saved passwords with a
// matching username but different signon_realm results in an empty list. // matching username but different signon_realm results in an empty list.
TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentSignonRealm) { TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentSignonRealm) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleOrg, kUsername1, kPassword1), MakeSavedPassword(kExampleOrg, kUsername1, kPassword1),
MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)}; MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)};
...@@ -381,7 +386,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentSignonRealm) { ...@@ -381,7 +386,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentSignonRealm) {
// Tests that joining a compromised credential with multiple saved passwords for // Tests that joining a compromised credential with multiple saved passwords for
// the same signon_realm and username combination results in multiple entries // the same signon_realm and username combination results in multiple entries
// when the passwords are distinct. // when the passwords are distinct.
TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleDistinctPasswords) { TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleDistinctPasswords) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
MakeSavedPassword(kExampleCom, kUsername1, kPassword2, "element_2")}; MakeSavedPassword(kExampleCom, kUsername1, kPassword2, "element_2")};
...@@ -405,7 +410,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleDistinctPasswords) { ...@@ -405,7 +410,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleDistinctPasswords) {
// Tests that joining a compromised credential with multiple saved passwords for // Tests that joining a compromised credential with multiple saved passwords for
// the same signon_realm and username combination results in a single entry // the same signon_realm and username combination results in a single entry
// when the passwords are the same. // when the passwords are the same.
TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) { TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) {
CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
...@@ -424,7 +429,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) { ...@@ -424,7 +429,7 @@ TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) {
// Tests that verifies mapping compromised credentials to passwords works // Tests that verifies mapping compromised credentials to passwords works
// correctly. // correctly.
TEST_F(CompromisedCredentialsManagerTest, MapCompromisedPasswordsToPasswords) { TEST_F(InsecureCredentialsManagerTest, MapCompromisedPasswordsToPasswords) {
std::vector<PasswordForm> passwords = { std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2"), MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2"),
...@@ -456,9 +461,157 @@ TEST_F(CompromisedCredentialsManagerTest, MapCompromisedPasswordsToPasswords) { ...@@ -456,9 +461,157 @@ TEST_F(CompromisedCredentialsManagerTest, MapCompromisedPasswordsToPasswords) {
ElementsAreArray(store().stored_passwords().at(kExampleOrg))); ElementsAreArray(store().stored_passwords().at(kExampleOrg)));
} }
TEST_F(InsecureCredentialsManagerTest, WeakCredentialsNotFound) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kStrongPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword2)};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty());
}
TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
std::vector<CredentialWithPassword> weak_credentials =
provider().GetWeakCredentials();
ASSERT_EQ(weak_credentials.size(), 1u);
EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
}
// Tests that credentials with the same signon_realm and username, but different
// passwords will be both returned by GetWeakCredentials().
TEST_F(InsecureCredentialsManagerTest,
FindBothWeakCredentialsWithDifferentPasswords) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword2, "element_2")};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
std::vector<CredentialWithPassword> weak_credentials =
provider().GetWeakCredentials();
ASSERT_EQ(weak_credentials.size(), 2u);
EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
EXPECT_TRUE(IsWeak(weak_credentials[1].insecure_type));
}
// Tests that credentials with the same signon_realm, username and passwords
// will be joind and GetWeakCredentials() will return one credential.
TEST_F(InsecureCredentialsManagerTest,
JoinWeakCredentialsWithTheSamePasswords) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_2")};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
std::vector<CredentialWithPassword> weak_credentials =
provider().GetWeakCredentials();
ASSERT_EQ(weak_credentials.size(), 1u);
EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
}
TEST_F(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
std::vector<CompromisedCredentials> compromised_credentials = {
MakeCompromised(kExampleCom, kUsername1),
MakeCompromised(kExampleCom, kUsername2)};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
store().AddCompromisedCredentials(compromised_credentials[0]);
store().AddCompromisedCredentials(compromised_credentials[1]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
std::vector<CredentialWithPassword> returned_weak_credentials =
provider().GetWeakCredentials();
std::vector<CredentialWithPassword> returned_compromised_credentials =
provider().GetCompromisedCredentials();
ASSERT_EQ(returned_weak_credentials.size(), 1u);
EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
kWeakPassword1);
EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
ASSERT_EQ(returned_compromised_credentials.size(), 2u);
EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type));
EXPECT_TRUE(IsCompromised(returned_compromised_credentials[1].insecure_type));
}
// Checks that for a credential that is both weak and compromised,
// getWeakCredentials and GetCompromisedCredentials will return this credential
// in one instance.
TEST_F(InsecureCredentialsManagerTest, SingleCredentialIsWeakAndCompromised) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1)};
std::vector<CompromisedCredentials> compromised_credentials = {
MakeCompromised(kExampleCom, kUsername1)};
store().AddLogin(passwords[0]);
store().AddCompromisedCredentials(compromised_credentials[0]);
RunUntilIdle();
provider().StartWeakCheck();
RunUntilIdle();
std::vector<CredentialWithPassword> returned_weak_credentials =
provider().GetWeakCredentials();
std::vector<CredentialWithPassword> returned_compromised_credentials =
provider().GetCompromisedCredentials();
// Since the credential is weak and compromised, the |insecure_type| should be
// weak and compromised for elements from |returned_weak_credentials| and
// |returned_compromised_credentials|.
ASSERT_EQ(returned_weak_credentials.size(), 1u);
EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
kWeakPassword1);
EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
EXPECT_TRUE(IsCompromised(returned_weak_credentials[0].insecure_type));
ASSERT_EQ(returned_compromised_credentials.size(), 1u);
EXPECT_TRUE(IsWeak(returned_compromised_credentials[0].insecure_type));
EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type));
}
// Test verifies that saving LeakCheckCredential via provider adds expected // Test verifies that saving LeakCheckCredential via provider adds expected
// compromised credential. // compromised credential.
TEST_F(CompromisedCredentialsManagerTest, SaveCompromisedPassword) { TEST_F(InsecureCredentialsManagerTest, SaveCompromisedPassword) {
PasswordForm password_form = PasswordForm password_form =
MakeSavedPassword(kExampleCom, kUsername1, kPassword1); MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
LeakCheckCredential credential = MakeLeakCredential(kUsername1, kPassword1); LeakCheckCredential credential = MakeLeakCredential(kUsername1, kPassword1);
...@@ -480,7 +633,7 @@ TEST_F(CompromisedCredentialsManagerTest, SaveCompromisedPassword) { ...@@ -480,7 +633,7 @@ TEST_F(CompromisedCredentialsManagerTest, SaveCompromisedPassword) {
// Test verifies that editing Compromised Credential via provider change the // Test verifies that editing Compromised Credential via provider change the
// original password form. // original password form.
TEST_F(CompromisedCredentialsManagerTest, UpdateCompromisedPassword) { TEST_F(InsecureCredentialsManagerTest, UpdateCompromisedPassword) {
PasswordForm password_form = PasswordForm password_form =
MakeSavedPassword(kExampleCom, kUsername1, kPassword1); MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
...@@ -499,7 +652,7 @@ TEST_F(CompromisedCredentialsManagerTest, UpdateCompromisedPassword) { ...@@ -499,7 +652,7 @@ TEST_F(CompromisedCredentialsManagerTest, UpdateCompromisedPassword) {
EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected)); EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected));
} }
TEST_F(CompromisedCredentialsManagerTest, RemoveCompromisedCredential) { TEST_F(InsecureCredentialsManagerTest, RemoveCompromisedCredential) {
CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1);
PasswordForm password = PasswordForm password =
MakeSavedPassword(kExampleCom, kUsername1, kPassword1); MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
...@@ -520,14 +673,14 @@ TEST_F(CompromisedCredentialsManagerTest, RemoveCompromisedCredential) { ...@@ -520,14 +673,14 @@ TEST_F(CompromisedCredentialsManagerTest, RemoveCompromisedCredential) {
} }
namespace { namespace {
class CompromisedCredentialsManagerWithTwoStoresTest : public ::testing::Test { class InsecureCredentialsManagerWithTwoStoresTest : public ::testing::Test {
protected: protected:
CompromisedCredentialsManagerWithTwoStoresTest() { InsecureCredentialsManagerWithTwoStoresTest() {
profile_store_->Init(/*prefs=*/nullptr); profile_store_->Init(/*prefs=*/nullptr);
account_store_->Init(/*prefs=*/nullptr); account_store_->Init(/*prefs=*/nullptr);
} }
~CompromisedCredentialsManagerWithTwoStoresTest() override { ~InsecureCredentialsManagerWithTwoStoresTest() override {
account_store_->ShutdownOnUIThread(); account_store_->ShutdownOnUIThread();
profile_store_->ShutdownOnUIThread(); profile_store_->ShutdownOnUIThread();
task_env_.RunUntilIdle(); task_env_.RunUntilIdle();
...@@ -553,7 +706,7 @@ class CompromisedCredentialsManagerWithTwoStoresTest : public ::testing::Test { ...@@ -553,7 +706,7 @@ class CompromisedCredentialsManagerWithTwoStoresTest : public ::testing::Test {
// Tests that verifies mapping compromised credentials to passwords works // Tests that verifies mapping compromised credentials to passwords works
// correctly. // correctly.
TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
MapCompromisedPasswordsToPasswords) { MapCompromisedPasswordsToPasswords) {
// Add credentials for both `kExampleCom` and `kExampleOrg` in both stores // Add credentials for both `kExampleCom` and `kExampleOrg` in both stores
// with the same username and difference passwords. For `kUsername1`, the // with the same username and difference passwords. For `kUsername1`, the
...@@ -607,8 +760,7 @@ TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, ...@@ -607,8 +760,7 @@ TEST_F(CompromisedCredentialsManagerWithTwoStoresTest,
// Test verifies that saving LeakCheckCredential via provider adds expected // Test verifies that saving LeakCheckCredential via provider adds expected
// compromised credential to the correct store. // compromised credential to the correct store.
TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, TEST_F(InsecureCredentialsManagerWithTwoStoresTest, SaveCompromisedPassword) {
SaveCompromisedPassword) {
ASSERT_TRUE(profile_store().compromised_credentials().empty()); ASSERT_TRUE(profile_store().compromised_credentials().empty());
ASSERT_TRUE(account_store().compromised_credentials().empty()); ASSERT_TRUE(account_store().compromised_credentials().empty());
// Add `kUsername1`,`kPassword1` to both stores. // Add `kUsername1`,`kPassword1` to both stores.
...@@ -642,7 +794,7 @@ TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, ...@@ -642,7 +794,7 @@ TEST_F(CompromisedCredentialsManagerWithTwoStoresTest,
EXPECT_EQ(2U, account_store().compromised_credentials().size()); EXPECT_EQ(2U, account_store().compromised_credentials().size());
} }
TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
RemoveCompromisedCredential) { RemoveCompromisedCredential) {
// Add `kUsername1`,`kPassword1` to both stores. // Add `kUsername1`,`kPassword1` to both stores.
profile_store().AddLogin( profile_store().AddLogin(
......
// Copyright 2020 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 "components/password_manager/core/browser/ui/weak_check_utility.h"
namespace password_manager {
namespace {
// Passwords longer than this constant should not be checked for weakness using
// the zxcvbn-cpp library. This is because the runtime grows extremely, starting
// at a password length of 40.
// See https://github.com/dropbox/zxcvbn#runtime-latency
// Needs to stay in sync with google3 constant: http://shortn/_1ufIF61G4X
constexpr int kZxcvbnLengthCap = 40;
// If the password has a score of 2 or less, this password should be marked as
// weak. The lower the password score, the weaker it is.
constexpr int kHighSeverityScore = 0;
constexpr int kLowSeverityScore = 2;
constexpr int kStrongPasswordScore = 4;
// Very rough, extremely simplified strength check that only makes sense for
// long passwords.
int SimpleLongPasswordStrengthEstimate(const base::string16& password) {
base::flat_set<base::char16> chars;
for (auto character : password) {
chars.insert(character);
if (chars.size() > 4) {
return kStrongPasswordScore;
}
}
return kHighSeverityScore;
}
// Returns the |password| score.
int PasswordWeakCheck(const base::string16& password) {
// zxcvbn's computation time explodes for long passwords, so don't use it for
// those.
if (password.size() > kZxcvbnLengthCap) {
return SimpleLongPasswordStrengthEstimate(password);
}
// TODO(crbug.com/1119752): Compute result by zxcvbn-cpp.
return kHighSeverityScore;
}
} // namespace
base::flat_set<base::string16> BulkWeakCheck(
SavedPasswordsPresenter::SavedPasswordsView saved_passwords) {
std::vector<base::string16> weak_passwords;
for (const auto& password : saved_passwords) {
if (PasswordWeakCheck(password.password_value) <= kLowSeverityScore) {
weak_passwords.push_back(password.password_value);
}
}
return base::flat_set<base::string16>(std::move(weak_passwords));
}
} // namespace password_manager
// Copyright 2020 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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_
#include "base/containers/flat_set.h"
#include "base/strings/string16.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
namespace password_manager {
// Checks each password for weakness.
base::flat_set<base::string16> BulkWeakCheck(
SavedPasswordsPresenter::SavedPasswordsView passwords);
} // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_
// Copyright 2020 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 "components/password_manager/core/browser/ui/weak_check_utility.h"
#include <vector>
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/password_form.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace password_manager {
namespace {
constexpr char kUsername1[] = "alice";
constexpr char kUsername2[] = "bob";
constexpr char kWeakShortPassword[] = "123456";
constexpr char kWeakLongPassword[] =
"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
constexpr char kStrongLongPassword[] =
"pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
using autofill::PasswordForm;
using ::testing::ElementsAre;
PasswordForm MakeSavedPassword(base::StringPiece username,
base::StringPiece password) {
PasswordForm form;
form.signon_realm = "https://example.com";
form.username_value = base::ASCIIToUTF16(username);
form.password_value = base::ASCIIToUTF16(password);
return form;
}
} // namespace
TEST(WeakCheckUtilityTest, WeakPasswordsNotFound) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kUsername1, kStrongLongPassword)};
EXPECT_THAT(BulkWeakCheck(passwords), testing::IsEmpty());
}
TEST(WeakCheckUtilityTest, DetectedShortAndLongWeakPasswords) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kUsername1, kStrongLongPassword),
MakeSavedPassword(kUsername1, kWeakShortPassword),
MakeSavedPassword(kUsername2, kWeakLongPassword)};
base::flat_set<base::string16> weak_passwords = BulkWeakCheck(passwords);
EXPECT_THAT(weak_passwords,
ElementsAre(base::ASCIIToUTF16(kWeakShortPassword),
base::ASCIIToUTF16(kWeakLongPassword)));
}
TEST(WeakCheckUtilityTest, WeakPasswordsSetContainsNoCopies) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kUsername1, kWeakShortPassword),
MakeSavedPassword(kUsername2, kWeakShortPassword)};
base::flat_set<base::string16> weak_passwords = BulkWeakCheck(passwords);
EXPECT_THAT(weak_passwords,
ElementsAre(base::ASCIIToUTF16(kWeakShortPassword)));
}
} // namespace password_manager
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment