| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/password_manager/core/browser/login_database.h" | 5 #include "components/password_manager/core/browser/login_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 // You *must* change LoginTableColumns if this query changes. | 570 // You *must* change LoginTableColumns if this query changes. |
| 571 const std::string sql_query = "SELECT origin_url, action_url, " | 571 const std::string sql_query = "SELECT origin_url, action_url, " |
| 572 "username_element, username_value, " | 572 "username_element, username_value, " |
| 573 "password_element, password_value, submit_element, " | 573 "password_element, password_value, submit_element, " |
| 574 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " | 574 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " |
| 575 "scheme, password_type, possible_usernames, times_used, form_data, " | 575 "scheme, password_type, possible_usernames, times_used, form_data, " |
| 576 "use_additional_auth, date_synced, display_name, avatar_url, " | 576 "use_additional_auth, date_synced, display_name, avatar_url, " |
| 577 "federation_url, is_zero_click FROM logins WHERE signon_realm == ? "; | 577 "federation_url, is_zero_click FROM logins WHERE signon_realm == ? "; |
| 578 sql::Statement s; | 578 sql::Statement s; |
| 579 const GURL signon_realm(form.signon_realm); | 579 const GURL signon_realm(form.signon_realm); |
| 580 std::string registered_domain = | 580 std::string registered_domain = GetRegistryControlledDomain(signon_realm); |
| 581 PSLMatchingHelper::GetRegistryControlledDomain(signon_realm); | 581 PSLDomainMatchMetric psl_domain_match_metric = PSL_DOMAIN_MATCH_NONE; |
| 582 PSLMatchingHelper::PSLDomainMatchMetric psl_domain_match_metric = | 582 const bool should_PSL_matching_apply = |
| 583 PSLMatchingHelper::PSL_DOMAIN_MATCH_NONE; | 583 ShouldPSLDomainMatchingApply(registered_domain); |
| 584 // PSL matching only applies to HTML forms. | 584 // PSL matching only applies to HTML forms. |
| 585 if (form.scheme == PasswordForm::SCHEME_HTML && | 585 if (form.scheme == PasswordForm::SCHEME_HTML && should_PSL_matching_apply) { |
| 586 psl_helper_.ShouldPSLDomainMatchingApply(registered_domain)) { | |
| 587 // We are extending the original SQL query with one that includes more | 586 // We are extending the original SQL query with one that includes more |
| 588 // possible matches based on public suffix domain matching. Using a regexp | 587 // possible matches based on public suffix domain matching. Using a regexp |
| 589 // here is just an optimization to not have to parse all the stored entries | 588 // here is just an optimization to not have to parse all the stored entries |
| 590 // in the |logins| table. The result (scheme, domain and port) is verified | 589 // in the |logins| table. The result (scheme, domain and port) is verified |
| 591 // further down using GURL. See the functions SchemeMatches, | 590 // further down using GURL. See the functions SchemeMatches, |
| 592 // RegistryControlledDomainMatches and PortMatches. | 591 // RegistryControlledDomainMatches and PortMatches. |
| 593 const std::string extended_sql_query = | 592 const std::string extended_sql_query = |
| 594 sql_query + "OR signon_realm REGEXP ? "; | 593 sql_query + "OR signon_realm REGEXP ? "; |
| 595 // TODO(nyquist) Re-enable usage of GetCachedStatement when | 594 // TODO(nyquist) Re-enable usage of GetCachedStatement when |
| 596 // http://crbug.com/248608 is fixed. | 595 // http://crbug.com/248608 is fixed. |
| 597 s.Assign(db_.GetUniqueStatement(extended_sql_query.c_str())); | 596 s.Assign(db_.GetUniqueStatement(extended_sql_query.c_str())); |
| 598 // We need to escape . in the domain. Since the domain has already been | 597 // We need to escape . in the domain. Since the domain has already been |
| 599 // sanitized using GURL, we do not need to escape any other characters. | 598 // sanitized using GURL, we do not need to escape any other characters. |
| 600 base::ReplaceChars(registered_domain, ".", "\\.", ®istered_domain); | 599 base::ReplaceChars(registered_domain, ".", "\\.", ®istered_domain); |
| 601 std::string scheme = signon_realm.scheme(); | 600 std::string scheme = signon_realm.scheme(); |
| 602 // We need to escape . in the scheme. Since the scheme has already been | 601 // We need to escape . in the scheme. Since the scheme has already been |
| 603 // sanitized using GURL, we do not need to escape any other characters. | 602 // sanitized using GURL, we do not need to escape any other characters. |
| 604 // The scheme soap.beep is an example with '.'. | 603 // The scheme soap.beep is an example with '.'. |
| 605 base::ReplaceChars(scheme, ".", "\\.", &scheme); | 604 base::ReplaceChars(scheme, ".", "\\.", &scheme); |
| 606 const std::string port = signon_realm.port(); | 605 const std::string port = signon_realm.port(); |
| 607 // For a signon realm such as http://foo.bar/, this regexp will match | 606 // For a signon realm such as http://foo.bar/, this regexp will match |
| 608 // domains on the form http://foo.bar/, http://www.foo.bar/, | 607 // domains on the form http://foo.bar/, http://www.foo.bar/, |
| 609 // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/. | 608 // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/. |
| 610 // The scheme and port has to be the same as the observed form. | 609 // The scheme and port has to be the same as the observed form. |
| 611 std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" + | 610 std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" + |
| 612 registered_domain + "(:" + port + ")?\\/$"; | 611 registered_domain + "(:" + port + ")?\\/$"; |
| 613 s.BindString(0, form.signon_realm); | 612 s.BindString(0, form.signon_realm); |
| 614 s.BindString(1, regexp); | 613 s.BindString(1, regexp); |
| 615 } else { | 614 } else { |
| 616 psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_DISABLED; | 615 psl_domain_match_metric = PSL_DOMAIN_MATCH_NOT_USED; |
| 617 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, sql_query.c_str())); | 616 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, sql_query.c_str())); |
| 618 s.BindString(0, form.signon_realm); | 617 s.BindString(0, form.signon_realm); |
| 619 } | 618 } |
| 620 | 619 |
| 621 while (s.Step()) { | 620 while (s.Step()) { |
| 622 scoped_ptr<PasswordForm> new_form(new PasswordForm()); | 621 scoped_ptr<PasswordForm> new_form(new PasswordForm()); |
| 623 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); | 622 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); |
| 624 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) | 623 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) |
| 625 return false; | 624 return false; |
| 626 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) | 625 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) |
| 627 continue; | 626 continue; |
| 628 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); | 627 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); |
| 629 if (psl_helper_.IsMatchingEnabled()) { | 628 if (should_PSL_matching_apply) { |
| 630 if (!PSLMatchingHelper::IsPublicSuffixDomainMatch(new_form->signon_realm, | 629 if (!IsPublicSuffixDomainMatch(new_form->signon_realm, |
| 631 form.signon_realm)) { | 630 form.signon_realm)) { |
| 632 // The database returned results that should not match. Skipping result. | 631 // The database returned results that should not match. Skipping result. |
| 633 continue; | 632 continue; |
| 634 } | 633 } |
| 635 if (form.signon_realm != new_form->signon_realm) { | 634 if (form.signon_realm != new_form->signon_realm) { |
| 636 // Ignore non-HTML matches. | 635 // Ignore non-HTML matches. |
| 637 if (new_form->scheme != PasswordForm::SCHEME_HTML) | 636 if (new_form->scheme != PasswordForm::SCHEME_HTML) |
| 638 continue; | 637 continue; |
| 639 | 638 |
| 640 psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_FOUND; | 639 psl_domain_match_metric = PSL_DOMAIN_MATCH_FOUND; |
| 641 // This is not a perfect match, so we need to create a new valid result. | 640 // This is not a perfect match, so we need to create a new valid result. |
| 642 // We do this by copying over origin, signon realm and action from the | 641 // We do this by copying over origin, signon realm and action from the |
| 643 // observed form and setting the original signon realm to what we found | 642 // observed form and setting the original signon realm to what we found |
| 644 // in the database. We use the fact that |original_signon_realm| is | 643 // in the database. We use the fact that |original_signon_realm| is |
| 645 // non-empty to communicate that this match was found using public | 644 // non-empty to communicate that this match was found using public |
| 646 // suffix matching. | 645 // suffix matching. |
| 647 new_form->original_signon_realm = new_form->signon_realm; | 646 new_form->original_signon_realm = new_form->signon_realm; |
| 648 new_form->origin = form.origin; | 647 new_form->origin = form.origin; |
| 649 new_form->signon_realm = form.signon_realm; | 648 new_form->signon_realm = form.signon_realm; |
| 650 new_form->action = form.action; | 649 new_form->action = form.action; |
| 651 } | 650 } |
| 652 } | 651 } |
| 653 forms->push_back(new_form.release()); | 652 forms->push_back(new_form.release()); |
| 654 } | 653 } |
| 655 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", | 654 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", |
| 656 psl_domain_match_metric, | 655 psl_domain_match_metric, |
| 657 PSLMatchingHelper::PSL_DOMAIN_MATCH_COUNT); | 656 PSL_DOMAIN_MATCH_COUNT); |
| 658 return s.Succeeded(); | 657 return s.Succeeded(); |
| 659 } | 658 } |
| 660 | 659 |
| 661 bool LoginDatabase::GetLoginsCreatedBetween( | 660 bool LoginDatabase::GetLoginsCreatedBetween( |
| 662 const base::Time begin, | 661 const base::Time begin, |
| 663 const base::Time end, | 662 const base::Time end, |
| 664 std::vector<autofill::PasswordForm*>* forms) const { | 663 std::vector<autofill::PasswordForm*>* forms) const { |
| 665 DCHECK(forms); | 664 DCHECK(forms); |
| 666 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, | 665 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, |
| 667 "SELECT origin_url, action_url, " | 666 "SELECT origin_url, action_url, " |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 | 762 |
| 764 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { | 763 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
| 765 DCHECK(db_.is_open()); | 764 DCHECK(db_.is_open()); |
| 766 meta_table_.Reset(); | 765 meta_table_.Reset(); |
| 767 db_.Close(); | 766 db_.Close(); |
| 768 sql::Connection::Delete(db_path_); | 767 sql::Connection::Delete(db_path_); |
| 769 return Init(db_path_); | 768 return Init(db_path_); |
| 770 } | 769 } |
| 771 | 770 |
| 772 } // namespace password_manager | 771 } // namespace password_manager |
| OLD | NEW |