Commit 16c49b51 authored by Viktor Semeniuk's avatar Viktor Semeniuk Committed by Chromium LUCI CQ

Retrieving compromised credentials

This change adds an API to retrieve the insecure credentials information
for a specific password form primary key. Follow up patches will use
this API to sync such information across devices.

Bug: 1137775
Change-Id: I1c29809d53abdb0c501c00904dc506963b69beb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2592996
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: default avatarMohamed Amir Yosef <mamir@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842499}
parent b19a07b3
......@@ -173,6 +173,23 @@ std::vector<CompromisedCredentials> InsecureCredentialsTable::GetRows(
return StatementToCompromisedCredentials(&s);
}
std::vector<CompromisedCredentials> InsecureCredentialsTable::GetRows(
FormPrimaryKey parent_key) const {
DCHECK(db_);
DCHECK(db_->DoesTableExist(kTableName));
sql::Statement s(db_->GetCachedStatement(
SQL_FROM_HERE,
base::StringPrintf("SELECT signon_realm, username_value, "
"insecurity_type, create_time, is_muted FROM %s "
"INNER JOIN logins ON parent_id = logins.id "
"WHERE parent_id = ? ",
kTableName)
.c_str()));
s.BindInt(0, *parent_key);
return StatementToCompromisedCredentials(&s);
}
bool InsecureCredentialsTable::RemoveRowsByUrlAndTime(
const base::RepeatingCallback<bool(const GURL&)>& url_filter,
base::Time remove_begin,
......
......@@ -10,6 +10,7 @@
#include "base/time/time.h"
#include "base/types/strong_alias.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_store_sync.h"
#include "url/gurl.h"
namespace sql {
......@@ -103,6 +104,9 @@ class InsecureCredentialsTable {
std::vector<CompromisedCredentials> GetRows(
const std::string& signon_realm) const;
// Gets all the rows in the database for |parent_key|.
std::vector<CompromisedCredentials> GetRows(FormPrimaryKey parent_key) const;
// Removes all compromised credentials created between |remove_begin|
// inclusive and |remove_end| exclusive. If |url_filter| is not null, only
// compromised credentials for matching signon_realms are removed. Returns
......
......@@ -35,6 +35,7 @@ constexpr char kUsername3[] = "user3";
using testing::ElementsAre;
using testing::IsEmpty;
using testing::SizeIs;
using testing::UnorderedElementsAre;
PasswordForm TestForm() {
PasswordForm form;
......@@ -353,5 +354,30 @@ TEST_F(InsecureCredentialsTableTest, ReportMetricsAfterBulkCheck) {
"PasswordManager.CompromisedCredentials.CountLeakedAfterBulkCheck", 2, 1);
}
TEST_F(InsecureCredentialsTableTest, GetAllRowsWithId) {
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
CompromisedCredentials compromised_credentials1 = test_data();
CompromisedCredentials compromised_credentials2 = test_data();
compromised_credentials2.compromise_type = CompromiseType::kReused;
EXPECT_TRUE(db()->AddRow(compromised_credentials1));
EXPECT_TRUE(db()->AddRow(compromised_credentials2));
EXPECT_THAT(
db()->GetRows(FormPrimaryKey(1)),
UnorderedElementsAre(compromised_credentials1, compromised_credentials2));
test_form().username_value = base::ASCIIToUTF16(kUsername2);
test_data().username = test_form().username_value;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
EXPECT_THAT(db()->GetRows(FormPrimaryKey(2)), IsEmpty());
compromised_credentials1 = test_data();
EXPECT_TRUE(db()->AddRow(compromised_credentials1));
EXPECT_THAT(db()->GetRows(FormPrimaryKey(2)),
UnorderedElementsAre(compromised_credentials1));
}
} // namespace
} // namespace password_manager
......@@ -1665,6 +1665,12 @@ FormRetrievalResult LoginDatabase::GetAllLogins(
return StatementToForms(&s, nullptr, key_to_form_map);
}
std::vector<CompromisedCredentials> LoginDatabase::GetCompromisedCredentials(
FormPrimaryKey parent_key) {
TRACE_EVENT0("passwords", "LoginDatabase::GetCompromisedCredentials");
return insecure_credentials_table_.GetRows(parent_key);
}
bool LoginDatabase::GetAutofillableLogins(
std::vector<std::unique_ptr<PasswordForm>>* forms) {
TRACE_EVENT0("passwords", "LoginDatabase::GetAutofillableLogins");
......
......@@ -148,6 +148,11 @@ class LoginDatabase : public PasswordStoreSync::MetadataStore {
FormRetrievalResult GetAllLogins(PrimaryKeyToFormMap* key_to_form_map)
WARN_UNUSED_RESULT;
// Gets the complete list of all compromised credentials for the password form
// with primary key `parent_key`.
std::vector<CompromisedCredentials> GetCompromisedCredentials(
FormPrimaryKey parent_key) WARN_UNUSED_RESULT;
// Gets the complete list of not blocklisted credentials.
bool GetAutofillableLogins(std::vector<std::unique_ptr<PasswordForm>>* forms)
WARN_UNUSED_RESULT;
......
......@@ -121,6 +121,8 @@ class MockPasswordStore : public PasswordStore {
MOCK_METHOD0(RollbackTransaction, void());
MOCK_METHOD0(CommitTransaction, bool());
MOCK_METHOD1(ReadAllLogins, FormRetrievalResult(PrimaryKeyToFormMap*));
MOCK_METHOD1(ReadSecurityIssues,
std::vector<CompromisedCredentials>(FormPrimaryKey));
MOCK_METHOD1(RemoveLoginByPrimaryKeySync, PasswordStoreChangeList(int));
MOCK_METHOD0(GetMetadataStore, PasswordStoreSync::MetadataStore*());
MOCK_CONST_METHOD0(IsAccountStore, bool());
......
......@@ -323,6 +323,13 @@ FormRetrievalResult PasswordStoreImpl::ReadAllLogins(
return login_db_->GetAllLogins(key_to_form_map);
}
std::vector<CompromisedCredentials> PasswordStoreImpl::ReadSecurityIssues(
FormPrimaryKey parent_key) {
if (!login_db_)
return {};
return login_db_->GetCompromisedCredentials(parent_key);
}
PasswordStoreChangeList PasswordStoreImpl::RemoveLoginByPrimaryKeySync(
int primary_key) {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
......
......@@ -99,6 +99,8 @@ class PasswordStoreImpl : public PasswordStore {
bool CommitTransaction() override;
FormRetrievalResult ReadAllLogins(
PrimaryKeyToFormMap* key_to_form_map) override;
std::vector<CompromisedCredentials> ReadSecurityIssues(
FormPrimaryKey parent_key) override;
PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
PasswordStoreSync::MetadataStore* GetMetadataStore() override;
bool IsAccountStore() const override;
......
......@@ -23,6 +23,7 @@ namespace password_manager {
struct CompromisedCredentials;
struct PasswordForm;
using FormPrimaryKey = base::StrongAlias<class FormPrimaryKeyTag, int>;
using PrimaryKeyToFormMap = std::map<int, std::unique_ptr<PasswordForm>>;
// This enum is used to determine result status when deleting undecryptable
......@@ -123,6 +124,10 @@ class PasswordStoreSync {
virtual FormRetrievalResult ReadAllLogins(
PrimaryKeyToFormMap* key_to_form_map) WARN_UNUSED_RESULT = 0;
// Returns compromised credentials for the provided |parent_key|.
virtual std::vector<CompromisedCredentials> ReadSecurityIssues(
FormPrimaryKey parent_key) = 0;
// Deletes logins that cannot be decrypted.
virtual DatabaseCleanupResult DeleteUndecryptableLogins() = 0;
......
......@@ -271,6 +271,10 @@ class MockPasswordStoreSync : public PasswordStoreSync {
ReadAllLogins,
(PrimaryKeyToFormMap*),
(override));
MOCK_METHOD(std::vector<CompromisedCredentials>,
ReadSecurityIssues,
(FormPrimaryKey),
(override));
MOCK_METHOD(PasswordStoreChangeList,
RemoveLoginByPrimaryKeySync,
(int),
......
......@@ -422,6 +422,12 @@ FormRetrievalResult TestPasswordStore::ReadAllLogins(
return FormRetrievalResult::kDbError;
}
std::vector<CompromisedCredentials> TestPasswordStore::ReadSecurityIssues(
FormPrimaryKey parent_key) {
NOTIMPLEMENTED();
return std::vector<CompromisedCredentials>();
}
PasswordStoreChangeList TestPasswordStore::RemoveLoginByPrimaryKeySync(
int primary_key) {
NOTIMPLEMENTED();
......
......@@ -141,6 +141,8 @@ class TestPasswordStore : public PasswordStore {
bool CommitTransaction() override;
FormRetrievalResult ReadAllLogins(
PrimaryKeyToFormMap* key_to_form_map) override;
std::vector<CompromisedCredentials> ReadSecurityIssues(
FormPrimaryKey parent_key) override;
PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
PasswordStoreSync::MetadataStore* GetMetadataStore() override;
bool IsAccountStore() const override;
......
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